Perform targeted sparse eigenvector search for selected subproblem. This routine finds a subset of eigenvectors near the specified target. Parameters ---------- subproblem : Subproblem object Subproblem for which to solve the EVP. N : int
(self, subproblem, N, target, rebuild_matrices=False, left=False, normalize_left=True, raise_on_mismatch=True, v0=None, **kw)
| 223 | self.eigenvectors = sp.pre_right @ pre_eigenvectors |
| 224 | |
| 225 | def solve_sparse(self, subproblem, N, target, rebuild_matrices=False, left=False, normalize_left=True, raise_on_mismatch=True, v0=None, **kw): |
| 226 | """ |
| 227 | Perform targeted sparse eigenvector search for selected subproblem. |
| 228 | This routine finds a subset of eigenvectors near the specified target. |
| 229 | |
| 230 | Parameters |
| 231 | ---------- |
| 232 | subproblem : Subproblem object |
| 233 | Subproblem for which to solve the EVP. |
| 234 | N : int |
| 235 | Number of eigenvectors to solve for. Note: the dense method may |
| 236 | be more efficient for finding large numbers of eigenvectors. |
| 237 | target : complex |
| 238 | Target eigenvalue for search. |
| 239 | rebuild_matrices : bool, optional |
| 240 | Rebuild LHS matrices if coefficients have changed (default: False). |
| 241 | left : bool, optional |
| 242 | Solve for the left eigenvectors of the system in addition to the |
| 243 | right eigenvectors. The left eigenvectors are the right eigenvectors |
| 244 | of the conjugate-transposed problem. Follows same definition described |
| 245 | in scipy.linalg.eig documentation (default: False). |
| 246 | normalize_left : bool, optional |
| 247 | Normalize the left eigenvectors such that the modified left eigenvectors |
| 248 | form a biorthonormal (not just biorthogonal) set with respect to the right |
| 249 | eigenvectors (default: True). |
| 250 | raise_on_mismatch : bool, optional |
| 251 | Raise a RuntimeError if the left and right eigenvalues do not match (default: True). |
| 252 | v0 : ndarray, optional |
| 253 | Initial guess for eigenvector, e.g. from subsystem.gather (default: None). |
| 254 | **kw : |
| 255 | Other keyword options passed to scipy.sparse.linalg.eig. |
| 256 | """ |
| 257 | self.eigenvalue_subproblem = sp = subproblem |
| 258 | # Build matrices if directed or not yet built |
| 259 | if rebuild_matrices or not hasattr(sp, 'L_min'): |
| 260 | self.build_matrices([sp], ['M', 'L']) |
| 261 | # Solve as sparse general eigenvalue problem |
| 262 | A = sp.L_min |
| 263 | B = - sp.M_min |
| 264 | # Precondition starting guess if provided |
| 265 | if v0 is not None: |
| 266 | v0 = sp.pre_right_pinv @ v0 |
| 267 | # Solve for the right (and optionally left) eigenvectors |
| 268 | eig_output = scipy_sparse_eigs(A=A, B=B, left=left, N=N, target=target, matsolver=self.matsolver, v0=v0, **kw) |
| 269 | if left: |
| 270 | # Note: this definition of "left eigenvectors" is consistent with the documentation for scipy.linalg.eig |
| 271 | self.eigenvalues, pre_right_evecs, self.left_eigenvalues, pre_left_evecs = eig_output |
| 272 | self.right_eigenvectors = self.eigenvectors = sp.pre_right @ pre_right_evecs |
| 273 | self.left_eigenvectors = sp.pre_left.conj().T @ pre_left_evecs |
| 274 | self.modified_left_eigenvectors = (sp.M_min @ sp.pre_right_pinv).conj().T @ pre_left_evecs |
| 275 | # Check that eigenvalues match |
| 276 | if not np.allclose(self.eigenvalues, np.conjugate(self.left_eigenvalues)): |
| 277 | if raise_on_mismatch: |
| 278 | raise RuntimeError("Conjugate of left eigenvalues does not match right eigenvalues. " |
| 279 | "The full sets of left and right vectors won't form a biorthogonal set. " |
| 280 | "This error can be disabled by passing raise_on_mismatch=False to " |
| 281 | "solve_sparse().") |
| 282 | else: |