diff --git a/examples/36-tddft-ris-grad-opt.py b/examples/36-tddft-ris-grad-opt.py new file mode 100644 index 00000000..03c70b03 --- /dev/null +++ b/examples/36-tddft-ris-grad-opt.py @@ -0,0 +1,64 @@ +# Copyright 2021-2025 The PySCF Developers. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +''' +TDDFT-ris excited state gradient and geometry optimization +''' + +import pyscf +import gpu4pyscf.tdscf.ris as ris +from gpu4pyscf.dft import rks +from pyscf.geomopt.geometric_solver import optimize + +atom = """ +O 0.0000000000 0.0000000000 0.0000000000 +H 0.0000000000 -0.7570000000 0.5870000000 +H 0.0000000000 0.7570000000 0.5870000000 +""" + +bas0 = "ccpvdz" + +mol = pyscf.M( + atom=atom, basis=bas0, max_memory=32000) +mf = rks.RKS(mol, xc='b3lyp').to_gpu() +mf.kernel() +td_ris = ris.TDDFT(mf=mf, nstates=5, spectra=False, single=False, GS=True) +td_ris.conv_tol = 1.0E-4 +td_ris.Ktrunc = 0.0 +td_ris.kernel() + +""" +TDDFT-ris excited state geometry optimization +1st usage +""" +mol_gpu = optimize(td_ris) +mff = rks.RKS(mol_gpu, xc='b3lyp').to_gpu() +mff.kernel() +tdf_ris = ris.TDDFT(mf=mff, nstates=5, spectra=False, single=False, GS=True) +tdf_ris.conv_tol = 1.0E-4 +tdf_ris.Ktrunc = 0.0 +output = tdf_ris.kernel() + +""" +TDDFT-ris excited state geometry optimization +2nd usage +""" +excited_grad = td_ris.nuc_grad_method().as_scanner(state=1) +mol_gpu = excited_grad.optimizer().kernel() + +""" +TDDFT-ris excited state gradient +""" +excited_gradf_ris = tdf_ris.nuc_grad_method() +excited_gradf_ris.kernel() diff --git a/gpu4pyscf/grad/tdrks_ris.py b/gpu4pyscf/grad/tdrks_ris.py index 3bf029d6..116dfff9 100644 --- a/gpu4pyscf/grad/tdrks_ris.py +++ b/gpu4pyscf/grad/tdrks_ris.py @@ -16,16 +16,14 @@ from functools import reduce import cupy as cp import numpy as np -from pyscf import lib +from pyscf import lib, gto from gpu4pyscf.lib import logger -from gpu4pyscf.lib.cupy_helper import contract, add_sparse, tag_array +from gpu4pyscf.lib.cupy_helper import contract, tag_array from gpu4pyscf.df import int3c2e from gpu4pyscf.df.grad import tdrhf as tdrhf_df -from gpu4pyscf.dft import numint,rks -from pyscf.dft.numint import NumInt as numint_cpu +from gpu4pyscf.dft import rks from gpu4pyscf.scf import cphf from gpu4pyscf.grad import rhf as rhf_grad -from gpu4pyscf.grad import rks as rks_grad from gpu4pyscf.grad import tdrhf from gpu4pyscf.grad import tdrks from gpu4pyscf import tdscf @@ -305,6 +303,7 @@ def fvind(x): def get_extra_force(atom_id, envs): return envs['dvhf'].aux[atom_id] + def get_veff_ris(mf_J, mf_K, mol=None, dm=None, j_factor=1.0, k_factor=1.0, omega=0.0, hermi=0, verbose=None): if omega != 0.0: @@ -341,10 +340,10 @@ def kernel(self, xy=None, state=None, singlet=None, atmlst=None): "state=0 found in the input. Gradients of ground state is computed.", ) return self.base._scf.nuc_grad_method().kernel(atmlst=atmlst) - if self.base.xy is not None: + if self.base.xy[1] is not None: xy = (self.base.xy[0][state-1]*np.sqrt(0.5), self.base.xy[1][state-1]*np.sqrt(0.5)) else: - xy = (self.base.X[state-1]*np.sqrt(0.5), self.base.X[state-1]*0.0) + xy = (self.base.xy[0][state-1]*np.sqrt(0.5), self.base.xy[0][state-1]*0.0) if singlet is None: singlet = self.base.singlet diff --git a/gpu4pyscf/grad/tests/test_tddft_ris_grad.py b/gpu4pyscf/grad/tests/test_tddft_ris_grad.py index 2e513dca..76a9b230 100644 --- a/gpu4pyscf/grad/tests/test_tddft_ris_grad.py +++ b/gpu4pyscf/grad/tests/test_tddft_ris_grad.py @@ -207,7 +207,7 @@ def test_grad_b3lyp_tda_singlet_ref(self): mf = dft.RKS(mol, xc='b3lyp').to_gpu() mf.kernel() - td = ris.TDDFT(mf=mf, nstates=5, spectra=True, single=False) + td = ris.TDDFT(mf=mf, nstates=5, spectra=False, single=False, gram_schmidt=True) td.conv_tol = 1.0E-4 td.Ktrunc = 0.0 td.kernel() diff --git a/gpu4pyscf/grad/tests/test_tddft_ris_opt.py b/gpu4pyscf/grad/tests/test_tddft_ris_opt.py new file mode 100644 index 00000000..7ac6d555 --- /dev/null +++ b/gpu4pyscf/grad/tests/test_tddft_ris_opt.py @@ -0,0 +1,93 @@ +# Copyright 2021-2025 The PySCF Developers. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pyscf +import numpy as np +import unittest +import pytest +from pyscf import dft +from pyscf.geomopt.geometric_solver import optimize +import gpu4pyscf.tdscf.ris as ris + +atom = """ +H 1.2953527433 -0.4895463266 0.8457608681 +C 0.6689912970 -0.0128659340 0.0499408027 +H 1.3504336752 0.5361460613 -0.6478375784 +C -0.6690192526 -0.0870427249 -0.0501820705 +H -1.4008634673 0.6483035475 0.3700152345 +H -1.2449949956 -0.8949946232 -0.5680972562 +""" + +bas0 = "def2tzvp" + +def setUpModule(): + global mol + mol = pyscf.M( + atom=atom, basis=bas0, max_memory=32000, output="/dev/null", verbose=1) + + +def tearDownModule(): + global mol + mol.stdout.close() + del mol + +class KnownValues(unittest.TestCase): + def test_opt_rks_tda_1(self): + mf = dft.RKS(mol, xc='pbe0').to_gpu() + mf.kernel() + assert mf.converged + td_ris = ris.TDA(mf=mf, nstates=5, spectra=False, single=False, gram_schmidt=True) + td_ris.conv_tol = 1.0E-5 + td_ris.Ktrunc = 0.0 + td_ris.kernel() + mol_gpu = optimize(td_ris) + + mff = dft.RKS(mol_gpu, xc='pbe0').to_gpu() + mff.kernel() + assert mff.converged + tdf_ris = ris.TDA(mf=mff, nstates=5, spectra=False, single=False, gram_schmidt=True) + tdf_ris.conv_tol = 1.0E-5 + tdf_ris.Ktrunc = 0.0 + tdf_ris.kernel() + excited_gradf_ris = tdf_ris.nuc_grad_method() + excited_gradf_ris.kernel() + assert np.linalg.norm(excited_gradf_ris.de) < 3.0e-4 + + def test_opt_rks_tda_2(self): + mf = dft.RKS(mol, xc='pbe0').to_gpu() + mf.kernel() + assert mf.converged + td_ris = ris.TDA(mf=mf, nstates=5, spectra=False, single=False, gram_schmidt=True) + td_ris.conv_tol = 1.0E-5 + td_ris.Ktrunc = 0.0 + td_ris.kernel() + + excited_grad = td_ris.nuc_grad_method().as_scanner(state=1) + mol_gpu = excited_grad.optimizer().kernel() + + mff = dft.RKS(mol_gpu, xc='pbe0').to_gpu() + mff.kernel() + assert mff.converged + tdf_ris = ris.TDA(mf=mff, nstates=5, spectra=False, single=False, gram_schmidt=True) + tdf_ris.conv_tol = 1.0E-5 + tdf_ris.Ktrunc = 0.0 + tdf_ris.kernel() + excited_gradf_ris = tdf_ris.nuc_grad_method() + excited_gradf_ris.kernel() + assert np.linalg.norm(excited_gradf_ris.de) < 3.0e-4 + + +if __name__ == "__main__": + print("Full Tests for geomtry optimization for excited states using TDDFT-ris.") + unittest.main() \ No newline at end of file diff --git a/gpu4pyscf/tdscf/_krylov_tools.py b/gpu4pyscf/tdscf/_krylov_tools.py index aa6ba768..3e50ee19 100644 --- a/gpu4pyscf/tdscf/_krylov_tools.py +++ b/gpu4pyscf/tdscf/_krylov_tools.py @@ -478,6 +478,7 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue', if ii == max_iter - 1 and max_norm >= conv_tol: log.warn(f'=== Warning: {problem_type.capitalize()} solver not converged below {conv_tol:.2e} ===') log.warn(f'Current residual norms: {r_norms.tolist()}') + converged = r_norms < conv_tol log.info(f'Finished in {ii+1} steps') log.info(f'Maximum residual norm = {max_norm:.2e}') log.info(f'Final subspace size = {sub_A.shape[0]}') @@ -497,9 +498,9 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue', log.info(f'========== {problem_type.capitalize()} Solver Done ==========') if problem_type == 'eigenvalue': - return omega, full_X + return converged, omega, full_X elif problem_type in ['linear', 'shifted_linear']: - return full_X + return converged, full_X def nested_krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue', rhs=None, omega_shift=None, n_states=20, conv_tol=1e-5, @@ -626,15 +627,15 @@ def matrix_vector_product(x): hdiag = cp.diag(A) - eigenvalues, eigenvecters = krylov_solver(matrix_vector_product=matrix_vector_product, hdiag=hdiag, + _, eigenvalues, eigenvecters = krylov_solver(matrix_vector_product=matrix_vector_product, hdiag=hdiag, problem_type='eigenvalue', n_states=5, conv_tol=1e-5, max_iter=35,gram_schmidt=True, verbose=5, single=False) - solution_vectors = krylov_solver(matrix_vector_product=matrix_vector_product, hdiag=hdiag, + _, solution_vectors = krylov_solver(matrix_vector_product=matrix_vector_product, hdiag=hdiag, problem_type='linear', rhs=rhs, conv_tol=1e-5, max_iter=35,gram_schmidt=True, verbose=5, single=False) - solution_vectors_shifted = krylov_solver(matrix_vector_product=matrix_vector_product, hdiag=hdiag, + _, solution_vectors_shifted = krylov_solver(matrix_vector_product=matrix_vector_product, hdiag=hdiag, problem_type='shifted_linear', rhs=rhs, omega_shift=omega_shift, conv_tol=1e-5, max_iter=35,gram_schmidt=True, verbose=5, single=False) diff --git a/gpu4pyscf/tdscf/_lr_eig.py b/gpu4pyscf/tdscf/_lr_eig.py index 6e44d5af..cd8943f7 100644 --- a/gpu4pyscf/tdscf/_lr_eig.py +++ b/gpu4pyscf/tdscf/_lr_eig.py @@ -1274,6 +1274,7 @@ def Davidson(matrix_vector_product, residual = AV - omega.reshape(-1, 1) * full_X r_norms = cp.linalg.norm(residual, axis=1) + conv = r_norms[:N_states] <= conv_tol max_norm = cp.max(r_norms) log.info(f'iter: {ii+1:<3d} max|R|: {max_norm:<12.2e} subspace: {sub_A.shape[0]:<8d}') if max_norm < conv_tol or ii == (max_iter-1): @@ -1312,7 +1313,7 @@ def Davidson(matrix_vector_product, log.info('========== Davidson Diagonalization Done ==========') - return omega, full_X + return conv, omega, full_X # TODO: merge with real_eig, write a Class of krylov method for Casida problem, allowing ris initial guess/preconditioner def Davidson_Casida(matrix_vector_product, @@ -1509,7 +1510,7 @@ def Davidson_Casida(matrix_vector_product, r_norms = cp.linalg.norm(residual, axis=1) max_norm = cp.max(r_norms) - + conv = r_norms[:N_states] <= conv_tol log.info(f'iter: {ii+1:<3d}, max|R|: {max_norm:<10.2e} subspace_size = {sub_A.shape[0]}') if max_norm < conv_tol or ii == (max_iter -1): @@ -1560,5 +1561,5 @@ def Davidson_Casida(matrix_vector_product, log.info('======= TDDFT Eigen Solver Done =======' ) - return omega, X_full, Y_full + return conv, omega, X_full, Y_full diff --git a/gpu4pyscf/tdscf/ris.py b/gpu4pyscf/tdscf/ris.py index 3bac4fe2..4cebede2 100644 --- a/gpu4pyscf/tdscf/ris.py +++ b/gpu4pyscf/tdscf/ris.py @@ -117,16 +117,10 @@ def get_auxmol(mol, theta=0.2, fitting_basis='s'): parse_arg = False turns off PySCF built-in parsing function ''' - auxmol = gto.M(atom=mol.atom, - basis=mol.basis, - parse_arg=False, - spin=mol.spin, - charge=mol.charge, - cart=mol.cart) - + auxmol = mol.copy() auxmol_basis_keys = mol._basis.keys() auxmol.basis = get_minimal_auxbasis(auxmol_basis_keys, theta, fitting_basis) - auxmol.build(dump_input=False) + auxmol.build(dump_input=False, parse_arg=False) return auxmol @@ -700,6 +694,53 @@ def add_hf_(a, b, hyb=1): return a.get(), b.get() +def as_scanner(td): + if isinstance(td, lib.SinglePointScanner): + return td + + logger.info(td, 'Set %s as a scanner', td.__class__) + name = td.__class__.__name__ + TD_Scanner.__name_mixin__ + return lib.set_class(TD_Scanner(td), (TD_Scanner, td.__class__), name) + + +class TD_Scanner(lib.SinglePointScanner): + def __init__(self, td): + self.__dict__.update(td.__dict__) + self._scf = td._scf.as_scanner() + + def __call__(self, mol_or_geom, **kwargs): + assert self.device == 'gpu' + if isinstance(mol_or_geom, gto.MoleBase): + mol = mol_or_geom + else: + mol = self.mol.set_geom_(mol_or_geom, inplace=False) + + self.reset(mol) + mf_scanner = self._scf + mf_e = mf_scanner(mol) + self.n_occ = None + self.n_vir = None + self.rest_occ = None + self.rest_vir = None + self.C_occ_notrunc = None + self.C_vir_notrunc = None + self.C_occ_Ktrunc = None + self.C_vir_Ktrunc = None + self.delta_hdiag = None + self.hdiag = None + self.eri_tag = None + self.auxmol_J = None + self.auxmol_K = None + self.lower_inv_eri2c_J = None + self.lower_inv_eri2c_K = None + self.RKS = True + self.UKS = False + self.mo_coeff = cp.asarray(self._scf.mo_coeff, dtype=self.dtype) + self.build() + self.kernel() + return mf_e + self.energies/HARTREE2EV + + class RisBase(lib.StreamObject): def __init__(self, mf, theta: float = 0.2, J_fit: str = 'sp', K_fit: str = 's', @@ -750,7 +791,6 @@ def __init__(self, mf, in_ram (bool, optional): Whether to perform calculations in RAM. Defaults to True. verbose (optional): Verbosity level of the logger. If None, it will use the verbosity of `mf`. """ - self.mf = mf self.single = single if single: @@ -788,6 +828,7 @@ def __init__(self, mf, self.verbose = verbose if verbose else mf.verbose self.device = mf.device + self.converged = None self._in_ram = in_ram @@ -850,10 +891,14 @@ def transition_magnetic_dipole(self): mdpol = cp.vstack((mdpol_alpha, mdpol_beta)) return mdpol + @property + def e_tot(self): + '''Excited state energies''' + return self._scf.e_tot + self.energies/HARTREE2EV def get_ab(self, mf=None): if mf is None: - mf = self.mf + mf = self._scf J_fit = self.J_fit K_fit = self.K_fit theta = self.theta @@ -862,7 +907,7 @@ def get_ab(self, mf=None): def build(self): log = self.log log.info(f'nstates: {self.nstates}') - log.info(f'N atoms:{self.mf.mol.natm}') + log.info(f'N atoms:{self._scf.mol.natm}') log.info(f'conv_tol: {self.conv_tol}') log.info(f'max_iter: {self.max_iter}') log.info(f'Ktrunc: {self.Ktrunc}') @@ -892,7 +937,7 @@ def build(self): note: the definition of a_x, α and β is kind of weird in pyscf/libxc ''' - omega, alpha_libxc, hyb_libxc = self.mf._numint.rsh_and_hybrid_coeff(self.mf.xc, spin=self.mf.mol.spin) + omega, alpha_libxc, hyb_libxc = self._scf._numint.rsh_and_hybrid_coeff(self._scf.xc, spin=self._scf.mol.spin) log.info(f'omega, alpha_libxc, hyb_libxc: {omega}, {alpha_libxc}, {hyb_libxc}') if omega > 0: @@ -935,14 +980,14 @@ def build(self): if self.mo_coeff.ndim == 2: self.RKS = True self.UKS = False - n_occ = int(sum(self.mf.mo_occ>0)) - n_vir = int(sum(self.mf.mo_occ==0)) + n_occ = int(sum(self._scf.mo_occ>0)) + n_vir = int(sum(self._scf.mo_occ==0)) self.n_occ = n_occ self.n_vir = n_vir self.C_occ_notrunc = cp.asfortranarray(self.mo_coeff[:,:n_occ]) self.C_vir_notrunc = cp.asfortranarray(self.mo_coeff[:,n_occ:]) - mo_energy = self.mf.mo_energy + mo_energy = self._scf.mo_energy log.info(f'mo_energy.shape: {mo_energy.shape}') vir_ene = mo_energy[n_occ:].reshape(1,n_vir) occ_ene = mo_energy[:n_occ].reshape(n_occ,1) @@ -986,10 +1031,10 @@ def build(self): ''' TODO UKS method ''' self.RKS = False self.UKS = True - self.n_occ_a = sum(self.mf.mo_occ[0]>0) - self.n_vir_a = sum(self.mf.mo_occ[0]==0) - self.n_occ_b = sum(self.mf.mo_occ[1]>0) - self.n_vir_b = sum(self.mf.mo_occ[1]==0) + self.n_occ_a = sum(self._scf.mo_occ[0]>0) + self.n_vir_a = sum(self._scf.mo_occ[0]==0) + self.n_occ_b = sum(self._scf.mo_occ[1]>0) + self.n_vir_b = sum(self._scf.mo_occ[1]==0) log.info('n_occ for alpha spin = {self.n_occ_a}') log.info('n_vir for alpha spin = {self.n_vir_a}') log.info('n_occ for beta spin = {self.n_occ_b}') @@ -1085,6 +1130,13 @@ def nuc_grad_method(self): from gpu4pyscf.grad import tdrks_ris return tdrks_ris.Gradients(self) + def reset(self, mol=None): + if mol is not None: + self.mol = mol + self._scf.reset(mol) + return self + + as_scanner = as_scanner class TDA(RisBase): def __init__(self, mf, **kwargs): @@ -1212,7 +1264,7 @@ def kernel(self): log = self.log TDA_MVP, hdiag = self.gen_vind() - energies, X = _krylov_tools.krylov_solver(matrix_vector_product=TDA_MVP,hdiag=hdiag, n_states=self.nstates, problem_type='eigenvalue', + converged, energies, X = _krylov_tools.krylov_solver(matrix_vector_product=TDA_MVP,hdiag=hdiag, n_states=self.nstates, problem_type='eigenvalue', conv_tol=self.conv_tol, max_iter=self.max_iter, gram_schmidt=self.gram_schmidt, single=self.single, verbose=log) @@ -1220,7 +1272,7 @@ def kernel(self): # conv_tol=self.conv_tol, max_iter=self.max_iter, gram_schmidt=self.gram_schmidt, # single=self.single, verbose=log) # print(energies) - + self.converged = converged log.debug(f'check orthonormality of X: {cp.linalg.norm(cp.dot(X, X.T) - cp.eye(X.shape[0])):.2e}') oscillator_strength, rotatory_strength = spectralib.get_spectra(energies=energies, @@ -1234,7 +1286,7 @@ def kernel(self): log.info(CITATION_INFO) self.energies = energies - self.xy = X + self.xy = (X, None) self.oscillator_strength = oscillator_strength self.rotatory_strength = rotatory_strength @@ -1366,11 +1418,14 @@ def kernel(self): # TODO: UKS - energies, X, Y = _lr_eig.Davidson_Casida(matrix_vector_product=TDDFT_hybrid_MVP, hdiag=hdiag, + conv, energies, X, Y = _lr_eig.Davidson_Casida(matrix_vector_product=TDDFT_hybrid_MVP, hdiag=hdiag, N_states=self.nstates, conv_tol=self.conv_tol, max_iter=self.max_iter, gram_schmidt=self.gram_schmidt, single=self.single, verbose=self.verbose) - + self.converged = conv + if not all(self.converged): + log.info('TD-SCF states %s not converged.', + [i for i, x in enumerate(self.converged) if not x]) elif self.a_x == 0: '''pure TDDFT''' if self.RKS: @@ -1378,9 +1433,13 @@ def kernel(self): elif self.UKS: TDDFT_pure_MVP, hdiag_sq = self.get_UKS_TDDFT_pure_MVP() - energies_sq, Z = _lr_eig.Davidson(matrix_vector_product=TDDFT_pure_MVP, hdiag=hdiag_sq, + conv, energies_sq, Z = _lr_eig.Davidson(matrix_vector_product=TDDFT_pure_MVP, hdiag=hdiag_sq, N_states=self.nstates, conv_tol=self.conv_tol, max_iter=self.max_iter, gram_schmidt=self.gram_schmidt, single=self.single, verbose=self.verbose) + self.converged = conv + if not all(self.converged): + log.info('TD-SCF states %s not converged.', + [i for i, x in enumerate(self.converged) if not x]) energies = energies_sq**0.5 Z = (energies**0.5).reshape(-1,1) * Z @@ -1394,7 +1453,6 @@ def kernel(self): P=self.transition_dipole(), mdpol=self.transition_magnetic_dipole(), name=self.out_name+'_TDDFT_ris', spectra=self.spectra, RKS=self.RKS, print_threshold = self.print_threshold, n_occ=self.n_occ, n_vir=self.n_vir, verbose=self.verbose) - energies = energies*HARTREE2EV log.info(f'energies: {energies}') log.info(f'oscillator strength: {oscillator_strength}') @@ -1480,7 +1538,7 @@ def kernel(self): TDA_MVP, hdiag = self.gen_vind() transition_dipole = self.transition_dipole() - solver = _krylov_tools.krylov_solver(matrix_vector_product=TDA_MVP,hdiag=hdiag, problem_type='linear', + _, solver = _krylov_tools.krylov_solver(matrix_vector_product=TDA_MVP,hdiag=hdiag, problem_type='linear', rhs=-transition_dipole, conv_tol=self.conv_tol, max_iter=self.max_iter, gram_schmidt=self.gram_schmidt, single=self.single, verbose=log) X = solver.run() diff --git a/gpu4pyscf/tdscf/tests/test_krylov.py b/gpu4pyscf/tdscf/tests/test_krylov.py index 55522012..b9176a69 100644 --- a/gpu4pyscf/tdscf/tests/test_krylov.py +++ b/gpu4pyscf/tdscf/tests/test_krylov.py @@ -73,7 +73,7 @@ def tearDownClass(self): def test_krylov_eigenvalue(self): """Test Krylov solver for eigenvalue problem""" - eigenvalues, eigenvectors = krylov_solver( + _, eigenvalues, eigenvectors = krylov_solver( matrix_vector_product=self.matrix_vector_product, hdiag=self.hdiag, problem_type='eigenvalue', @@ -85,7 +85,7 @@ def test_krylov_eigenvalue(self): single=False ) - eigenvalues_single, eigenvectors_single = krylov_solver( + _, eigenvalues_single, eigenvectors_single = krylov_solver( matrix_vector_product=self.matrix_vector_product_single, hdiag=self.hdiag, problem_type='eigenvalue', @@ -124,7 +124,7 @@ def test_krylov_eigenvalue(self): def test_krylov_linear(self): """Test Krylov solver for linear system""" - solution_vectors = krylov_solver( + _, solution_vectors = krylov_solver( matrix_vector_product=self.matrix_vector_product, hdiag=self.hdiag, problem_type='linear', @@ -137,7 +137,7 @@ def test_krylov_linear(self): ) - solution_vectors_single = krylov_solver( + _, solution_vectors_single = krylov_solver( matrix_vector_product=self.matrix_vector_product_single, hdiag=self.hdiag, problem_type='linear', @@ -164,7 +164,7 @@ def test_krylov_linear(self): def test_krylov_shifted_linear(self): """Test Krylov solver for shifted linear system""" - solution_vectors_shifted = krylov_solver( + _, solution_vectors_shifted = krylov_solver( matrix_vector_product=self.matrix_vector_product, hdiag=self.hdiag, problem_type='shifted_linear', @@ -178,7 +178,7 @@ def test_krylov_shifted_linear(self): ) - solution_vectors_shifted_single = krylov_solver( + _, solution_vectors_shifted_single = krylov_solver( matrix_vector_product=self.matrix_vector_product_single, hdiag=self.hdiag, problem_type='shifted_linear',