示例#1
0
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
示例#2
0
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)
示例#3
0
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"]
示例#4
0
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
示例#5
0
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)
示例#6
0
    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
示例#7
0
    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
示例#8
0
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)
示例#9
0
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)
示例#10
0
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
示例#11
0
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]