예제 #1
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)
예제 #2
0
    def form_explicit_hessian(self, hamiltonian: Hamiltonian, spin: Spin, frequency: float) -> None:

        assert hasattr(self, "tei_mo")
        assert self.tei_mo is not None
        assert len(self.tei_mo) in (1, 2, 4, 6)
        assert isinstance(self.tei_mo_type, AO2MOTransformationType)

        assert hamiltonian == Hamiltonian.TDA
        assert isinstance(spin, Spin)
        assert isinstance(frequency, (float, type(None)))

        nocc_alph, nvirt_alph, nocc_beta, nvirt_beta = self.occupations
        nov_alph = nocc_alph * nvirt_alph
        nov_beta = nocc_beta * nvirt_beta

        if not self.is_uhf:

            # Set up "function pointers".
            if self.tei_mo_type == AO2MOTransformationType.full:
                assert len(self.tei_mo) == 1
                tei_mo = self.tei_mo[0]
            elif self.tei_mo_type == AO2MOTransformationType.partial:
                assert len(self.tei_mo) == 2
                tei_mo_ovov = self.tei_mo[0]
                tei_mo_oovv = self.tei_mo[1]

            if self.tei_mo_type == AO2MOTransformationType.full:
                if spin == Spin.singlet:
                    A = form_rpa_a_matrix_mo_singlet_full(self.moenergies[0], tei_mo, nocc_alph)
                elif spin == Spin.triplet:
                    A = form_rpa_a_matrix_mo_triplet_full(self.moenergies[0], tei_mo, nocc_alph)
            elif self.tei_mo_type == AO2MOTransformationType.partial:
                if spin == Spin.singlet:
                    A = form_rpa_a_matrix_mo_singlet_partial(
                        self.moenergies[0], tei_mo_ovov, tei_mo_oovv
                    )
                elif spin == Spin.triplet:
                    A = form_rpa_a_matrix_mo_triplet_partial(self.moenergies[0], tei_mo_oovv)

            self.explicit_hessian = A

        else:
            # TODO UHF
            pass
