|
18 | 18 | import pyscf.ao2mo
|
19 | 19 | import pyscf.tools
|
20 | 20 | from opt_einsum import contract
|
21 |
| -from pyscf.fci.direct_nosym import absorb_h1e, contract_1e, contract_2e, make_hdiag |
| 21 | +from pyscf.fci.direct_nosym import absorb_h1e, contract_2e, make_hdiag |
22 | 22 | from scipy.sparse.linalg import LinearOperator
|
23 | 23 | from typing_extensions import deprecated
|
24 | 24 |
|
@@ -122,34 +122,22 @@ def rotated(self, orbital_rotation: np.ndarray) -> MolecularHamiltonian:
|
122 | 122 |
|
123 | 123 | def _linear_operator_(self, norb: int, nelec: tuple[int, int]) -> LinearOperator:
|
124 | 124 | """Return a SciPy LinearOperator representing the object."""
|
125 |
| - if np.iscomplexobj(self.two_body_tensor): |
126 |
| - raise NotImplementedError( |
127 |
| - "This Hamiltonian has a complex-valued two-body tensor. " |
128 |
| - "LinearOperator support for complex two-body tensors is not yet " |
129 |
| - "implemented. See https://github.com/qiskit-community/ffsim/issues/81." |
130 |
| - ) |
131 |
| - |
132 | 125 | n_alpha, n_beta = nelec
|
133 | 126 | linkstr_index_a = gen_linkstr_index(range(norb), n_alpha)
|
134 | 127 | linkstr_index_b = gen_linkstr_index(range(norb), n_beta)
|
135 | 128 | link_index = (linkstr_index_a, linkstr_index_b)
|
| 129 | + two_body = absorb_h1e( |
| 130 | + self.one_body_tensor, self.two_body_tensor, norb, nelec, 0.5 |
| 131 | + ) |
136 | 132 |
|
137 |
| - if np.iscomplexobj(self.one_body_tensor): |
138 |
| - return _linear_operator_complex( |
139 |
| - one_body_tensor=self.one_body_tensor, |
140 |
| - two_body_tensor=self.two_body_tensor, |
141 |
| - constant=self.constant, |
142 |
| - norb=norb, |
143 |
| - nelec=nelec, |
144 |
| - link_index=link_index, |
145 |
| - ) |
146 |
| - return _linear_operator_real( |
147 |
| - one_body_tensor=self.one_body_tensor, |
148 |
| - two_body_tensor=self.two_body_tensor, |
149 |
| - constant=self.constant, |
150 |
| - norb=norb, |
151 |
| - nelec=nelec, |
152 |
| - link_index=link_index, |
| 133 | + def matvec(vec: np.ndarray): |
| 134 | + result = self.constant * vec.astype(complex, copy=False) |
| 135 | + result += contract_2e(two_body, vec, norb, nelec, link_index=link_index) |
| 136 | + return result |
| 137 | + |
| 138 | + dim_ = dim(norb, nelec) |
| 139 | + return LinearOperator( |
| 140 | + shape=(dim_, dim_), matvec=matvec, rmatvec=matvec, dtype=complex |
153 | 141 | )
|
154 | 142 |
|
155 | 143 | def _diag_(self, norb: int, nelec: tuple[int, int]) -> np.ndarray:
|
@@ -203,57 +191,3 @@ def _approx_eq_(self, other, rtol: float, atol: float) -> bool:
|
203 | 191 | return False
|
204 | 192 | return True
|
205 | 193 | return NotImplemented
|
206 |
| - |
207 |
| - |
208 |
| -def _linear_operator_complex( |
209 |
| - one_body_tensor: np.ndarray, |
210 |
| - two_body_tensor: np.ndarray, |
211 |
| - constant: float, |
212 |
| - norb: int, |
213 |
| - nelec: tuple[int, int], |
214 |
| - link_index: tuple[np.ndarray, np.ndarray], |
215 |
| -): |
216 |
| - two_body = absorb_h1e(one_body_tensor.real, two_body_tensor, norb, nelec, 0.5) |
217 |
| - dim_ = dim(norb, nelec) |
218 |
| - |
219 |
| - def matvec(vec: np.ndarray): |
220 |
| - result = constant * vec.astype(complex, copy=False) |
221 |
| - result += 1j * contract_1e( |
222 |
| - one_body_tensor.imag, vec.real, norb, nelec, link_index=link_index |
223 |
| - ) |
224 |
| - result -= contract_1e( |
225 |
| - one_body_tensor.imag, vec.imag, norb, nelec, link_index=link_index |
226 |
| - ) |
227 |
| - result += contract_2e(two_body, vec.real, norb, nelec, link_index=link_index) |
228 |
| - result += 1j * contract_2e( |
229 |
| - two_body, vec.imag, norb, nelec, link_index=link_index |
230 |
| - ) |
231 |
| - return result |
232 |
| - |
233 |
| - return LinearOperator( |
234 |
| - shape=(dim_, dim_), matvec=matvec, rmatvec=matvec, dtype=complex |
235 |
| - ) |
236 |
| - |
237 |
| - |
238 |
| -def _linear_operator_real( |
239 |
| - one_body_tensor: np.ndarray, |
240 |
| - two_body_tensor: np.ndarray, |
241 |
| - constant: float, |
242 |
| - norb: int, |
243 |
| - nelec: tuple[int, int], |
244 |
| - link_index: tuple[np.ndarray, np.ndarray], |
245 |
| -): |
246 |
| - two_body = absorb_h1e(one_body_tensor, two_body_tensor, norb, nelec, 0.5) |
247 |
| - dim_ = dim(norb, nelec) |
248 |
| - |
249 |
| - def matvec(vec: np.ndarray): |
250 |
| - result = constant * vec.astype(complex, copy=False) |
251 |
| - result += contract_2e(two_body, vec.real, norb, nelec, link_index=link_index) |
252 |
| - result += 1j * contract_2e( |
253 |
| - two_body, vec.imag, norb, nelec, link_index=link_index |
254 |
| - ) |
255 |
| - return result |
256 |
| - |
257 |
| - return LinearOperator( |
258 |
| - shape=(dim_, dim_), matvec=matvec, rmatvec=matvec, dtype=complex |
259 |
| - ) |
0 commit comments