def test_ao2mo_hand_against_pyscf_rhf_partial(): mol = molecules_pyscf.molecule_physicists_water_sto3g() mol.build() mf = pyscf.scf.RHF(mol) mf.kernel() C = fix_mocoeffs_shape(mf.mo_coeff) occupations = occupations_from_pyscf_mol(mol, C) nocc, nvirt, _, _ = occupations nmo = nocc + nvirt ntransforms = 2 o = slice(0, nocc) v = slice(nocc, nmo) ao2mo = AO2MOpyscf(C, verbose=mol.verbose, pyscfmol=mol) ao2mo.perform_rhf_partial() assert len(ao2mo.tei_mo) == ntransforms tei_mo_ovov_pyscf = ao2mo.tei_mo[0] tei_mo_oovv_pyscf = ao2mo.tei_mo[1] tei_ao = mol.intor("int2e_sph", aosym="s1") print("1. Use the class method explicitly.") tei_mo_ovov_hand = AO2MO.transform( tei_ao, C[0, :, o], C[0, :, v], C[0, :, o], C[0, :, v] ) tei_mo_oovv_hand = AO2MO.transform( tei_ao, C[0, :, o], C[0, :, o], C[0, :, v], C[0, :, v] ) assert tei_mo_ovov_pyscf.shape == tei_mo_ovov_hand.shape == (nocc, nvirt, nocc, nvirt) assert tei_mo_oovv_pyscf.shape == tei_mo_oovv_hand.shape == (nocc, nocc, nvirt, nvirt) np.testing.assert_allclose(tei_mo_ovov_hand, tei_mo_ovov_pyscf, rtol=0, atol=1.0e-15) np.testing.assert_allclose(tei_mo_oovv_hand, tei_mo_oovv_pyscf, rtol=0, atol=1.0e-15) print("2. Use the class method normally.") ao2mo_method = AO2MO(C, occupations, verbose=mol.verbose, I=tei_ao) ao2mo_method.perform_rhf_partial() assert len(ao2mo_method.tei_mo) == ntransforms tei_mo_ovov_method = ao2mo_method.tei_mo[0] tei_mo_oovv_method = ao2mo_method.tei_mo[1] assert ( tei_mo_ovov_pyscf.shape == tei_mo_ovov_method.shape == (nocc, nvirt, nocc, nvirt) ) assert ( tei_mo_oovv_pyscf.shape == tei_mo_oovv_method.shape == (nocc, nocc, nvirt, nvirt) ) np.testing.assert_allclose( tei_mo_ovov_method, tei_mo_ovov_pyscf, rtol=0, atol=1.0e-15 ) np.testing.assert_allclose( tei_mo_oovv_method, tei_mo_oovv_pyscf, rtol=0, atol=1.0e-15 ) return
def test_explicit_rhf_outside_solver_off_diagonal_blocks(): mol = molecules.molecule_water_sto3g() mol.build() mf = pyscf.scf.RHF(mol) mf.kernel() mocoeffs = mf.mo_coeff moenergies = mf.mo_energy ao2mo = AO2MOpyscf(mocoeffs, mol.verbose, mol) ao2mo.perform_rhf_full() tei_mo = ao2mo.tei_mo[0] C = mocoeffs E = np.diag(moenergies) occupations = utils.occupations_from_pyscf_mol(mol, mocoeffs) nocc, nvirt, _, _ = occupations A = eqns.form_rpa_a_matrix_mo_singlet_full(E, tei_mo, nocc) B = eqns.form_rpa_b_matrix_mo_singlet_full(tei_mo, nocc) G = np.block([[A, B], [B, A]]) assert G.shape == (2 * nocc * nvirt, 2 * nocc * nvirt) G_inv = np.linalg.inv(G) components = 3 integrals_dipole_ao = mol.intor("cint1e_r_sph", comp=components) integrals_dipole_mo_ai = [] for component in range(components): integrals_dipole_mo_ai_component = np.dot( C[:, nocc:].T, np.dot(integrals_dipole_ao[component, ...], C[:, :nocc])).reshape(-1, order="F") integrals_dipole_mo_ai.append(integrals_dipole_mo_ai_component) integrals_dipole_mo_ai = np.stack(integrals_dipole_mo_ai, axis=0).T integrals_dipole_mo_ai_super = np.concatenate( (integrals_dipole_mo_ai, -integrals_dipole_mo_ai), axis=0) rhsvecs = integrals_dipole_mo_ai_super rspvecs = np.dot(G_inv, rhsvecs) polarizability = 4 * np.dot(rhsvecs.T, rspvecs) / 2 # pylint: disable=bad-whitespace result__0_00 = np.array([[7.93556221, 0.0, 0.0], [0.0, 3.06821077, 0.0], [0.0, 0.0, 0.05038621]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(polarizability, result__0_00, rtol=rtol, atol=atol)
def test_uncoupled_rhf() -> None: mol = molecules.molecule_trithiolane_sto3g() mol.build() mf = pyscf.scf.RHF(mol) mf.scf() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = occupations_from_pyscf_mol(mol, C) solver = solvers.ExactInv(C, E, occupations) ao2mo = AO2MOpyscf(C, mol.verbose, mol) ao2mo.perform_rhf_partial() solver.tei_mo = ao2mo.tei_mo solver.tei_mo_type = AO2MOTransformationType.partial driver = cphf.CPHF(solver) operator_diplen = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False, triplet=False) integrals_diplen_ao = mol.intor("cint1e_r_sph", comp=3) operator_diplen.ao_integrals = integrals_diplen_ao driver.add_operator(operator_diplen) frequencies = [0.0, 0.0773178, 0.128347] driver.set_frequencies(frequencies) driver.run( hamiltonian=Hamiltonian.RPA, spin=Spin.singlet, program=Program.PySCF, program_obj=mol, ) for idxf, frequency in enumerate(frequencies): print(idxf, frequency) print("uncoupled") diag_res = np.diag(driver.uncoupled_results[idxf]) diag_ref = np.diag(rhf_uncoupled[frequency]["result"]) diff = diag_res - diag_ref print(diag_res) print(diag_ref) print(diff) assert np.max( np.abs(diff)) < rhf_uncoupled[frequency]["error_max_diag"] print("coupled") diag_res = np.diag(driver.results[idxf]) diag_ref = np.diag(rhf_coupled[frequency]["result"]) diff = diag_res - diag_ref print(diag_res) print(diag_ref) print(diff) assert np.max(np.abs(diff)) < rhf_coupled[frequency]["error_max_diag"]
def test_uncoupled_uhf(): mol = molecules.molecule_trithiolane_sto3g() mol.charge = 1 mol.spin = 1 mol.build() mf = pyscf.scf.uhf.UHF(mol) mf.scf() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = utils.occupations_from_pyscf_mol(mol, C) solver = iterators.ExactInv(C, E, occupations) ao2mo = AO2MOpyscf(C, mol.verbose, mol) ao2mo.perform_uhf_partial() solver.tei_mo = ao2mo.tei_mo solver.tei_mo_type = "partial" driver = cphf.CPHF(solver) operator_diplen = operators.Operator( label="dipole", is_imaginary=False, is_spin_dependent=False, triplet=False ) integrals_diplen_ao = mol.intor("cint1e_r_sph", comp=3) operator_diplen.ao_integrals = integrals_diplen_ao driver.add_operator(operator_diplen) frequencies = [0.0, 0.0773178, 0.128347, 0.4556355] driver.set_frequencies(frequencies) driver.run(solver_type="exact", hamiltonian="rpa", spin="singlet") for idxf, frequency in enumerate(frequencies): print(idxf, frequency) print("uncoupled") diag_res = np.diag(driver.uncoupled_results[idxf]) diag_ref = np.diag(uhf_uncoupled[frequency]["result"]) diff = diag_res - diag_ref print(diag_res) print(diag_ref) print(diff) assert np.max(np.abs(diff)) < uhf_uncoupled[frequency]["error_max_diag"] print("coupled") diag_res = np.diag(driver.results[idxf]) diag_ref = np.diag(uhf_coupled[frequency]["result"]) diff = diag_res - diag_ref print(diag_res) print(diag_ref) print(diff) assert np.max(np.abs(diff)) < uhf_coupled[frequency]["error_max_diag"] return
def test_explicit_uhf(): mol = molecules.molecule_water_sto3g() mol.charge = 1 mol.spin = 1 mol.build() mf = pyscf.scf.UHF(mol) mf.kernel() C = np.stack(mf.mo_coeff, axis=0) E_a = np.diag(mf.mo_energy[0]) E_b = np.diag(mf.mo_energy[1]) assert E_a.shape == E_b.shape E = np.stack((E_a, E_b), axis=0) integrals_dipole_ao = mol.intor("cint1e_r_sph", comp=3) occupations = utils.occupations_from_pyscf_mol(mol, C) solver = iterators.ExactInv(C, E, occupations) ao2mo = AO2MOpyscf(C, mol.verbose, mol) ao2mo.perform_uhf_full() solver.tei_mo = ao2mo.tei_mo solver.tei_mo_type = "full" driver = cphf.CPHF(solver) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = integrals_dipole_ao driver.add_operator(operator_dipole) driver.set_frequencies() driver.run(solver_type="exact", hamiltonian="rpa", spin="singlet") assert len(driver.frequencies) == len(driver.results) == 1 res = driver.results[0] print(res) atol = 1.0e-5 rtol = 0.0 np.testing.assert_allclose(res, ref_water_cation_UHF_HF_STO3G, rtol=rtol, atol=atol)
def form_tei_mo( self, program: Program, program_obj, tei_mo_type: AO2MOTransformationType ) -> None: assert isinstance(program, Program) # TODO program_obj assert isinstance(tei_mo_type, AO2MOTransformationType) nden = self.mocoeffs.shape[0] assert nden in (1, 2) if program == Program.PySCF: from pyresponse.pyscf.ao2mo import AO2MOpyscf ao2mo = AO2MOpyscf(self.mocoeffs, program_obj.verbose, program_obj) elif program == Program.Psi4: import psi4 from pyresponse.ao2mo import AO2MO assert isinstance(program_obj, psi4.core.Molecule) ao2mo = AO2MO( self.mocoeffs, self.occupations, I=psi4.core.MintsHelper( psi4.core.Wavefunction.build( program_obj, psi4.core.get_global_option("BASIS") ).basisset() ) .ao_eri() .np, ) else: raise RuntimeError if tei_mo_type == AO2MOTransformationType.partial and nden == 2: ao2mo.perform_uhf_partial() elif tei_mo_type == AO2MOTransformationType.partial and nden == 1: ao2mo.perform_rhf_partial() elif tei_mo_type == AO2MOTransformationType.full and nden == 2: ao2mo.perform_uhf_full() elif tei_mo_type == AO2MOTransformationType.full and nden == 1: ao2mo.perform_rhf_full() else: raise ValueError(f"Unknown combination of tei_mo_type {tei_mo_type} and nden {nden}") self.tei_mo = ao2mo.tei_mo self.tei_mo_type = tei_mo_type
def form_tei_mo(self, program, program_obj, tei_mo_type="partial"): assert tei_mo_type in ("partial", "full") nden = self.mocoeffs.shape[0] assert nden in (1, 2) if program == Program.PySCF: from pyresponse.pyscf.ao2mo import AO2MOpyscf ao2mo = AO2MOpyscf(self.mocoeffs, program_obj.verbose, program_obj) elif program == Program.Psi4: from pyresponse.ao2mo import AO2MO import psi4 assert isinstance(program_obj, psi4.core.Molecule) ao2mo = AO2MO( self.mocoeffs, self.occupations, I=psi4.core.MintsHelper( psi4.core.Wavefunction.build( program_obj, psi4.core.get_global_option( "BASIS")).basisset()).ao_eri().np, ) else: raise RuntimeError if tei_mo_type == "partial" and nden == 2: ao2mo.perform_uhf_partial() elif tei_mo_type == "partial" and nden == 1: ao2mo.perform_rhf_partial() elif tei_mo_type == "full" and nden == 2: ao2mo.perform_uhf_full() elif tei_mo_type == "full" and nden == 1: ao2mo.perform_rhf_full() else: # TODO more specific exception raise Exception self.tei_mo = ao2mo.tei_mo self.tei_mo_type = tei_mo_type
def test_explicit_uhf_outside_solver(): mol = molecules.molecule_water_sto3g() mol.charge = 1 mol.spin = 1 mol.build() mf = pyscf.scf.UHF(mol) mf.kernel() C_a = mf.mo_coeff[0] C_b = mf.mo_coeff[1] E_a = np.diag(mf.mo_energy[0]) E_b = np.diag(mf.mo_energy[1]) assert C_a.shape == C_b.shape assert E_a.shape == E_b.shape ao2mo = AO2MOpyscf(mf.mo_coeff, 5, mol) ao2mo.perform_uhf_full() tei_mo_aaaa, tei_mo_aabb, tei_mo_bbaa, tei_mo_bbbb = ao2mo.tei_mo occupations = utils.occupations_from_pyscf_mol(mol, mf.mo_coeff) nocc_a, nvirt_a, nocc_b, nvirt_b = occupations A_s_ss_a = eqns.form_rpa_a_matrix_mo_singlet_ss_full(E_a, tei_mo_aaaa, nocc_a) A_s_os_a = eqns.form_rpa_a_matrix_mo_singlet_os_full(tei_mo_aabb, nocc_a, nocc_b) B_s_ss_a = eqns.form_rpa_b_matrix_mo_singlet_ss_full(tei_mo_aaaa, nocc_a) B_s_os_a = eqns.form_rpa_b_matrix_mo_singlet_os_full(tei_mo_aabb, nocc_a, nocc_b) A_s_ss_b = eqns.form_rpa_a_matrix_mo_singlet_ss_full(E_b, tei_mo_bbbb, nocc_b) A_s_os_b = eqns.form_rpa_a_matrix_mo_singlet_os_full(tei_mo_bbaa, nocc_b, nocc_a) B_s_ss_b = eqns.form_rpa_b_matrix_mo_singlet_ss_full(tei_mo_bbbb, nocc_b) B_s_os_b = eqns.form_rpa_b_matrix_mo_singlet_os_full(tei_mo_bbaa, nocc_b, nocc_a) # Since the "triplet" part contains no Coulomb contribution, and # (xx|yy) is only in the Coulomb part, there is no ss/os # separation for the triplet part. G_aa = np.block([[A_s_ss_a, B_s_ss_a], [B_s_ss_a, A_s_ss_a]]) G_bb = np.block([[A_s_ss_b, B_s_ss_b], [B_s_ss_b, A_s_ss_b]]) G_ab = np.block([[A_s_os_a, B_s_os_a], [B_s_os_a, A_s_os_a]]) G_ba = np.block([[A_s_os_b, B_s_os_b], [B_s_os_b, A_s_os_b]]) G_aa_inv = np.linalg.inv(G_aa) G_bb_inv = np.linalg.inv(G_bb) nov_aa = nocc_a * nvirt_a nov_bb = nocc_b * nvirt_b assert G_aa_inv.shape == (2 * nov_aa, 2 * nov_aa) assert G_bb_inv.shape == (2 * nov_bb, 2 * nov_bb) # Form the operator-independent part of the response vectors. left_a = np.linalg.inv(G_aa - np.dot(G_ab, np.dot(G_bb_inv, G_ba))) left_b = np.linalg.inv(G_bb - np.dot(G_ba, np.dot(G_aa_inv, G_ab))) integrals_dipole_ao = mol.intor("cint1e_r_sph", comp=3) integrals_dipole_mo_ai_a = [] integrals_dipole_mo_ai_b = [] for comp in range(3): integrals_dipole_mo_ai_comp_a = np.dot( C_a[:, nocc_a:].T, np.dot(integrals_dipole_ao[comp, ...], C_a[:, :nocc_a]) ) integrals_dipole_mo_ai_comp_b = np.dot( C_b[:, nocc_b:].T, np.dot(integrals_dipole_ao[comp, ...], C_b[:, :nocc_b]) ) integrals_dipole_mo_ai_comp_a = np.reshape(integrals_dipole_mo_ai_comp_a, -1, order="F") integrals_dipole_mo_ai_comp_b = np.reshape(integrals_dipole_mo_ai_comp_b, -1, order="F") integrals_dipole_mo_ai_a.append(integrals_dipole_mo_ai_comp_a) integrals_dipole_mo_ai_b.append(integrals_dipole_mo_ai_comp_b) integrals_dipole_mo_ai_a = np.stack(integrals_dipole_mo_ai_a, axis=0).T integrals_dipole_mo_ai_b = np.stack(integrals_dipole_mo_ai_b, axis=0).T integrals_dipole_mo_ai_a_super = np.concatenate( (integrals_dipole_mo_ai_a, -integrals_dipole_mo_ai_a), axis=0 ) integrals_dipole_mo_ai_b_super = np.concatenate( (integrals_dipole_mo_ai_b, -integrals_dipole_mo_ai_b), axis=0 ) # Form the operator-dependent part of the response vectors. right_a = integrals_dipole_mo_ai_a_super - ( np.dot(G_ab, np.dot(G_bb_inv, integrals_dipole_mo_ai_b_super)) ) right_b = integrals_dipole_mo_ai_b_super - ( np.dot(G_ba, np.dot(G_aa_inv, integrals_dipole_mo_ai_a_super)) ) # The total response vector for each spin is the product of the # operator-independent (left) and operator-dependent (right) # parts. rspvec_a = np.dot(left_a, right_a) rspvec_b = np.dot(left_b, right_b) res_a = np.dot(integrals_dipole_mo_ai_a_super.T, rspvec_a) / 2 res_b = np.dot(integrals_dipole_mo_ai_b_super.T, rspvec_b) / 2 res_u = 2 * (res_a + res_b) print(res_u) atol = 1.0e-5 rtol = 0.0 np.testing.assert_allclose(res_u, ref_water_cation_UHF_HF_STO3G, rtol=rtol, atol=atol)
def test_explicit_uhf_from_rhf_outside_solver(): mol = molecules.molecule_water_sto3g() mol.build() mf = pyscf.scf.RHF(mol) mf.kernel() mocoeffs = mf.mo_coeff moenergies = mf.mo_energy ao2mo = AO2MOpyscf(mocoeffs, mol.verbose, mol) ao2mo.perform_rhf_full() tei_mo = ao2mo.tei_mo[0] C_a = mocoeffs C_b = C_a.copy() E_a = np.diag(moenergies) # E_b = E_a.copy() occupations = utils.occupations_from_pyscf_mol(mol, mocoeffs) nocc_a, nvirt_a, nocc_b, nvirt_b = occupations # Same-spin and opposite-spin contributions should add together # properly for restricted wavefunction. A_s = eqns.form_rpa_a_matrix_mo_singlet_full(E_a, tei_mo, nocc_a) A_s_ss = eqns.form_rpa_a_matrix_mo_singlet_ss_full(E_a, tei_mo, nocc_a) A_s_os = eqns.form_rpa_a_matrix_mo_singlet_os_full(tei_mo, nocc_a, nocc_b) np.testing.assert_allclose(A_s, A_s_ss + A_s_os) B_s = eqns.form_rpa_b_matrix_mo_singlet_full(tei_mo, nocc_a) B_s_ss = eqns.form_rpa_b_matrix_mo_singlet_ss_full(tei_mo, nocc_a) B_s_os = eqns.form_rpa_b_matrix_mo_singlet_os_full(tei_mo, nocc_a, nocc_b) np.testing.assert_allclose(B_s, B_s_ss + B_s_os) # Since the "triplet" part contains no Coulomb contribution, and # (xx|yy) is only in the Coulomb part, there is no ss/os # separation for the triplet part. G_r = np.block([[A_s, B_s], [B_s, A_s]]) G_aa = np.block([[A_s_ss, B_s_ss], [B_s_ss, A_s_ss]]) G_bb = G_aa.copy() G_ab = np.block([[A_s_os, B_s_os], [B_s_os, A_s_os]]) G_ba = G_ab.copy() np.testing.assert_allclose(G_r, (G_aa + G_ab)) G_r_inv = np.linalg.inv(G_r) G_aa_inv = np.linalg.inv(G_aa) G_bb_inv = np.linalg.inv(G_bb) assert G_r_inv.shape == (2 * nocc_a * nvirt_a, 2 * nocc_a * nvirt_a) assert G_aa_inv.shape == (2 * nocc_a * nvirt_a, 2 * nocc_a * nvirt_a) assert G_bb_inv.shape == (2 * nocc_b * nvirt_b, 2 * nocc_b * nvirt_b) # Form the operator-independent part of the response vectors. left_alph = np.linalg.inv(G_aa - np.dot(G_ab, np.dot(G_bb_inv, G_ba))) left_beta = np.linalg.inv(G_bb - np.dot(G_ba, np.dot(G_aa_inv, G_ab))) integrals_dipole_ao = mol.intor("cint1e_r_sph", comp=3) integrals_dipole_mo_ai_r = [] integrals_dipole_mo_ai_a = [] integrals_dipole_mo_ai_b = [] for comp in range(3): integrals_dipole_mo_ai_comp_r = np.dot( C_a[:, nocc_a:].T, np.dot(integrals_dipole_ao[comp, ...], C_a[:, :nocc_a]) ) integrals_dipole_mo_ai_comp_a = np.dot( C_a[:, nocc_a:].T, np.dot(integrals_dipole_ao[comp, ...], C_a[:, :nocc_a]) ) integrals_dipole_mo_ai_comp_b = np.dot( C_b[:, nocc_b:].T, np.dot(integrals_dipole_ao[comp, ...], C_b[:, :nocc_b]) ) integrals_dipole_mo_ai_comp_r = np.reshape(integrals_dipole_mo_ai_comp_r, -1, order="F") integrals_dipole_mo_ai_comp_a = np.reshape(integrals_dipole_mo_ai_comp_a, -1, order="F") integrals_dipole_mo_ai_comp_b = np.reshape(integrals_dipole_mo_ai_comp_b, -1, order="F") integrals_dipole_mo_ai_r.append(integrals_dipole_mo_ai_comp_r) integrals_dipole_mo_ai_a.append(integrals_dipole_mo_ai_comp_a) integrals_dipole_mo_ai_b.append(integrals_dipole_mo_ai_comp_b) integrals_dipole_mo_ai_r = np.stack(integrals_dipole_mo_ai_r, axis=0).T integrals_dipole_mo_ai_a = np.stack(integrals_dipole_mo_ai_a, axis=0).T integrals_dipole_mo_ai_b = np.stack(integrals_dipole_mo_ai_b, axis=0).T integrals_dipole_mo_ai_r_super = np.concatenate( (integrals_dipole_mo_ai_r, -integrals_dipole_mo_ai_r), axis=0 ) integrals_dipole_mo_ai_a_super = np.concatenate( (integrals_dipole_mo_ai_a, -integrals_dipole_mo_ai_a), axis=0 ) integrals_dipole_mo_ai_b_super = np.concatenate( (integrals_dipole_mo_ai_b, -integrals_dipole_mo_ai_b), axis=0 ) # Form the operator-dependent part of the response vectors. right_alph = integrals_dipole_mo_ai_a_super - ( np.dot(G_ab, np.dot(G_bb_inv, integrals_dipole_mo_ai_b_super)) ) right_beta = integrals_dipole_mo_ai_b_super - ( np.dot(G_ba, np.dot(G_aa_inv, integrals_dipole_mo_ai_a_super)) ) rspvec_r = np.dot(G_r_inv, integrals_dipole_mo_ai_r_super) # The total response vector for each spin is the product of the # operator-independent (left) and operator-dependent (right) # parts. rspvec_a = np.dot(left_alph, right_alph) rspvec_b = np.dot(left_beta, right_beta) res_r = 4 * np.dot(integrals_dipole_mo_ai_r_super.T, rspvec_r) / 2 res_a = np.dot(integrals_dipole_mo_ai_a_super.T, rspvec_a) / 2 res_b = np.dot(integrals_dipole_mo_ai_b_super.T, rspvec_b) / 2 res_u = 2 * (res_a + res_b) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(res_u, res_r, rtol=rtol, atol=atol) print(res_r) print(res_u)
def test_HF_both_singlet_HF_STO3G(): mol = pyscf.gto.Mole() mol.verbose = 0 mol.output = None # pylint: disable=bad-whitespace mol.atom = [["H", (0.0, 0.0, 0.917)], ["F", (0.0, 0.0, 0.0)]] mol.basis = "sto-3g" mol.build() mf = pyscf.scf.RHF(mol) mf.scf() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = utils.occupations_from_pyscf_mol(mol, C) solver_tda = iterators.ExactDiagonalizationSolverTDA(C, E, occupations) solver_tdhf = iterators.ExactDiagonalizationSolver(C, E, occupations) ao2mo = AO2MOpyscf(C, mol.verbose, mol) ao2mo.perform_rhf_partial() tei_mo = ao2mo.tei_mo solver_tda.tei_mo = tei_mo solver_tda.tei_mo_type = "partial" solver_tdhf.tei_mo = tei_mo solver_tdhf.tei_mo_type = "partial" driver_tda = td.TDA(solver_tda) driver_tdhf = td.TDHF(solver_tdhf) nroots = 5 print("TDA using TDA()") driver_tda.run(solver_type="exact", hamiltonian="tda", spin="singlet") excitation_energies_tda_using_tda = driver_tda.solver.eigvals[:nroots].real print("TDA using TDHF()") driver_tdhf.run(solver_type="exact", hamiltonian="tda", spin="singlet") excitation_energies_tda_using_tdhf = driver_tdhf.solver.eigvals[:nroots].real print("RPA using TDHF()") driver_tdhf.run(solver_type="exact", hamiltonian="rpa", spin="singlet") excitation_energies_rpa = driver_tdhf.solver.eigvals[:nroots].real assert ( excitation_energies_tda_using_tda.shape == excitation_energies_tda_using_tdhf.shape ) assert excitation_energies_tda_using_tdhf.shape == excitation_energies_rpa.shape # There should be no difference in the TDA results regardless of # which implementation used. assert ( excitation_energies_tda_using_tda - excitation_energies_tda_using_tdhf ).all() == 0 # Now compare against reference_data ref_tda = HF_neutral_singlet_HF_STO3G_CIS_qchem ref_rpa = HF_neutral_singlet_HF_STO3G_RPA_qchem thresh = 1.0e-7 for i in range(nroots): abs_diff = abs(ref_tda["etenergies"][i] - excitation_energies_tda_using_tda[i]) assert abs_diff < thresh thresh = 1.0e-7 for i in range(nroots): abs_diff = abs(ref_rpa["etenergies"][i] - excitation_energies_rpa[i]) assert abs_diff < thresh return
def calculate_uhf( dalton_tmpdir: Path, hamiltonian: str, spin: str, operator_label: str, operator: str, source_moenergies: str, source_mocoeffs: str, source_operator: str, ): if operator_label: # TODO add dipvel assert operator_label in ("dipole", "angmom", "spinorb") assert source_moenergies in ("pyscf", "dalton") assert source_mocoeffs in ("pyscf", "dalton") dalton_molecule = dalmol.readin(dalton_tmpdir / "DALTON.BAS") lines = [] for atom in dalton_molecule: label = atom["label"][0] center = atom["center"][0] center_str = " ".join(["{:f}".format(pos) for pos in center]) line = "{:3} {}".format(label, center_str) lines.append(line) lines = "\n".join(lines) # PySCF molecule setup, needed for generating the TEIs in the MO # basis. mol = pyscf.gto.Mole() verbose = 1 mol.verbose = verbose mol.atom = lines mol.unit = "Bohr" # TODO read basis from DALTON molecule mol.basis = "sto-3g" mol.symmetry = False # TODO read charge from DALTON molecule? mol.charge = 1 # TODO read spin from DALTON molecule? mol.spin = 1 mol.build() ifc = sirifc.sirifc(dalton_tmpdir / "SIRIFC") occupations = utils.occupations_from_sirifc(ifc) if source_moenergies == "pyscf" or source_mocoeffs == "pyscf": mf = pyscf.scf.UHF(mol) mf.kernel() if source_moenergies == "pyscf": E_alph = np.diag(mf.mo_energy[0]) E_beta = np.diag(mf.mo_energy[1]) E = np.stack((E_alph, E_beta), axis=0) elif source_moenergies == "dalton": job = ccopen(dalton_tmpdir / "DALTON.OUT") data = job.parse() # pylint: disable=no-member E = np.diag([ convertor(x, "eV", "hartree") for x in data.moenergies[0] ])[np.newaxis, ...] E = np.concatenate((E, E), axis=0) else: pass if source_mocoeffs == "pyscf": C = mf.mo_coeff elif source_mocoeffs == "dalton": C = ifc.cmo[0][np.newaxis, ...] C = np.concatenate((C, C), axis=0) else: pass solver = solvers.ExactInv(C, E, occupations) solver.tei_mo = AO2MOpyscf(mol, C).perform_uhf_partial() solver.tei_mo_type = AO2MOTransformationType.partial driver = cphf.CPHF(solver) if operator: driver.add_operator(operator) elif operator_label: if operator_label == "dipole": operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False, triplet=False) integrals_dipole_ao = mol.intor("cint1e_r_sph", comp=3) operator_dipole.ao_integrals = integrals_dipole_ao driver.add_operator(operator_dipole) elif operator_label == "angmom": operator_angmom = operators.Operator(label="angmom", is_imaginary=True, is_spin_dependent=False, triplet=False) integrals_angmom_ao = mol.intor("cint1e_cg_irxp_sph", comp=3) operator_angmom.ao_integrals = integrals_angmom_ao driver.add_operator(operator_angmom) elif operator_label == "spinorb": operator_spinorb = operators.Operator(label="spinorb", is_imaginary=True, is_spin_dependent=False, triplet=False) integrals_spinorb_ao = 0 for atm_id in range(mol.natm): mol.set_rinv_orig(mol.atom_coord(atm_id)) chg = mol.atom_charge(atm_id) integrals_spinorb_ao += chg * mol.intor("cint1e_prinvxp_sph", comp=3) operator_spinorb.ao_integrals = integrals_spinorb_ao driver.add_operator(operator_spinorb) else: pass else: pass driver.set_frequencies() driver.run(hamiltonian=Hamiltonian[hamiltonian.upper()], spin=Spin[spin]) return driver.results[0]