예제 #3
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)
예제 #4
0
    def form_explicit_hessian(self, hamiltonian: Hamiltonian, spin: Spin, frequency: float) -> None:

        assert self.tei_mo is not None
        assert len(self.tei_mo) in (1, 2, 4, 6)
        assert isinstance(self.tei_mo_type, AO2MOTransformationType)

        assert isinstance(hamiltonian, Hamiltonian)
        assert isinstance(spin, Spin)
        assert isinstance(frequency, (float, type(None)))

        nocc_alph, nvirt_alph, nocc_beta, nvirt_beta = self.occupations
        nov_alph = nocc_alph * nvirt_alph
        nov_beta = nocc_beta * nvirt_beta

        superoverlap_alph = (
            np.block(
                [
                    [np.eye(nov_alph), np.zeros(shape=(nov_alph, nov_alph))],
                    [np.zeros(shape=(nov_alph, nov_alph)), -np.eye(nov_alph)],
                ]
            )
            * frequency
        )

        if not self.is_uhf:

            # Set up "function pointers".
            if self.tei_mo_type == AO2MOTransformationType.full:
                assert len(self.tei_mo) == 1
                tei_mo = self.tei_mo[0]
            elif self.tei_mo_type == AO2MOTransformationType.partial:
                assert len(self.tei_mo) == 2
                tei_mo_ovov = self.tei_mo[0]
                tei_mo_oovv = self.tei_mo[1]

            if self.tei_mo_type == AO2MOTransformationType.full:
                if hamiltonian == Hamiltonian.RPA and spin == Spin.singlet:
                    A = form_rpa_a_matrix_mo_singlet_full(self.moenergies[0], tei_mo, nocc_alph)
                    B = form_rpa_b_matrix_mo_singlet_full(tei_mo, nocc_alph)
                elif hamiltonian == Hamiltonian.RPA and spin == Spin.triplet:
                    A = form_rpa_a_matrix_mo_triplet_full(self.moenergies[0], tei_mo, nocc_alph)
                    B = form_rpa_b_matrix_mo_triplet_full(tei_mo, nocc_alph)
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.singlet:
                    A = form_rpa_a_matrix_mo_singlet_full(self.moenergies[0], tei_mo, nocc_alph)
                    B = np.zeros(shape=(nov_alph, nov_alph))
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.triplet:
                    A = form_rpa_a_matrix_mo_triplet_full(self.moenergies[0], tei_mo, nocc_alph)
                    B = np.zeros(shape=(nov_alph, nov_alph))
            elif self.tei_mo_type == AO2MOTransformationType.partial:
                if hamiltonian == Hamiltonian.RPA and spin == Spin.singlet:
                    A = form_rpa_a_matrix_mo_singlet_partial(
                        self.moenergies[0], tei_mo_ovov, tei_mo_oovv
                    )
                    B = form_rpa_b_matrix_mo_singlet_partial(tei_mo_ovov)
                elif hamiltonian == Hamiltonian.RPA and spin == Spin.triplet:
                    A = form_rpa_a_matrix_mo_triplet_partial(self.moenergies[0], tei_mo_oovv)
                    B = form_rpa_b_matrix_mo_triplet_partial(tei_mo_ovov)
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.singlet:
                    A = form_rpa_a_matrix_mo_singlet_partial(
                        self.moenergies[0], tei_mo_ovov, tei_mo_oovv
                    )
                    B = np.zeros(shape=(nov_alph, nov_alph))
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.triplet:
                    A = form_rpa_a_matrix_mo_triplet_partial(self.moenergies[0], tei_mo_oovv)
                    B = np.zeros(shape=(nov_alph, nov_alph))

            G = np.block([[A, B], [B, A]])
            self.explicit_hessian = G - superoverlap_alph

        else:
            # For UHF there are both "operator-dependent" and
            # operator-indepenent parts of the orbital Hessian because
            # the opposite-spin property gradient couples in. Here,
            # only form the 4 blocks of the "super-Hessian" (a
            # supermatrix of supermatrices); the equations will get
            # pieced together when it is time ot form the response
            # vectors.

            # Set up "function pointers".
            if self.tei_mo_type == AO2MOTransformationType.full:
                assert len(self.tei_mo) == 4
                tei_mo_aaaa = self.tei_mo[0]
                tei_mo_aabb = self.tei_mo[1]
                tei_mo_bbaa = self.tei_mo[2]
                tei_mo_bbbb = self.tei_mo[3]
            elif self.tei_mo_type == AO2MOTransformationType.partial:
                assert len(self.tei_mo) == 6
                tei_mo_ovov_aaaa = self.tei_mo[0]
                tei_mo_ovov_aabb = self.tei_mo[1]
                tei_mo_ovov_bbaa = self.tei_mo[2]
                tei_mo_ovov_bbbb = self.tei_mo[3]
                tei_mo_oovv_aaaa = self.tei_mo[4]
                tei_mo_oovv_bbbb = self.tei_mo[5]
            else:
                pass

            E_a = self.moenergies[0]
            E_b = self.moenergies[1]

            # TODO clean this up...
            if self.tei_mo_type == AO2MOTransformationType.full:
                if hamiltonian == Hamiltonian.RPA and spin == Spin.singlet:
                    A_ss_a = form_rpa_a_matrix_mo_singlet_ss_full(E_a, tei_mo_aaaa, nocc_alph)
                    A_os_a = form_rpa_a_matrix_mo_singlet_os_full(tei_mo_aabb, nocc_alph, nocc_beta)
                    B_ss_a = form_rpa_b_matrix_mo_singlet_ss_full(tei_mo_aaaa, nocc_alph)
                    B_os_a = form_rpa_b_matrix_mo_singlet_os_full(tei_mo_aabb, nocc_alph, nocc_beta)
                    A_ss_b = form_rpa_a_matrix_mo_singlet_ss_full(E_b, tei_mo_bbbb, nocc_beta)
                    A_os_b = form_rpa_a_matrix_mo_singlet_os_full(tei_mo_bbaa, nocc_beta, nocc_alph)
                    B_ss_b = form_rpa_b_matrix_mo_singlet_ss_full(tei_mo_bbbb, nocc_beta)
                    B_os_b = form_rpa_b_matrix_mo_singlet_os_full(tei_mo_bbaa, nocc_beta, nocc_alph)
                elif hamiltonian == Hamiltonian.RPA and spin == Spin.triplet:
                    # 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.
                    zeros_ab = np.zeros(shape=(nov_alph, nov_beta))
                    zeros_ba = zeros_ab.T
                    A_ss_a = form_rpa_a_matrix_mo_triplet_full(E_a, tei_mo_aaaa, nocc_alph)
                    A_os_a = zeros_ab
                    B_ss_a = form_rpa_b_matrix_mo_triplet_full(tei_mo_aaaa, nocc_alph)
                    B_os_a = zeros_ab
                    A_ss_b = form_rpa_a_matrix_mo_triplet_full(E_b, tei_mo_bbbb, nocc_beta)
                    A_os_b = zeros_ba
                    B_ss_b = form_rpa_b_matrix_mo_triplet_full(tei_mo_bbbb, nocc_beta)
                    B_os_b = zeros_ba
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.singlet:
                    zeros_aa = np.zeros(shape=(nov_alph, nov_alph))
                    zeros_ab = np.zeros(shape=(nov_alph, nov_beta))
                    zeros_ba = zeros_ab.T
                    zeros_bb = np.zeros(shape=(nov_beta, nov_beta))
                    A_ss_a = form_rpa_a_matrix_mo_singlet_ss_full(E_a, tei_mo_aaaa, nocc_alph)
                    A_os_a = form_rpa_a_matrix_mo_singlet_os_full(tei_mo_aabb, nocc_alph, nocc_beta)
                    B_ss_a = zeros_aa
                    B_os_a = zeros_ab
                    A_ss_b = form_rpa_a_matrix_mo_singlet_ss_full(E_b, tei_mo_bbbb, nocc_beta)
                    A_os_b = form_rpa_a_matrix_mo_singlet_os_full(tei_mo_bbaa, nocc_beta, nocc_alph)
                    B_ss_b = zeros_bb
                    B_os_b = zeros_ba
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.triplet:
                    zeros_aa = np.zeros(shape=(nov_alph, nov_alph))
                    zeros_ab = np.zeros(shape=(nov_alph, nov_beta))
                    zeros_ba = zeros_ab.T
                    zeros_bb = np.zeros(shape=(nov_beta, nov_beta))
                    A_ss_a = form_rpa_a_matrix_mo_triplet_full(E_a, tei_mo_aaaa, nocc_alph)
                    A_os_a = zeros_ab
                    B_ss_a = zeros_aa
                    B_os_a = zeros_ab
                    A_ss_b = form_rpa_a_matrix_mo_triplet_full(E_b, tei_mo_bbbb, nocc_beta)
                    A_os_b = zeros_ba
                    B_ss_b = zeros_bb
                    B_os_b = zeros_ba

            elif self.tei_mo_type == AO2MOTransformationType.partial:
                if hamiltonian == Hamiltonian.RPA and spin == Spin.singlet:
                    A_ss_a = form_rpa_a_matrix_mo_singlet_ss_partial(
                        E_a, tei_mo_ovov_aaaa, tei_mo_oovv_aaaa
                    )
                    A_os_a = form_rpa_a_matrix_mo_singlet_os_partial(tei_mo_ovov_aabb)
                    B_ss_a = form_rpa_b_matrix_mo_singlet_ss_partial(tei_mo_ovov_aaaa)
                    B_os_a = form_rpa_b_matrix_mo_singlet_os_partial(tei_mo_ovov_aabb)
                    A_ss_b = form_rpa_a_matrix_mo_singlet_ss_partial(
                        E_b, tei_mo_ovov_bbbb, tei_mo_oovv_bbbb
                    )
                    A_os_b = form_rpa_a_matrix_mo_singlet_os_partial(tei_mo_ovov_bbaa)
                    B_ss_b = form_rpa_b_matrix_mo_singlet_ss_partial(tei_mo_ovov_bbbb)
                    B_os_b = form_rpa_b_matrix_mo_singlet_os_partial(tei_mo_ovov_bbaa)
                elif hamiltonian == Hamiltonian.RPA and spin == Spin.triplet:
                    # 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.
                    zeros_ab = np.zeros(shape=(nov_alph, nov_beta))
                    zeros_ba = zeros_ab.T
                    A_ss_a = form_rpa_a_matrix_mo_triplet_partial(E_a, tei_mo_oovv_aaaa)
                    A_os_a = zeros_ab
                    B_ss_a = form_rpa_b_matrix_mo_triplet_partial(tei_mo_ovov_aaaa)
                    B_os_a = zeros_ab
                    A_ss_b = form_rpa_a_matrix_mo_triplet_partial(E_b, tei_mo_oovv_bbbb)
                    A_os_b = zeros_ba
                    B_ss_b = form_rpa_b_matrix_mo_triplet_partial(tei_mo_ovov_bbbb)
                    B_os_b = zeros_ba
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.singlet:
                    zeros_aa = np.zeros(shape=(nov_alph, nov_alph))
                    zeros_ab = np.zeros(shape=(nov_alph, nov_beta))
                    zeros_ba = zeros_ab.T
                    zeros_bb = np.zeros(shape=(nov_beta, nov_beta))
                    A_ss_a = form_rpa_a_matrix_mo_singlet_ss_partial(
                        E_a, tei_mo_ovov_aaaa, tei_mo_oovv_aaaa
                    )
                    A_os_a = form_rpa_a_matrix_mo_singlet_os_partial(tei_mo_ovov_aabb)
                    B_ss_a = zeros_aa
                    B_os_a = zeros_ab
                    A_ss_b = form_rpa_a_matrix_mo_singlet_ss_partial(
                        E_b, tei_mo_ovov_bbbb, tei_mo_oovv_bbbb
                    )
                    A_os_b = form_rpa_a_matrix_mo_singlet_os_partial(tei_mo_ovov_bbaa)
                    B_ss_b = zeros_bb
                    B_os_b = zeros_ba
                elif hamiltonian == Hamiltonian.TDA and spin == Spin.triplet:
                    zeros_aa = np.zeros(shape=(nov_alph, nov_alph))
                    zeros_ab = np.zeros(shape=(nov_alph, nov_beta))
                    zeros_ba = zeros_ab.T
                    zeros_bb = np.zeros(shape=(nov_beta, nov_beta))
                    A_ss_a = form_rpa_a_matrix_mo_triplet_partial(E_a, tei_mo_oovv_aaaa)
                    A_os_a = zeros_ab
                    B_ss_a = zeros_aa
                    B_os_a = zeros_ab
                    A_ss_b = form_rpa_a_matrix_mo_triplet_partial(E_b, tei_mo_oovv_bbbb)
                    A_os_b = zeros_ba
                    B_ss_b = zeros_bb
                    B_os_b = zeros_ba

            superoverlap_beta = np.block(
                [
                    [np.eye(nov_beta), np.zeros(shape=(nov_beta, nov_beta))],
                    [np.zeros(shape=(nov_beta, nov_beta)), -np.eye(nov_beta)],
                ]
            )
            superoverlap_beta = superoverlap_beta * frequency

            G_aa = np.block([[A_ss_a, B_ss_a], [B_ss_a, A_ss_a]])
            G_ab = np.block([[A_os_a, B_os_a], [B_os_a, A_os_a]])
            G_ba = np.block([[A_os_b, B_os_b], [B_os_b, A_os_b]])
            G_bb = np.block([[A_ss_b, B_ss_b], [B_ss_b, A_ss_b]])

            self.explicit_hessian = (
                G_aa - superoverlap_alph,
                G_ab,
                G_ba,
                G_bb - superoverlap_beta,
            )
