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_electronicgtensor_small(): mol = molecules.molecule_bc2h4_neutral_radical_sto3g() 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) gtensor_calculator = magnetic.ElectronicGTensor(Program.PySCF, mol, C, E, occupations) gtensor_calculator.form_operators() gtensor_calculator.run(hamiltonian="rpa", spin="singlet") gtensor_calculator.form_results() print(ref_electronicgtensor_small) print(gtensor_calculator.g_oz_soc_1) assert np.all( np.equal( np.sign(ref_electronicgtensor_small), np.sign(gtensor_calculator.g_oz_soc_1) ) ) return
def form_rhs_geometric( self, C: np.ndarray, occupations: np.ndarray, natoms, MO_full, mints, return_dict: bool = False, ) -> None: from pyresponse.integrals import _form_rhs_geometric C_ = fix_mocoeffs_shape(C) B_dict = _form_rhs_geometric(C_[0], occupations, natoms, MO_full, mints) if return_dict: return B_dict # TODO I think this is wrong, because the matrices are [i, a] B_matrices = [B_dict[k].T for k in sorted(B_dict.keys())] B_vectors = [ repack_matrix_to_vector(B)[:, np.newaxis] for B in B_matrices ] mo_integrals_ai_alph = np.stack(B_vectors) self.mo_integrals_ai_alph = mo_integrals_ai_alph # pylint: disable=invalid-unary-operand-type self.mo_integrals_ai_supervector_alph = np.concatenate( (mo_integrals_ai_alph, -mo_integrals_ai_alph), axis=1)
def test_magnetizability_uhf() -> None: mol = molecules.molecule_glycine_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 = occupations_from_pyscf_mol(mol, C) calculator_common = magnetic.Magnetizability( Program.PySCF, mol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, ) calculator_common.form_operators() calculator_common.run(hamiltonian=Hamiltonian.RPA, spin=Spin.singlet) calculator_common.form_results() ref_eigvals, ref_iso, _ = utils.tensor_printer(ref_magnetizability_rohf) res_eigvals, res_iso, _ = utils.tensor_printer( calculator_common.magnetizability) thresh_eigval = 1.0e-1 for i in range(3): assert abs(ref_eigvals[i] - res_eigvals[i]) < thresh_eigval
def test_electronicgtensor_tiny() -> None: mol = molecules.molecule_lih_cation_sto3g() 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 = occupations_from_pyscf_mol(mol, C) gtensor_calculator = magnetic.ElectronicGTensor( Program.PySCF, mol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, ) gtensor_calculator.form_operators() gtensor_calculator.run(hamiltonian=Hamiltonian.RPA, spin=Spin.singlet) gtensor_calculator.form_results() print(ref_electronicgtensor_tiny) print(gtensor_calculator.g_oz_soc_1) assert np.all( np.equal( np.sign(ref_electronicgtensor_tiny), np.sign(utils.screen(gtensor_calculator.g_oz_soc_1)), ))
def test_magnetizability_rhf(): mol = molecules.molecule_glycine_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 = utils.occupations_from_pyscf_mol(mol, C) calculator_common = magnetic.Magnetizability(Program.PySCF, mol, C, E, occupations) calculator_common.form_operators() calculator_common.run(hamiltonian="rpa", spin="singlet") calculator_common.form_results() ref_eigvals, ref_iso, _ = utils.tensor_printer(ref_magnetizability_rhf) res_eigvals, res_iso, _ = utils.tensor_printer(calculator_common.magnetizability) thresh_eigval = 1.0e-3 for i in range(3): assert abs(ref_eigvals[i] - res_eigvals[i]) < thresh_eigval # TODO it isn't so simple; there are actually many more terms # present when using London orbitals. # calculator_giao = magnetic.Magnetizability(mol, C, E, occupations, hamiltonian='rpa', spin='singlet', use_giao=True) # calculator_giao.form_operators() # calculator_giao.run() # calculator_giao.form_results() return
def test_ORD_RPA_singlet_BC2H4_HF_STO3G(): ref = BC2H4_HF_STO3G_RPA_singlet_nwchem pyscfmol = molecules.molecule_bc2h4_neutral_radical_sto3g() pyscfmol.build() mf = pyscf.scf.UHF(pyscfmol) mf.scf() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = occupations_from_pyscf_mol(pyscfmol, C) frequencies = [0.0, 0.001, 0.0773178, 0.128347] ord_solver = optrot.ORD( Program.PySCF, pyscfmol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, frequencies=frequencies, do_dipvel=False, ) ord_solver.form_operators() ord_solver.run(hamiltonian=Hamiltonian.RPA, spin=Spin.singlet) ord_solver.form_results() print("Polarizabilities") assert len(frequencies) == len(ord_solver.polarizabilities) thresh = 6.5e-4 for idxf, frequency in enumerate(frequencies): ref_polar = ref[frequency]["polar"] res_polar = ord_solver.polarizabilities[idxf] abs_diff = abs(res_polar - ref_polar) print(idxf, frequency) print(res_polar) print(abs_diff) if frequency == 0.128347: thresh = 6.0e-3 assert (abs_diff < thresh).all() print(r"\beta(\omega)") thresh = 0.09 for idxf, frequency in enumerate(frequencies): if "orbeta" in ref[frequency]: ref_beta = ref[frequency]["orbeta"] # TODO why no speed of light? # TODO why the (1/2)? res_beta = -(0.5 / frequency) * ord_solver.driver.results[idxf][3:6, 0:3] abs_diff = abs(res_beta - ref_beta) print(idxf, frequency) print(res_beta) print(ref_beta) print(abs_diff) assert (abs_diff < thresh).all()
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 mocoeffs_from_psi4wfn(wfn: psi4.core.Wavefunction) -> np.ndarray: is_uhf = not wfn.same_a_b_orbs() Ca = wfn.Ca().to_array() if is_uhf: Cb = wfn.Cb().to_array() C = np.stack((Ca, Cb), axis=0) else: C = Ca # Clean up. return fix_mocoeffs_shape(C)
def __init__(self, C, occupations, verbose=1, I=None): self.C = fix_mocoeffs_shape(C) self.occupations = occupations self.verbose = verbose self.I = I self.nocc_alph, self.nvirt_alph, self.nocc_beta, self.nvirt_beta = occupations self.tei_mo = tuple()
def test_iterators(): """Test that each kind of iterator gives identical results.""" mol = molecules_pyscf.molecule_glycine_sto3g() mol.charge = 1 mol.spin = 1 mol.build() mf = pyscf.scf.uhf.UHF(mol) mf.scf() assert isinstance(mf.mo_coeff, np.ndarray) assert len(mf.mo_coeff) == 2 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_ref = iterators.ExactInv(C, E, occupations) calculator_ref = magnetic.Magnetizability(Program.PySCF, mol, C, E, occupations, solver=solver_ref) calculator_ref.form_operators() calculator_ref.run(hamiltonian="rpa", spin="singlet") calculator_ref.form_results() ref = calculator_ref.magnetizability inv_funcs = (sp.linalg.inv, sp.linalg.pinv, sp.linalg.pinv2) thresh = 6.0e-14 for inv_func in inv_funcs: solver_res = iterators.ExactInv(C, E, occupations, inv_func=inv_func) calculator_res = magnetic.Magnetizability(Program.PySCF, mol, C, E, occupations, solver=solver_res) calculator_res.form_operators() calculator_res.run(hamiltonian="rpa", spin="singlet") calculator_res.form_results() np.testing.assert_equal( np.sign(calculator_ref.magnetizability), np.sign(calculator_res.magnetizability), ) diff = calculator_ref.magnetizability - calculator_res.magnetizability abs_diff = np.abs(diff) print(abs_diff) assert np.all(abs_diff < thresh) return
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 __init__( self, C: np.ndarray, occupations: Sequence[int], verbose: int = 1, I: Optional[np.ndarray] = None, ) -> None: self.C = fix_mocoeffs_shape(C) self.occupations = occupations self.verbose = verbose self.I = I self.nocc_alph, self.nvirt_alph, self.nocc_beta, self.nvirt_beta = occupations self.tei_mo = tuple()
def test_ORD_RPA_singlet_trithiolane_HF_STO3G(): ref = trithiolane_HF_STO3G_RPA_singlet pyscfmol = molecules.molecule_trithiolane_sto3g() pyscfmol.build() mf = pyscf.scf.RHF(pyscfmol) mf.scf() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = occupations_from_pyscf_mol(pyscfmol, C) frequencies = [0.0, 0.0773178, 0.128347] ord_solver = optrot.ORD( Program.PySCF, pyscfmol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, frequencies=frequencies, do_dipvel=False, ) ord_solver.form_operators() ord_solver.run(hamiltonian=Hamiltonian.RPA, spin=Spin.singlet) ord_solver.form_results() print("Polarizabilities") assert len(frequencies) == len(ord_solver.polarizabilities) thresh = 5.0e-4 for idxf, frequency in enumerate(frequencies): ref_polar = ref[frequency]["polar"] res_polar = ord_solver.polarizabilities[idxf] abs_diff = abs(res_polar - ref_polar) print(idxf, frequency) print(res_polar) print(abs_diff) assert (abs_diff < thresh).all()
def test_final_result_rhf_h2o_sto3g_rpa_singlet(): hamiltonian = "rpa" spin = "singlet" C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = [5, 2, 5, 2] stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = iterators.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = "full" driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(solver_type="exact", hamiltonian=hamiltonian, spin=spin) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[7.93556221, 0.0, 0.0], [0.0, 3.06821077, 0.0], [0.0, 0.0, 0.05038621]]) result__0_02 = np.array([[7.94312371, 0.0, 0.0], [0.0, 3.07051688, 0.0], [0.0, 0.0, 0.05054685]]) result__0_06 = np.array([[8.00414009, 0.0, 0.0], [0.0, 3.08913608, 0.0], [0.0, 0.0, 0.05186977]]) result__0_10 = np.array([[8.1290378, 0.0, 0.0], [0.0, 3.12731363, 0.0], [0.0, 0.0, 0.05473482]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) # Reminder: there's no call to do SCF here because we already have # the MO coefficients. mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability(Program.PySCF, mol, C, E, occupations, frequencies) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol) return
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 occupations_from_pyscf_mol(mol: pyscf.gto.Mole, C: np.ndarray) -> np.ndarray: norb = fix_mocoeffs_shape(C).shape[-1] nocc_a, nocc_b = mol.nelec nvirt_a, nvirt_b = norb - nocc_a, norb - nocc_b return np.asarray([nocc_a, nvirt_a, nocc_b, nvirt_b], dtype=int)
def test_ECD_RPA_singlet_BC2H4_cation_HF_STO3G() -> None: ref = BC2H4_cation_HF_STO3G_RPA_singlet_nwchem nroots = ref["nroots"] mol = molecules.molecule_bc2h4_cation_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) ecd_dipvel_rpa = ecd.ECD( Program.PySCF, mol, td.TDHF(solvers.ExactDiagonalizationSolver(C, E, occupations)), C, E, occupations, do_dipvel=True, ) ecd_dipvel_rpa.form_operators() ecd_dipvel_rpa.run(hamiltonian=Hamiltonian.RPA, spin=Spin.singlet) ecd_dipvel_rpa.form_results() print("excitation energies") ref_etenergies = np.array(ref["etenergies"]) res_etenergies = ecd_dipvel_rpa.driver.solver.eigvals.real[:nroots] print("ref, res") for refval, resval in zip(ref_etenergies, res_etenergies): print(refval, resval) thresh = 2.5e-7 for i in range(nroots): abs_diff = abs(ref_etenergies[i] - res_etenergies[i]) assert abs_diff < thresh print("dipole (length) oscillator strengths") ref_etoscslen = np.array(ref["etoscslen"]) res_etoscslen = ecd_dipvel_rpa.driver.solver.operators[ 1].total_oscillator_strengths[:nroots] print("ref, res") for refval, resval in zip(ref_etoscslen, res_etoscslen): print(refval, resval) thresh = 1.0e-5 for i in range(nroots): abs_diff = abs(ref_etoscslen[i] - res_etoscslen[i]) assert abs_diff < thresh # TODO print("TODO dipole (mixed length/velocity) oscillator strengths") # TODO print("TODO dipole (velocity) oscillator strengths") ref_etoscsvel = np.array(ref["etoscsvel"]) res_etoscsvel = ecd_dipvel_rpa.driver.solver.operators[ 2].total_oscillator_strengths[:nroots] # print('ref, res') # for refval, resval in zip(ref_etoscsvel, res_etoscsvel): # print(refval, resval) # print(ref_etoscsvel / res_etoscsvel) # print(res_etoscsvel / ref_etoscsvel) print("rotatory strengths (length)") ref_etrotstrlen = np.array(ref["etrotstrlen"]) res_etrotstrlen = ecd_dipvel_rpa.rotational_strengths_diplen[:nroots] print("ref, res") for refval, resval in zip(ref_etrotstrlen, res_etrotstrlen): print(refval, resval) # TODO unlike other quantities, the error isn't uniformly # distributed among the roots; how should this be handled? thresh = 1.5e1 for i in range(nroots): abs_diff = abs(ref_etrotstrlen[i] - res_etrotstrlen[i]) assert abs_diff < thresh print("rotatory strengths (velocity)") ref_etrotstrvel = np.array(ref["etrotstrvel"]) res_etrotstrvel = ecd_dipvel_rpa.rotational_strengths_dipvel[:nroots] print("ref, res") for refval, resval in zip(ref_etrotstrvel, res_etrotstrvel): print(refval, resval) thresh = 1.0e-2 for i in range(nroots): abs_diff = abs(ref_etrotstrvel[i] - res_etrotstrvel[i]) assert abs_diff < thresh
def test_first_hyperpolarizability_shg_rhf_wigner_explicit_psi4numpy_pyscf_large(): mol = molecule_physicists_water_augccpvdz() mol.build() mf = pyscf.scf.RHF(mol) mf.kernel() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = occupations_from_pyscf_mol(mol, C) nocc_alph, nvirt_alph, _, _ = occupations nov_alph = nocc_alph * nvirt_alph norb = nocc_alph + nvirt_alph # calculate linear response vectors for electric dipole operator f1 = 0.0773178 f2 = 2 * f1 frequencies = [f1, f2] calculator = electric.Polarizability( Program.PySCF, mol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, frequencies=frequencies, ) calculator.form_operators() calculator.run(hamiltonian=Hamiltonian.RPA, spin=Spin.singlet) calculator.form_results() polarizability_1 = calculator.polarizabilities[0] polarizability_2 = calculator.polarizabilities[1] print("polarizability: {} a.u.".format(f1)) print(polarizability_1) print("polarizability: {} a.u. (frequency doubled)".format(f2)) print(polarizability_2) # each operator contains multiple sets of response vectors, one # set of components for each frequency assert isinstance(calculator.driver.solver.operators, list) assert len(calculator.driver.solver.operators) == 1 operator = calculator.driver.solver.operators[0] rhsvecs = operator.mo_integrals_ai_supervector_alph assert isinstance(operator.rspvecs_alph, list) assert len(operator.rspvecs_alph) == 2 rspvecs_1 = operator.rspvecs_alph[0] rspvecs_2 = operator.rspvecs_alph[1] ## Form the full [norb, norb] representation of everything. # Response vectors: transform X_{ia} and Y_{ia} -> U_{p,q} # 0. 'a' is fast index, 'i' slow # 1. rspvec == [X Y] # 2. U_{p, q} -> zero # 3. place X_{ia} into U_{i, a} # 4. place Y_{ia} into U_{a, i} ncomp = rhsvecs.shape[0] rspmats_1 = np.zeros(shape=(ncomp, norb, norb)) rspmats_2 = np.zeros(shape=(ncomp, norb, norb)) for i in range(ncomp): rspvec_1 = rspvecs_1[i, :, 0] rspvec_2 = rspvecs_2[i, :, 0] x_1 = rspvec_1[:nov_alph] y_1 = rspvec_1[nov_alph:] x_2 = rspvec_2[:nov_alph] y_2 = rspvec_2[nov_alph:] x_full_1 = utils.repack_vector_to_matrix(x_1, (nvirt_alph, nocc_alph)) y_full_1 = utils.repack_vector_to_matrix(y_1, (nvirt_alph, nocc_alph)) x_full_2 = utils.repack_vector_to_matrix(x_2, (nvirt_alph, nocc_alph)) y_full_2 = utils.repack_vector_to_matrix(y_2, (nvirt_alph, nocc_alph)) rspmats_1[i, :nocc_alph, nocc_alph:] = y_full_1.T rspmats_1[i, nocc_alph:, :nocc_alph] = x_full_1 rspmats_2[i, :nocc_alph, nocc_alph:] = y_full_2.T rspmats_2[i, nocc_alph:, :nocc_alph] = x_full_2 rhsmats = np.zeros(shape=(ncomp, norb, norb)) for i in range(ncomp): rhsvec = rhsvecs[i, :, 0] rhsvec_top = rhsvec[:nov_alph] rhsvec_bot = rhsvec[nov_alph:] rhsvec_top_mat = utils.repack_vector_to_matrix(rhsvec_top, (nvirt_alph, nocc_alph)) rhsvec_bot_mat = utils.repack_vector_to_matrix(rhsvec_bot, (nvirt_alph, nocc_alph)) rhsmats[i, :nocc_alph, nocc_alph:] = rhsvec_top_mat.T rhsmats[i, nocc_alph:, :nocc_alph] = rhsvec_bot_mat polarizability_full_1 = np.empty_like(polarizability_1) polarizability_full_2 = np.empty_like(polarizability_2) for a in (0, 1, 2): for b in (0, 1, 2): polarizability_full_1[a, b] = 2 * np.trace(np.dot(rhsmats[a].T, rspmats_1[b])) polarizability_full_2[a, b] = 2 * np.trace(np.dot(rhsmats[a].T, rspmats_2[b])) np.testing.assert_almost_equal(polarizability_1, -polarizability_full_1) np.testing.assert_almost_equal(polarizability_2, -polarizability_full_2) # V_{p,q} <- full MO transformation of right hand side integrals_ao = operator.ao_integrals integrals_mo = np.empty_like(integrals_ao) for i in range(ncomp): integrals_mo[i] = (C[0].T).dot(integrals_ao[i]).dot(C[0]) G_1 = np.empty_like(rspmats_1) G_2 = np.empty_like(rspmats_2) C = mf.mo_coeff # TODO I feel as though if I have all the MO-basis two-electron # integrals, I shouldn't need another JK build. for i in range(ncomp): V = integrals_mo[i] Dl_1 = (C[:, :nocc_alph]).dot(rspmats_1[i, :nocc_alph, :]).dot(C.T) Dr_1 = (-C).dot(rspmats_1[i, :, :nocc_alph]).dot(C[:, :nocc_alph].T) D_1 = Dl_1 + Dr_1 Dl_2 = (C[:, :nocc_alph]).dot(rspmats_2[i, :nocc_alph, :]).dot(C.T) Dr_2 = (-C).dot(rspmats_2[i, :, :nocc_alph]).dot(C[:, :nocc_alph].T) D_2 = Dl_2 + Dr_2 J_1, K_1 = mf.get_jk(mol, D_1, hermi=0) J_2, K_2 = mf.get_jk(mol, D_2, hermi=0) F_AO_1 = 2 * J_1 - K_1 F_AO_2 = 2 * J_2 - K_2 F_MO_1 = (C.T).dot(F_AO_1).dot(C) F_MO_2 = (C.T).dot(F_AO_2).dot(C) G_1[i] = V + F_MO_1 G_2[i] = V + F_MO_2 E_diag = np.diag(E[0, ...]) epsilon_1 = G_1.copy() epsilon_2 = G_2.copy() for i in range(ncomp): eoU_1 = (E_diag[..., np.newaxis] + f1) * rspmats_1[i] Ue_1 = rspmats_1[i] * E_diag[np.newaxis, ...] epsilon_1[i] += eoU_1 - Ue_1 eoU_2 = (E_diag[..., np.newaxis] + f2) * rspmats_2[i] Ue_2 = rspmats_2[i] * E_diag[np.newaxis, ...] epsilon_2[i] += eoU_2 - Ue_2 # Assume some symmetry and calculate only part of the tensor. hyperpolarizability = np.zeros(shape=(6, 3)) off1 = [0, 1, 2, 0, 0, 1] off2 = [0, 1, 2, 1, 2, 2] for r in range(6): b = off1[r] c = off2[r] for a in range(3): tl1 = np.trace(rspmats_2[a].T.dot(G_1[b]).dot(rspmats_1[c])[:nocc_alph, :nocc_alph]) tl2 = np.trace(rspmats_1[c].dot(G_1[b]).dot(rspmats_2[a].T)[:nocc_alph, :nocc_alph]) tl3 = np.trace(rspmats_2[a].T.dot(G_1[c]).dot(rspmats_1[b])[:nocc_alph, :nocc_alph]) tl4 = np.trace(rspmats_1[b].dot(G_1[c]).dot(rspmats_2[a].T)[:nocc_alph, :nocc_alph]) tl5 = np.trace(rspmats_1[c].dot(-G_2[a].T).dot(rspmats_1[b])[:nocc_alph, :nocc_alph]) tl6 = np.trace(rspmats_1[b].dot(-G_2[a].T).dot(rspmats_1[c])[:nocc_alph, :nocc_alph]) tr1 = np.trace( rspmats_1[c].dot(rspmats_1[b]).dot(-epsilon_2[a].T)[:nocc_alph, :nocc_alph] ) tr2 = np.trace( rspmats_1[b].dot(rspmats_1[c]).dot(-epsilon_2[a].T)[:nocc_alph, :nocc_alph] ) tr3 = np.trace( rspmats_1[c].dot(rspmats_2[a].T).dot(epsilon_1[b])[:nocc_alph, :nocc_alph] ) tr4 = np.trace( rspmats_2[a].T.dot(rspmats_1[c]).dot(epsilon_1[b])[:nocc_alph, :nocc_alph] ) tr5 = np.trace( rspmats_1[b].dot(rspmats_2[a].T).dot(epsilon_1[c])[:nocc_alph, :nocc_alph] ) tr6 = np.trace( rspmats_2[a].T.dot(rspmats_1[b]).dot(epsilon_1[c])[:nocc_alph, :nocc_alph] ) tl = tl1 + tl2 + tl3 + tl4 + tl5 + tl6 tr = tr1 + tr2 + tr3 + tr4 + tr5 + tr6 hyperpolarizability[r, a] = -2 * (tl - tr) # pylint: disable=C0326 ref = np.array( [ [0.00000000, 0.00000000, 1.92505358], [0.00000000, 0.00000000, -31.33652886], [0.00000000, 0.00000000, -13.92830863], [0.00000000, 0.00000000, 0.00000000], [-1.80626084, 0.00000000, 0.00000000], [0.00000000, -31.13504192, 0.00000000], ] ) ref_avgs = np.array([0.00000000, 0.00000000, 45.69300223]) ref_avg = 45.69300223 diff = np.abs(ref - hyperpolarizability) print("abs diff") print(diff) thresh = 2.5e-04 assert np.all(diff < thresh) print("hyperpolarizability: SHG, (-{}; {}, {}), symmetry-unique components".format(f2, f1, f1)) print(hyperpolarizability) print("ref") print(ref) # Transpose all frequency-doubled quantities (+2w) to get -2w. for i in range(ncomp): rspmats_2[i] = rspmats_2[i].T G_2[i] = -G_2[i].T epsilon_2[i] = -epsilon_2[i].T # Assume some symmetry and calculate only part of the tensor. This # time, work with the in-place manipulated quantities (this tests # their correctness). mU = (rspmats_2, rspmats_1) mG = (G_2, G_1) me = (epsilon_2, epsilon_1) hyperpolarizability = np.zeros(shape=(6, 3)) off1 = [0, 1, 2, 0, 0, 1] off2 = [0, 1, 2, 1, 2, 2] for r in range(6): b = off1[r] c = off2[r] for a in range(3): tl1 = np.trace(mU[0][a].dot(mG[1][b]).dot(mU[1][c])[:nocc_alph, :nocc_alph]) tl2 = np.trace(mU[1][c].dot(mG[1][b]).dot(mU[0][a])[:nocc_alph, :nocc_alph]) tl3 = np.trace(mU[0][a].dot(mG[1][c]).dot(mU[1][b])[:nocc_alph, :nocc_alph]) tl4 = np.trace(mU[1][b].dot(mG[1][c]).dot(mU[0][a])[:nocc_alph, :nocc_alph]) tl5 = np.trace(mU[1][c].dot(mG[0][a]).dot(mU[1][b])[:nocc_alph, :nocc_alph]) tl6 = np.trace(mU[1][b].dot(mG[0][a]).dot(mU[1][c])[:nocc_alph, :nocc_alph]) tr1 = np.trace(mU[1][c].dot(mU[1][b]).dot(me[0][a])[:nocc_alph, :nocc_alph]) tr2 = np.trace(mU[1][b].dot(mU[1][c]).dot(me[0][a])[:nocc_alph, :nocc_alph]) tr3 = np.trace(mU[1][c].dot(mU[0][a]).dot(me[1][b])[:nocc_alph, :nocc_alph]) tr4 = np.trace(mU[0][a].dot(mU[1][c]).dot(me[1][b])[:nocc_alph, :nocc_alph]) tr5 = np.trace(mU[1][b].dot(mU[0][a]).dot(me[1][c])[:nocc_alph, :nocc_alph]) tr6 = np.trace(mU[0][a].dot(mU[1][b]).dot(me[1][c])[:nocc_alph, :nocc_alph]) tl = [tl1, tl2, tl3, tl4, tl5, tl6] tr = [tr1, tr2, tr3, tr4, tr5, tr6] hyperpolarizability[r, a] = -2 * (sum(tl) - sum(tr)) assert np.all(np.abs(ref - hyperpolarizability) < thresh) # Assume no symmetry and calculate the full tensor. hyperpolarizability_full = np.zeros(shape=(3, 3, 3)) # components x, y, z for ip, p in enumerate(list(product(range(3), range(3), range(3)))): a, b, c = p tl, tr = [], [] # 1st tuple -> index a, b, c (*not* x, y, z!) # 2nd tuple -> index frequency (0 -> -2w, 1 -> +w) for iq, q in enumerate(list(permutations(zip(p, (0, 1, 1)), 3))): d, e, f = q tlp = (mU[d[1]][d[0]]).dot(mG[e[1]][e[0]]).dot(mU[f[1]][f[0]]) tle = np.trace(tlp[:nocc_alph, :nocc_alph]) tl.append(tle) trp = (mU[d[1]][d[0]]).dot(mU[e[1]][e[0]]).dot(me[f[1]][f[0]]) tre = np.trace(trp[:nocc_alph, :nocc_alph]) tr.append(tre) hyperpolarizability_full[a, b, c] = -2 * (sum(tl) - sum(tr)) print("hyperpolarizability: SHG, (-{}; {}, {}), full tensor".format(f2, f1, f1)) print(hyperpolarizability_full) # Check that the elements of the reduced and full tensors are # equivalent. for r in range(6): b = off1[r] c = off2[r] for a in range(3): diff = hyperpolarizability[r, a] - hyperpolarizability_full[a, b, c] # TODO why not 14? assert abs(diff) < 1.0e-13 # Compute averages and compare to reference. avgs, avg = utils.form_first_hyperpolarizability_averages(hyperpolarizability_full) assert np.allclose(ref_avgs, avgs, rtol=0, atol=1.0e-3) assert np.allclose([ref_avg], [avg], rtol=0, atol=1.0e-3) print(avgs) print(avg) return
def test_final_result_rhf_h2o_sto3g_rpa_singlet() -> None: """Test correctness of the final result for water/STO-3G with full RPA for singlet response induced by the dipole length operator (the electric polarizability) computed with quantities from disk. """ hamiltonian = Hamiltonian.RPA spin = Spin.singlet C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = np.asarray([5, 2, 5, 2], dtype=int) stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = solvers.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = AO2MOTransformationType.full driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(hamiltonian=hamiltonian, spin=spin, program=None, program_obj=None) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[7.93556221, 0.0, 0.0], [0.0, 3.06821077, 0.0], [0.0, 0.0, 0.05038621]]) result__0_02 = np.array([[7.94312371, 0.0, 0.0], [0.0, 3.07051688, 0.0], [0.0, 0.0, 0.05054685]]) result__0_06 = np.array([[8.00414009, 0.0, 0.0], [0.0, 3.08913608, 0.0], [0.0, 0.0, 0.05186977]]) result__0_10 = np.array([[8.1290378, 0.0, 0.0], [0.0, 3.12731363, 0.0], [0.0, 0.0, 0.05473482]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) # Reminder: there's no call to do SCF here because we already have # the MO coefficients. mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability( Program.PySCF, mol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, frequencies=frequencies, ) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol)
def test_final_result_rhf_h2o_sto3g_tda_triplet() -> None: """Test correctness of the final result for water/STO-3G with the TDA approximation/CIS for triplet response induced by the dipole length operator computed with quantities from disk. """ hamiltonian = Hamiltonian.TDA spin = Spin.triplet C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = np.asarray([5, 2, 5, 2], dtype=int) stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = solvers.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = AO2MOTransformationType.full driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(hamiltonian=hamiltonian, spin=spin, program=None, program_obj=None) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[14.64430714, 0.0, 0.0], [0.0, 8.80921432, 0.0], [0.0, 0.0, 0.06859496]]) result__0_02 = np.array([[14.68168443, 0.0, 0.0], [0.0, 8.83562647, 0.0], [0.0, 0.0, 0.0689291]]) result__0_06 = np.array([[14.98774296, 0.0, 0.0], [0.0, 9.0532224, 0.0], [0.0, 0.0, 0.07172414]]) result__0_10 = np.array([[15.63997724, 0.0, 0.0], [0.0, 9.52504267, 0.0], [0.0, 0.0, 0.07805428]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability( Program.PySCF, mol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, frequencies=frequencies, ) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol)
def test_first_hyperpolarizability_static_rhf_wigner_explicit(): mol = molecule_water_sto3g_angstrom() mol.build() mf = pyscf.scf.RHF(mol) mf.kernel() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = utils.occupations_from_pyscf_mol(mol, C) nocc_alph, nvirt_alph, _, _ = occupations nov_alph = nocc_alph * nvirt_alph norb = nocc_alph + nvirt_alph # calculate linear response vectors for electric dipole operator calculator = electric.Polarizability(Program.PySCF, mol, C, E, occupations, frequencies=[0.0]) calculator.form_operators() calculator.run() calculator.form_results() polarizability = calculator.polarizabilities[0] print("polarizability (static)") print(polarizability) operator = calculator.driver.solver.operators[0] rhsvecs = operator.mo_integrals_ai_supervector_alph rspvecs = operator.rspvecs_alph[0] ## Form the full [norb, norb] representation of everything. # Response vectors: transform X_{ia} and Y_{ia} -> U_{p,q} # 0. 'a' is fast index, 'i' slow # 1. rspvec == [X Y] # 2. U_{p, q} -> zero # 3. place X_{ia} into U_{i, a} # 4. place Y_{ia} into U_{a, i} ncomp = rhsvecs.shape[0] rspmats = np.zeros(shape=(ncomp, norb, norb)) for i in range(ncomp): rspvec = rspvecs[i, :, 0] x = rspvec[:nov_alph] y = rspvec[nov_alph:] x_full = utils.repack_vector_to_matrix(x, (nvirt_alph, nocc_alph)) y_full = utils.repack_vector_to_matrix(y, (nvirt_alph, nocc_alph)) rspmats[i, :nocc_alph, nocc_alph:] = x_full.T rspmats[i, nocc_alph:, :nocc_alph] = y_full rhsmats = np.zeros(shape=(ncomp, norb, norb)) for i in range(ncomp): rhsvec = rhsvecs[i, :, 0] rhsvec_top = rhsvec[:nov_alph] rhsvec_bot = rhsvec[nov_alph:] rhsvec_top_mat = utils.repack_vector_to_matrix(rhsvec_top, (nvirt_alph, nocc_alph)) rhsvec_bot_mat = utils.repack_vector_to_matrix(rhsvec_bot, (nvirt_alph, nocc_alph)) rhsmats[i, :nocc_alph, nocc_alph:] = rhsvec_top_mat.T rhsmats[i, nocc_alph:, :nocc_alph] = rhsvec_bot_mat polarizability_full = np.empty_like(polarizability) for a in (0, 1, 2): for b in (0, 1, 2): polarizability_full[a, b] = 2 * np.trace(rhsmats[a, ...].T.dot( rspmats[b, ...])) np.testing.assert_almost_equal(polarizability, polarizability_full) # V_{p,q} <- full MO transformation of right hand side integrals_ao = operator.ao_integrals integrals_mo = np.empty_like(integrals_ao) for i in range(ncomp): integrals_mo[i, ...] = (C[0, ...].T).dot(integrals_ao[i, ...]).dot(C[0, ...]) G = np.empty_like(rspmats) C = mf.mo_coeff # TODO I feel as though if I have all the MO-basis two-electron # integrals, I shouldn't need another JK build. for i in range(ncomp): V = integrals_mo[i, ...] Dl = (C[:, nocc_alph:].dot( utils.repack_vector_to_matrix(rspvecs[i, :nov_alph, 0], (nvirt_alph, nocc_alph))).dot( C[:, :nocc_alph].T)) J, K = mf.get_jk(mol, Dl, hermi=0) F_AO = -(4 * J - K - K.T) F_MO = (C.T).dot(F_AO).dot(C) G[i, ...] = V + F_MO E_diag = np.diag(E[0, ...]) epsilon = G.copy() omega = 0 for i in range(ncomp): eoU = (E_diag[..., np.newaxis] + omega) * rspmats[i, ...] Ue = rspmats[i, ...] * E_diag[np.newaxis, ...] epsilon[i, ...] += eoU - Ue # Assume some symmetry and calculate only part of the tensor. hyperpolarizability = np.zeros(shape=(6, 3)) off1 = [0, 1, 2, 0, 0, 1] off2 = [0, 1, 2, 1, 2, 2] for r in range(6): b = off1[r] c = off2[r] for a in range(3): tl1 = 2 * np.trace(rspmats[a, ...].dot(G[b, ...]).dot( rspmats[c, ...])[:nocc_alph, :nocc_alph]) tl2 = 2 * np.trace(rspmats[a, ...].dot(G[c, ...]).dot( rspmats[b, ...])[:nocc_alph, :nocc_alph]) tl3 = 2 * np.trace(rspmats[c, ...].dot(G[a, ...]).dot( rspmats[b, ...])[:nocc_alph, :nocc_alph]) tr1 = np.trace(rspmats[c, ...].dot(rspmats[b, ...]).dot( epsilon[a, ...])[:nocc_alph, :nocc_alph]) tr2 = np.trace(rspmats[b, ...].dot(rspmats[c, ...]).dot( epsilon[a, ...])[:nocc_alph, :nocc_alph]) tr3 = np.trace(rspmats[c, ...].dot(rspmats[a, ...]).dot( epsilon[b, ...])[:nocc_alph, :nocc_alph]) tr4 = np.trace(rspmats[a, ...].dot(rspmats[c, ...]).dot( epsilon[b, ...])[:nocc_alph, :nocc_alph]) tr5 = np.trace(rspmats[b, ...].dot(rspmats[a, ...]).dot( epsilon[c, ...])[:nocc_alph, :nocc_alph]) tr6 = np.trace(rspmats[a, ...].dot(rspmats[b, ...]).dot( epsilon[c, ...])[:nocc_alph, :nocc_alph]) tl = tl1 + tl2 + tl3 tr = tr1 + tr2 + tr3 + tr4 + tr5 + tr6 hyperpolarizability[r, a] = 2 * (tl - tr) # pylint: disable=C0326 ref = np.array([ [-8.86822254, 0.90192130, -0.50796586], [1.98744058, 5.13635628, -2.95319400], [0.66008119, 1.62699646, -0.85632412], [0.90192130, 1.98744058, -1.09505123], [-0.50796586, -1.09505123, 0.66008119], [-1.09505123, -2.95319400, 1.62699646], ]) ref_avgs = np.array([6.22070078, -7.66527404, 4.31748398]) ref_avg = 10.77470242 thresh = 1.5e-4 assert np.all(np.abs(ref - hyperpolarizability) < thresh) print("hyperpolarizability (static), symmetry-unique components") print(hyperpolarizability) # Assume no symmetry and calculate the full tensor. hyperpolarizability_full = np.zeros(shape=(3, 3, 3)) for p in product(range(3), range(3), range(3)): a, b, c = p tl, tr = 0, 0 for q in permutations(p, 3): d, e, f = q tl += np.trace(rspmats[d, ...].dot(G[e, ...]).dot( rspmats[f, ...])[:nocc_alph, :nocc_alph]) tr += np.trace(rspmats[d, ...].dot(rspmats[e, ...]).dot( epsilon[f, ...])[:nocc_alph, :nocc_alph]) hyperpolarizability_full[a, b, c] = 2 * (tl - tr) print("hyperpolarizability (static), full tensor") print(hyperpolarizability_full) # Check that the elements of the reduced and full tensors are # equivalent. thresh = 1.0e-14 for r in range(6): b = off1[r] c = off2[r] for a in range(3): diff = hyperpolarizability[r, a] - hyperpolarizability_full[a, b, c] assert abs(diff) < thresh # Compute averages and compare to reference. # This is the slow way. # avgs = [] # for i in range(3): # avg_c = 0 # for j in range(3): # avg_c += hyperpolarizability_full[i, j, j] + hyperpolarizability_full[j, i, j] + hyperpolarizability_full[j, j, i] # avgs.append((-1/3) * avg_c) # print(np.asarray(avgs)) x = hyperpolarizability_full # This is the simplest non-einsum way. # avgs = (-1 / 3) * np.asarray([np.trace(x[i, :, :] + x[:, i, :] + x[:, :, i]) for i in range(3)]) # This is the best way. avgs = (-1 / 3) * (np.einsum("ijj->i", x) + np.einsum("jij->i", x) + np.einsum("jji->i", x)) # print(list(set([''.join(p) for p in list(permutations('ijj', 3))]))) assert np.allclose(ref_avgs, avgs, rtol=0, atol=1.0e-3) avg = np.sum(avgs**2)**(1 / 2) assert np.allclose([ref_avg], [avg], rtol=0, atol=1.0e-3) print(avgs) print(avg) utils_avgs, utils_avg = utils.form_first_hyperpolarizability_averages(x) assert np.allclose(avgs, utils_avgs, rtol=0, atol=1.0e-13) assert np.allclose([avg], [utils_avg], rtol=0, atol=1.0e-13) return
def test_final_result_rhf_h2o_sto3g_rpa_triplet() -> None: """Test correctness of the final result for water/STO-3G with full RPA for triplet response induced by the dipole length operator computed with quantities from disk. """ hamiltonian = Hamiltonian.RPA spin = Spin.triplet C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = np.asarray([5, 2, 5, 2], dtype=int) stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = solvers.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = AO2MOTransformationType.full driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(hamiltonian=hamiltonian, spin=spin, program=None, program_obj=None) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[26.59744305, 0.0, 0.0], [0.0, 18.11879557, 0.0], [0.0, 0.0, 0.07798969]]) result__0_02 = np.array([[26.68282287, 0.0, 0.0], [0.0, 18.19390051, 0.0], [0.0, 0.0, 0.07837521]]) result__0_06 = np.array([[27.38617401, 0.0, 0.0], [0.0, 18.81922578, 0.0], [0.0, 0.0, 0.08160226]]) result__0_10 = np.array([[28.91067234, 0.0, 0.0], [0.0, 20.21670386, 0.0], [0.0, 0.0, 0.08892512]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability( Program.PySCF, mol, cphf.CPHF(solvers.ExactInv(C, E, occupations)), C, E, occupations, frequencies=frequencies, ) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol)
def test_ECD_RPA_singlet_BC2H4_cation_HF_STO3G(): ref = BC2H4_cation_HF_STO3G_RPA_singlet_nwchem nroots = ref["nroots"] mol = molecules.molecule_bc2h4_cation_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 = utils.occupations_from_pyscf_mol(mol, C) ecd_dipvel_rpa = ecd.ECD(Program.PySCF, mol, C, E, occupations, do_dipvel=True) ecd_dipvel_rpa.form_operators() ecd_dipvel_rpa.run(hamiltonian="rpa", spin="singlet") ecd_dipvel_rpa.form_results() print("excitation energies") ref_etenergies = np.array(ref["etenergies"]) res_etenergies = ecd_dipvel_rpa.driver.solver.eigvals.real[:nroots] print("ref, res") for refval, resval in zip(ref_etenergies, res_etenergies): print(refval, resval) thresh = 1.0e-7 for i in range(nroots): abs_diff = abs(ref_etenergies[i] - res_etenergies[i]) assert abs_diff < thresh print("dipole (length) oscillator strengths") ref_etoscslen = np.array(ref["etoscslen"]) res_etoscslen = ecd_dipvel_rpa.driver.solver.operators[1].total_oscillator_strengths[ :nroots ] print("ref, res") for refval, resval in zip(ref_etoscslen, res_etoscslen): print(refval, resval) thresh = 1.0e-5 for i in range(nroots): abs_diff = abs(ref_etoscslen[i] - res_etoscslen[i]) assert abs_diff < thresh # TODO print("TODO dipole (mixed length/velocity) oscillator strengths") # TODO print("TODO dipole (velocity) oscillator strengths") ref_etoscsvel = np.array(ref["etoscsvel"]) res_etoscsvel = ecd_dipvel_rpa.driver.solver.operators[2].total_oscillator_strengths[ :nroots ] # print('ref, res') # for refval, resval in zip(ref_etoscsvel, res_etoscsvel): # print(refval, resval) # print(ref_etoscsvel / res_etoscsvel) # print(res_etoscsvel / ref_etoscsvel) print("rotatory strengths (length)") ref_etrotstrlen = np.array(ref["etrotstrlen"]) res_etrotstrlen = ecd_dipvel_rpa.rotational_strengths_diplen[:nroots] print("ref, res") for refval, resval in zip(ref_etrotstrlen, res_etrotstrlen): print(refval, resval) # TODO unlike other quantities, the error isn't uniformly # distributed among the roots; how should this be handled? thresh = 1.5e1 for i in range(nroots): abs_diff = abs(ref_etrotstrlen[i] - res_etrotstrlen[i]) assert abs_diff < thresh print("rotatory strengths (velocity)") ref_etrotstrvel = np.array(ref["etrotstrvel"]) res_etrotstrvel = ecd_dipvel_rpa.rotational_strengths_dipvel[:nroots] print("ref, res") for refval, resval in zip(ref_etrotstrvel, res_etrotstrvel): print(refval, resval) thresh = 1.0e-2 for i in range(nroots): abs_diff = abs(ref_etrotstrvel[i] - res_etrotstrvel[i]) assert abs_diff < thresh # with open(os.path.join(refdir, 'BC2H4_cation', 'nwchem_singlet_rpa_velocity_root.str')) as fh: # ref_str = fh.read() # res_str = ecd_dipvel_rpa.print_results_nwchem() # assert res_str == ref_str # print(ecd_dipvel_rpa.print_results_nwchem()) # print(ecd_dipvel_rpa.print_results_orca()) # print(ecd_dipvel_rpa.print_results_qchem()) # tmom_diplen = ecd_dipvel_rpa.driver.solver.operators[1].transition_moments # tmom_dipvel = ecd_dipvel_rpa.driver.solver.operators[2].transition_moments # print(tmom_diplen) # print('dipole') # for i in range(nroots): # print((2 / 3) * res_etenergies[i] * np.dot(tmom_diplen[i], tmom_diplen[i])) # print('mixed') # for i in range(nroots): # print((2 / 3) * res_etenergies[i] * np.dot(tmom_diplen[i], tmom_dipvel[i])) # print('sum rule') # print('ref_etoscslen:', sum(ref_etoscslen)) # print('res_etoscslen:', sum(res_etoscslen)) # # print('ref_etoscsmix:', sum(ref_etoscsmix)) # # print('res_etoscsmix:', sum(res_etoscsmix)) # print('ref_etoscsvel:', sum(ref_etoscsvel)) # print('res_etoscsvel:', sum(res_etoscsvel)) return
def test_first_hyperpolarizability_or_rhf_wigner_explicit(): mol = molecule_water_sto3g_angstrom() mol.build() mf = pyscf.scf.RHF(mol) mf.kernel() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = utils.occupations_from_pyscf_mol(mol, C) nocc_alph, nvirt_alph, _, _ = occupations nov_alph = nocc_alph * nvirt_alph norb = nocc_alph + nvirt_alph # calculate linear response vectors for electric dipole operator f1 = 0.0 f2 = 0.0773178 frequencies = [f1, f2] calculator = electric.Polarizability(Program.PySCF, mol, C, E, occupations, frequencies=frequencies) calculator.form_operators() calculator.run() calculator.form_results() polarizability_1 = calculator.polarizabilities[0] polarizability_2 = calculator.polarizabilities[1] print("polarizability (static)") print(polarizability_1) print("polarizability: {} a.u.".format(f2)) print(polarizability_2) # each operator contains multiple sets of response vectors, one # set of components for each frequency assert isinstance(calculator.driver.solver.operators, list) assert len(calculator.driver.solver.operators) == 1 operator = calculator.driver.solver.operators[0] rhsvecs = operator.mo_integrals_ai_supervector_alph assert isinstance(operator.rspvecs_alph, list) assert len(operator.rspvecs_alph) == 2 rspvecs_1 = operator.rspvecs_alph[0] rspvecs_2 = operator.rspvecs_alph[1] ## Form the full [norb, norb] representation of everything. # Response vectors: transform X_{ia} and Y_{ia} -> U_{p,q} # 0. 'a' is fast index, 'i' slow # 1. rspvec == [X Y] # 2. U_{p, q} -> zero # 3. place X_{ia} into U_{i, a} # 4. place Y_{ia} into U_{a, i} ncomp = rhsvecs.shape[0] rspmats_1 = np.zeros(shape=(ncomp, norb, norb)) rspmats_2 = np.zeros(shape=(ncomp, norb, norb)) for i in range(ncomp): rspvec_1 = rspvecs_1[i, :, 0] rspvec_2 = rspvecs_2[i, :, 0] x_1 = rspvec_1[:nov_alph] y_1 = rspvec_1[nov_alph:] x_2 = rspvec_2[:nov_alph] y_2 = rspvec_2[nov_alph:] x_full_1 = utils.repack_vector_to_matrix(x_1, (nvirt_alph, nocc_alph)) y_full_1 = utils.repack_vector_to_matrix(y_1, (nvirt_alph, nocc_alph)) x_full_2 = utils.repack_vector_to_matrix(x_2, (nvirt_alph, nocc_alph)) y_full_2 = utils.repack_vector_to_matrix(y_2, (nvirt_alph, nocc_alph)) rspmats_1[i, :nocc_alph, nocc_alph:] = y_full_1.T rspmats_1[i, nocc_alph:, :nocc_alph] = x_full_1 rspmats_2[i, :nocc_alph, nocc_alph:] = y_full_2.T rspmats_2[i, nocc_alph:, :nocc_alph] = x_full_2 rhsmats = np.zeros(shape=(ncomp, norb, norb)) for i in range(ncomp): rhsvec = rhsvecs[i, :, 0] rhsvec_top = rhsvec[:nov_alph] rhsvec_bot = rhsvec[nov_alph:] rhsvec_top_mat = utils.repack_vector_to_matrix(rhsvec_top, (nvirt_alph, nocc_alph)) rhsvec_bot_mat = utils.repack_vector_to_matrix(rhsvec_bot, (nvirt_alph, nocc_alph)) rhsmats[i, :nocc_alph, nocc_alph:] = rhsvec_top_mat.T rhsmats[i, nocc_alph:, :nocc_alph] = rhsvec_bot_mat polarizability_full_1 = np.empty_like(polarizability_1) polarizability_full_2 = np.empty_like(polarizability_2) for a in (0, 1, 2): for b in (0, 1, 2): polarizability_full_1[a, b] = 2 * np.trace(rhsmats[a, ...].T.dot( rspmats_1[b, ...])) polarizability_full_2[a, b] = 2 * np.trace(rhsmats[a, ...].T.dot( rspmats_2[b, ...])) np.testing.assert_almost_equal(polarizability_1, -polarizability_full_1) np.testing.assert_almost_equal(polarizability_2, -polarizability_full_2) # V_{p,q} <- full MO transformation of right hand side integrals_ao = operator.ao_integrals integrals_mo = np.empty_like(integrals_ao) for i in range(ncomp): integrals_mo[i, ...] = (C[0, ...].T).dot(integrals_ao[i, ...]).dot(C[0, ...]) # from pyresponse.ao2mo import AO2MOpyscf # ao2mo = AO2MOpyscf(C, pyscfmol=mol) # ao2mo.perform_rhf_full() # tei_mo = ao2mo.tei_mo[0] G_1 = np.empty_like(rspmats_1) G_2 = np.empty_like(rspmats_2) C = mf.mo_coeff # TODO I feel as though if I have all the MO-basis two-electron # integrals, I shouldn't need another JK build. for i in range(ncomp): V = integrals_mo[i, ...] Dl_1 = (C[:, :nocc_alph]).dot(rspmats_1[i, :nocc_alph, :]).dot(C.T) Dr_1 = (-C).dot(rspmats_1[i, :, :nocc_alph]).dot(C[:, :nocc_alph].T) D_1 = Dl_1 + Dr_1 Dl_2 = (C[:, :nocc_alph]).dot(rspmats_2[i, :nocc_alph, :]).dot(C.T) Dr_2 = (-C).dot(rspmats_2[i, :, :nocc_alph]).dot(C[:, :nocc_alph].T) D_2 = Dl_2 + Dr_2 J_1, K_1 = mf.get_jk(mol, D_1, hermi=0) J_2, K_2 = mf.get_jk(mol, D_2, hermi=0) F_AO_1 = 2 * J_1 - K_1 F_AO_2 = 2 * J_2 - K_2 F_MO_1 = (C.T).dot(F_AO_1).dot(C) F_MO_2 = (C.T).dot(F_AO_2).dot(C) G_1[i, ...] = V + F_MO_1 G_2[i, ...] = V + F_MO_2 E_diag = np.diag(E[0, ...]) epsilon_1 = G_1.copy() epsilon_2 = G_2.copy() for i in range(ncomp): eoU_1 = (E_diag[..., np.newaxis] + f1) * rspmats_1[i, ...] Ue_1 = rspmats_1[i, ...] * E_diag[np.newaxis, ...] epsilon_1[i, ...] += eoU_1 - Ue_1 eoU_2 = (E_diag[..., np.newaxis] + f2) * rspmats_2[i, ...] Ue_2 = rspmats_2[i, ...] * E_diag[np.newaxis, ...] epsilon_2[i, ...] += eoU_2 - Ue_2 # Assume some symmetry and calculate only part of the tensor. hyperpolarizability = np.zeros(shape=(6, 3)) off1 = [0, 1, 2, 0, 0, 1] off2 = [0, 1, 2, 1, 2, 2] for r in range(6): b = off1[r] c = off2[r] for a in range(3): # _1 -> 0 # _2 -> +w # a is _1, b is _2, c is _2 transposed/negated tl1 = np.trace(rspmats_1[a, ...].dot(G_2[b, ...]).dot( rspmats_2[c, ...].T)[:nocc_alph, :nocc_alph]) tl2 = np.trace(rspmats_2[c, ...].T.dot(G_2[b, ...]).dot( rspmats_1[a, ...])[:nocc_alph, :nocc_alph]) tl3 = np.trace(rspmats_1[a, ...].dot(-G_2[c, ...].T).dot( rspmats_2[b, ...])[:nocc_alph, :nocc_alph]) tl4 = np.trace(rspmats_2[b, ...].dot(-G_2[c, ...].T).dot( rspmats_1[a, ...])[:nocc_alph, :nocc_alph]) tl5 = np.trace(rspmats_2[c, ...].T.dot(G_1[a, ...]).dot( rspmats_2[b, ...])[:nocc_alph, :nocc_alph]) tl6 = np.trace(rspmats_2[b, ...].dot(G_1[a, ...]).dot( rspmats_2[c, ...].T)[:nocc_alph, :nocc_alph]) tr1 = np.trace(rspmats_2[c, ...].T.dot(rspmats_2[b, ...]).dot( epsilon_1[a, ...])[:nocc_alph, :nocc_alph]) tr2 = np.trace(rspmats_2[b, ...].dot(rspmats_2[c, ...].T).dot( epsilon_1[a, ...])[:nocc_alph, :nocc_alph]) tr3 = np.trace(rspmats_2[c, ...].T.dot(rspmats_1[a, ...]).dot( epsilon_2[b, ...])[:nocc_alph, :nocc_alph]) tr4 = np.trace(rspmats_1[a, ...].dot(rspmats_2[c, ...].T).dot( epsilon_2[b, ...])[:nocc_alph, :nocc_alph]) tr5 = np.trace(rspmats_2[b, ...].dot( rspmats_1[a, ...]).dot(-epsilon_2[c, ...].T)[:nocc_alph, :nocc_alph]) tr6 = np.trace(rspmats_1[a, ...].dot( rspmats_2[b, ...]).dot(-epsilon_2[c, ...].T)[:nocc_alph, :nocc_alph]) tl = tl1 + tl2 + tl3 + tl4 + tl5 + tl6 tr = tr1 + tr2 + tr3 + tr4 + tr5 + tr6 hyperpolarizability[r, a] = -2 * (tl - tr) # pylint: disable=C0326 ref = np.array([ [-9.02854579, 0.92998934, -0.52377445], [2.01080066, 5.23470702, -3.01208409], [0.66669794, 1.66112712, -0.87205853], [0.92021130, 2.01769267, -1.11067223], [-0.51824440, -1.11067586, 0.67140102], [-1.10887175, -3.00950655, 1.65659586], ]) ref_avgs = np.array([6.34331713, -7.81628395, 4.40251201]) ref_avg = 10.98699590 thresh = 4.0e-5 assert np.all(np.abs(ref - hyperpolarizability) < thresh) print("hyperpolarizability: OR, (0; {}, -{}), symmetry-unique components". format(f2, f2)) print(hyperpolarizability) return
def test_ECD_TDA_singlet_BC2H4_cation_HF_STO3G(): ref = BC2H4_cation_HF_STO3G_TDA_singlet_orca nroots = ref["nroots"] mol = molecules.molecule_bc2h4_cation_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 = utils.occupations_from_pyscf_mol(mol, C) ecd_dipvel_tda = ecd.ECD(Program.PySCF, mol, C, E, occupations, do_dipvel=True) ecd_dipvel_tda.form_operators() ecd_dipvel_tda.run(hamiltonian="tda", spin="singlet") ecd_dipvel_tda.form_results() print("excitation energies") ref_etenergies = np.array(ref["etenergies"]) res_etenergies = ecd_dipvel_tda.driver.solver.eigvals.real[:nroots] print("ref, res") for refval, resval in zip(ref_etenergies, res_etenergies): print(refval, resval) # TODO this might be from ORCA, should use NWChem instead thresh = 1.0e-3 for i in range(nroots): abs_diff = abs(ref_etenergies[i] - res_etenergies[i]) assert abs_diff < thresh print("dipole (length) oscillator strengths") ref_etoscslen = np.array(ref["etoscslen"]) res_etoscslen = ecd_dipvel_tda.driver.solver.operators[1].total_oscillator_strengths[ :nroots ] print("ref, res") for refval, resval in zip(ref_etoscslen, res_etoscslen): print(refval, resval) thresh = 1.0e-3 # np.testing.assert_allclose(ref_etoscslen, res_etoscslen) for i in range(nroots): abs_diff = abs(ref_etoscslen[i] - res_etoscslen[i]) assert abs_diff < thresh # TODO print("TODO dipole (mixed length/velocity) oscillator strengths") # TODO print("TODO dipole (velocity) oscillator strengths") print("rotatory strengths (length)") ref_etrotstrlen = np.array(ref["etrotstrlen"]) res_etrotstrlen = ecd_dipvel_tda.rotational_strengths_diplen[:nroots] print("ref, res") for refval, resval in zip(ref_etrotstrlen, res_etrotstrlen): print(refval, resval) # TODO unlike other quantities, the error isn't uniformly # distributed among the roots; how should this be handled? thresh = 1.0e2 for i in range(nroots): abs_diff = abs(ref_etrotstrlen[i] - res_etrotstrlen[i]) assert abs_diff < thresh # print('rotatory strengths (velocity)') # ref_etrotstrvel = np.array(ref['etrotstrvel']) # res_etrotstrvel = ecd_dipvel_tda.rotational_strengths_dipvel[:nroots] # print('ref, res') # for refval, resval in zip(ref_etrotstrvel, res_etrotstrvel): # print(refval, resval) # thresh = 1.0e-2 # for i in range(nroots): # abs_diff = abs(ref_etrotstrvel[i] - res_etrotstrvel[i]) # assert abs_diff < thresh # print(ecd_dipvel_tda.print_results_nwchem()) # print(ecd_dipvel_tda.print_results_orca()) # print(ecd_dipvel_tda.print_results_qchem()) return
def test_final_result_rhf_h2o_sto3g_tda_triplet(): hamiltonian = "tda" spin = "triplet" C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = [5, 2, 5, 2] stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = iterators.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = "full" driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(solver_type="exact", hamiltonian=hamiltonian, spin=spin) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[14.64430714, 0.0, 0.0], [0.0, 8.80921432, 0.0], [0.0, 0.0, 0.06859496]]) result__0_02 = np.array([[14.68168443, 0.0, 0.0], [0.0, 8.83562647, 0.0], [0.0, 0.0, 0.0689291]]) result__0_06 = np.array([[14.98774296, 0.0, 0.0], [0.0, 9.0532224, 0.0], [0.0, 0.0, 0.07172414]]) result__0_10 = np.array([[15.63997724, 0.0, 0.0], [0.0, 9.52504267, 0.0], [0.0, 0.0, 0.07805428]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability(Program.PySCF, mol, C, E, occupations, frequencies) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol) return
def test_final_result_rhf_h2o_sto3g_tda_singlet(): hamiltonian = "tda" spin = "singlet" C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = [5, 2, 5, 2] stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = iterators.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = "full" driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(solver_type="exact", hamiltonian=hamiltonian, spin=spin) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[8.89855952, 0.0, 0.0], [0.0, 4.00026556, 0.0], [0.0, 0.0, 0.0552774]]) result__0_02 = np.array([[8.90690928, 0.0, 0.0], [0.0, 4.00298342, 0.0], [0.0, 0.0, 0.05545196]]) result__0_06 = np.array([[8.97427725, 0.0, 0.0], [0.0, 4.02491517, 0.0], [0.0, 0.0, 0.05688918]]) result__0_10 = np.array([[9.11212633, 0.0, 0.0], [0.0, 4.06981937, 0.0], [0.0, 0.0, 0.05999934]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability(Program.PySCF, mol, C, E, occupations, frequencies) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol) return
def test_ORD_RPA_singlet_trithiolane_HF_STO3G(): ref = trithiolane_HF_STO3G_RPA_singlet pyscfmol = molecules.molecule_trithiolane_sto3g() pyscfmol.build() mf = pyscf.scf.RHF(pyscfmol) mf.scf() C = utils.fix_mocoeffs_shape(mf.mo_coeff) E = utils.fix_moenergies_shape(mf.mo_energy) occupations = utils.occupations_from_pyscf_mol(pyscfmol, C) frequencies = [0.0, 0.0773178, 0.128347] ord_solver = optrot.ORD( Program.PySCF, pyscfmol, C, E, occupations, frequencies=frequencies, do_dipvel=False, ) ord_solver.form_operators() ord_solver.run(hamiltonian="rpa", spin="singlet") ord_solver.form_results() print("Polarizabilities") assert len(frequencies) == len(ord_solver.polarizabilities) thresh = 5.0e-4 for idxf, frequency in enumerate(frequencies): ref_polar = ref[frequency]["polar"] res_polar = ord_solver.polarizabilities[idxf] abs_diff = abs(res_polar - ref_polar) print(idxf, frequency) print(res_polar) print(abs_diff) assert (abs_diff < thresh).all() # print('Electric dipole-magnetic dipole polarizabilities') # assert len(frequencies) == len(ord_solver.polarizabilities_lenmag) # # thresh # for idxf, frequency in enumerate(frequencies): # if 'dipmag' in ref[frequency]: # ref_dipmag = ref[frequency]['dipmag'] # res_dipmag = ord_solver.polarizabilities_lenmag[idxf] # print(idxf, frequency) # # print(ref_dipmag) # # print(res_dipmag) # print(res_dipmag / ref_dipmag) # print(r'\beta(\omega)') # thresh = 5.0e-2 # for idxf, frequency in enumerate(frequencies): # if 'orbeta' in ref[frequency]: # ref_beta = ref[frequency]['orbeta'] # # why no speed of light? atomic units... # # TODO why the (1/2)? # res_beta = -(0.5 / frequency) * ord_solver.solver.results[idxf][3:6, 0:3] # abs_diff = abs(res_beta - ref_beta) # print(idxf, frequency) # print(res_beta) # print(abs_diff) # assert (abs_diff < thresh).all() return
def test_final_result_rhf_h2o_sto3g_rpa_triplet(): hamiltonian = "rpa" spin = "triplet" C = utils.fix_mocoeffs_shape(utils.np_load(REFDIR / "C.npz")) E = utils.fix_moenergies_shape(utils.np_load(REFDIR / "F_MO.npz")) TEI_MO = utils.np_load(REFDIR / "TEI_MO.npz") # nocc_alph, nvirt_alph, nocc_beta, nvirt_beta occupations = [5, 2, 5, 2] stub = "h2o_sto3g_" dim = occupations[0] + occupations[1] mat_dipole_x = utils.parse_int_file_2(REFDIR / f"{stub}mux.dat", dim) mat_dipole_y = utils.parse_int_file_2(REFDIR / f"{stub}muy.dat", dim) mat_dipole_z = utils.parse_int_file_2(REFDIR / f"{stub}muz.dat", dim) solver = iterators.ExactInv(C, E, occupations) solver.tei_mo = (TEI_MO, ) solver.tei_mo_type = "full" driver = cphf.CPHF(solver) ao_integrals_dipole = np.stack((mat_dipole_x, mat_dipole_y, mat_dipole_z), axis=0) operator_dipole = operators.Operator(label="dipole", is_imaginary=False, is_spin_dependent=False) operator_dipole.ao_integrals = ao_integrals_dipole driver.add_operator(operator_dipole) frequencies = (0.0, 0.02, 0.06, 0.1) driver.set_frequencies(frequencies) driver.run(solver_type="exact", hamiltonian=hamiltonian, spin=spin) assert len(driver.results) == len(frequencies) result__0_00 = np.array([[26.59744305, 0.0, 0.0], [0.0, 18.11879557, 0.0], [0.0, 0.0, 0.07798969]]) result__0_02 = np.array([[26.68282287, 0.0, 0.0], [0.0, 18.19390051, 0.0], [0.0, 0.0, 0.07837521]]) result__0_06 = np.array([[27.38617401, 0.0, 0.0], [0.0, 18.81922578, 0.0], [0.0, 0.0, 0.08160226]]) result__0_10 = np.array([[28.91067234, 0.0, 0.0], [0.0, 20.21670386, 0.0], [0.0, 0.0, 0.08892512]]) atol = 1.0e-8 rtol = 0.0 np.testing.assert_allclose(driver.results[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(driver.results[3], result__0_10, rtol=rtol, atol=atol) mol = molecules.molecule_water_sto3g() mol.build() polarizability = electric.Polarizability(Program.PySCF, mol, C, E, occupations, frequencies) polarizability.form_operators() polarizability.run(hamiltonian=hamiltonian, spin=spin) polarizability.form_results() np.testing.assert_allclose(polarizability.polarizabilities[0], result__0_00, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[1], result__0_02, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[2], result__0_06, rtol=rtol, atol=atol) np.testing.assert_allclose(polarizability.polarizabilities[3], result__0_10, rtol=rtol, atol=atol) return