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 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_atomic_polar_tensor_rhf(): mol = molecules.molecule_physicists_water_sto3g() mol.reset_point_group("c1") mol.update_geometry() psi4.core.set_active_molecule(mol) options = { "BASIS": "STO-3G", "SCF_TYPE": "PK", "E_CONVERGENCE": 1e-10, "D_CONVERGENCE": 1e-10, } psi4.set_options(options) _, wfn = psi4.energy("hf", return_wfn=True) mints = psi4.core.MintsHelper(wfn) C = mocoeffs_from_psi4wfn(wfn) E = moenergies_from_psi4wfn(wfn) occupations = occupations_from_psi4wfn(wfn) nocc, nvir, _, _ = occupations norb = nocc + nvir # electric perturbation part ao2mo = AO2MO(C, occupations, I=np.asarray(mints.ao_eri())) ao2mo.perform_rhf_full() solver = ExactInv(C, E, occupations) solver.tei_mo = ao2mo.tei_mo solver.tei_mo_type = "full" driver = CPHF(solver) operator_diplen = Operator(label="dipole", is_imaginary=False, is_spin_dependent=False, triplet=False) # integrals_diplen_ao = self.pyscfmol.intor('cint1e_r_sph', comp=3) M = np.stack([np.asarray(Mc) for Mc in mints.ao_dipole()]) operator_diplen.ao_integrals = M driver.add_operator(operator_diplen) # geometric perturbation part operator_geometric = Operator(label="nuclear", is_imaginary=False, is_spin_dependent=False, triplet=False) operator_geometric.form_rhs_geometric(C, occupations, mol.natom(), solver.tei_mo[0], mints) print(operator_geometric.label) print(operator_geometric.mo_integrals_ai_alph) print(operator_diplen.label) print(operator_diplen.mo_integrals_ai_alph) # hack for dim check in solver operator_geometric.ao_integrals = np.zeros( (3 * mol.natom(), M.shape[1], M.shape[2])) # bypass driver's call to form_rhs driver.solver.operators.append(operator_geometric) driver.run() print(driver.results[0]) print(driver.results[0].T) print(driver.results[0] - driver.results[0].T) print(operator_geometric.rspvecs_alph[0]) # Nuclear contribution to dipole gradient # Electronic contributions to static part of dipole gradient # Reorthonormalization part of dipole gradient # Static contribution to dipole gradient # Relaxation part of dipole gradient # Total dipole gradient - TRAROT print("Nuclear contribution to dipole gradient") natom = mol.natom() Z = np.asarray([mol.Z(i) for i in range(natom)]) nuclear_contrib = np.concatenate( [np.diag(Z.take(3 * [i])) for i in range(natom)]) print(nuclear_contrib) return locals()