예제 #5
0
    def form_explicit_hessian(self,
                              hamiltonian=None,
                              spin=None,
                              frequency=None):

        assert hasattr(self, "tei_mo")
        assert self.tei_mo is not None
        assert len(self.tei_mo) in (1, 2, 4, 6)
        assert self.tei_mo_type in ("full", "partial")

        if not hamiltonian:
            hamiltonian = self.hamiltonian
        if not spin:
            spin = self.spin

        assert isinstance(hamiltonian, str)
        assert isinstance(spin, str)
        hamiltonian = hamiltonian.lower()
        spin = spin.lower()

        assert hamiltonian == "tda"
        assert spin in ("singlet", "triplet")

        self.hamiltonian = hamiltonian
        self.spin = spin

        nocc_alph, nvirt_alph, nocc_beta, nvirt_beta = self.occupations
        nov_alph = nocc_alph * nvirt_alph
        nov_beta = nocc_beta * nvirt_beta

        if not self.is_uhf:

            # Set up "function pointers".
            if self.tei_mo_type == "full":
                assert len(self.tei_mo) == 1
                tei_mo = self.tei_mo[0]
            elif self.tei_mo_type == "partial":
                assert len(self.tei_mo) == 2
                tei_mo_ovov = self.tei_mo[0]
                tei_mo_oovv = self.tei_mo[1]

            if self.tei_mo_type == "full":
                if spin == "singlet":
                    A = form_rpa_a_matrix_mo_singlet_full(
                        self.moenergies[0], tei_mo, nocc_alph)
                elif spin == "triplet":
                    A = form_rpa_a_matrix_mo_triplet_full(
                        self.moenergies[0], tei_mo, nocc_alph)
            elif self.tei_mo_type == "partial":
                if spin == "singlet":
                    A = form_rpa_a_matrix_mo_singlet_partial(
                        self.moenergies[0], tei_mo_ovov, tei_mo_oovv)
                elif spin == "triplet":
                    A = form_rpa_a_matrix_mo_triplet_partial(
                        self.moenergies[0], tei_mo_oovv)

            self.explicit_hessian = A

        else:
            # TODO UHF
            pass