Ejemplo n.º 1
0
def energy(h1e, eri, fcivec, norb, nelec, link_index=None):
    '''Compute the FCI electronic energy for given Hamiltonian and FCI vector.
    '''
    from pyscf.fci import direct_spin1
    h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5)
    ci1 = direct_spin1.contract_2e(h2e, fcivec, norb, nelec, link_index)
    return numpy.dot(fcivec.reshape(-1), ci1.reshape(-1))
Ejemplo n.º 2
0
 def test_lasuccsd_total_energy (self):
     mc = mcscf.CASCI (mf, 4, 4)
     mc.mo_coeff = las.mo_coeff
     mc.fcisolver = lasuccsd.FCISolver (mol)
     mc.fcisolver.norb_f = [2,2]
     mc.kernel ()
     with self.subTest (from_='reported'):
         self.assertAlmostEqual (mc.e_tot, ref.e_tot, 6)
     psi = mc.fcisolver.psi
     x = psi.x
     h1, h0 = mc.get_h1eff ()
     h2 = mc.get_h2eff ()
     h = [h0, h1, h2]
     energy, gradient = psi.e_de (x, h)
     with self.subTest (from_='obj fn'):
         self.assertAlmostEqual (energy, mc.e_tot, 9)
     c = np.squeeze (fockspace.fock2hilbert (psi.get_fcivec (x), 4, (2,2)))
     h2eff = direct_spin1.absorb_h1e (h1, h2, 4, (2,2), 0.5)
     hc = direct_spin1.contract_2e (h2eff, c, 4, (2,2))
     chc = c.conj ().ravel ().dot (hc.ravel ()) + h0
     with self.subTest (from_='h2 contraction'):
         self.assertAlmostEqual (chc, mc.e_tot, 9)
     c_f = psi.ci_f
     for ifrag, c in enumerate (c_f):
         heff = psi.get_dense_heff (x, h, ifrag)
         hc = np.dot (heff.full, c.ravel ())
         chc = np.dot (c.conj ().ravel (), hc)
         with self.subTest (from_='frag {} Fock-space dense effective Hamiltonian'.format (ifrag)):
             self.assertAlmostEqual (chc, mc.e_tot, 9)
         heff, _ = heff.get_number_block ((1,1),(1,1))
         c = np.squeeze (fockspace.fock2hilbert (c, 2, (1,1))).ravel ()
         hc = np.dot (heff, c)
         chc = np.dot (c.conj (), hc)
         with self.subTest (from_='frag {} Hilbert-space dense effective Hamiltonian'.format (ifrag)):
             self.assertAlmostEqual (chc, mc.e_tot, 9)
Ejemplo n.º 3
0
def energy(h1e, eri, fcivec, norb, nelec, link_index=None):
    '''Compute the FCI electronic energy for given Hamiltonian and FCI vector.
    '''
    from pyscf.fci import direct_spin1
    h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5)
    ci1 = direct_spin1.contract_2e(h2e, fcivec, norb, nelec, link_index)
    return numpy.dot(fcivec.reshape(-1), ci1.reshape(-1))
Ejemplo n.º 4
0
def contract_2e(eri, fcivec, norb, nelec, link_index=None, orbsym=None):
    fcivec = numpy.asarray(fcivec, order='C')
    if orbsym is None:
        return direct_spin1.contract_2e(eri, fcivec, norb, nelec, link_index)

    eri = pyscf.ao2mo.restore(4, eri, norb)
    link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index)
    na, nlinka = link_indexa.shape[:2]
    nb, nlinkb = link_indexb.shape[:2]
    assert(fcivec.size == na*nb)
    ci1 = numpy.empty_like(fcivec)

    eri, link_indexa, dimirrep = reorder4irrep(eri, norb, link_indexa, orbsym)
    link_indexb = reorder4irrep(eri, norb, link_indexb, orbsym)[1]
    dimirrep = numpy.array(dimirrep, dtype=numpy.int32)

    libfci.FCIcontract_2e_spin1_symm(eri.ctypes.data_as(ctypes.c_void_p),
                                     fcivec.ctypes.data_as(ctypes.c_void_p),
                                     ci1.ctypes.data_as(ctypes.c_void_p),
                                     ctypes.c_int(norb),
                                     ctypes.c_int(na), ctypes.c_int(nb),
                                     ctypes.c_int(nlinka), ctypes.c_int(nlinkb),
                                     link_indexa.ctypes.data_as(ctypes.c_void_p),
                                     link_indexb.ctypes.data_as(ctypes.c_void_p),
                                     dimirrep.ctypes.data_as(ctypes.c_void_p),
                                     ctypes.c_int(len(dimirrep)))
    return ci1
Ejemplo n.º 5
0
def contract_2e(eri, fcivec, norb, nelec, link_index=None, orbsym=[]):
    if not orbsym:
        return direct_spin1.contract_2e(eri, fcivec, norb, nelec, link_index)

    eri = pyscf.ao2mo.restore(4, eri, norb)
    if link_index is None:
        if isinstance(nelec, (int, numpy.integer)):
            nelecb = nelec//2
            neleca = nelec - nelecb
        else:
            neleca, nelecb = nelec
        link_indexa = cistring.gen_linkstr_index_trilidx(range(norb), neleca)
        link_indexb = cistring.gen_linkstr_index_trilidx(range(norb), nelecb)
    else:
        link_indexa, link_indexb = link_index
    na, nlinka = link_indexa.shape[:2]
    nb, nlinkb = link_indexb.shape[:2]
    fcivec = fcivec.reshape(na,nb)
    ci1 = numpy.empty_like(fcivec)

    eri, link_indexa, dimirrep = reorder4irrep(eri, norb, link_indexa, orbsym)
    link_indexb = reorder4irrep(eri, norb, link_indexb, orbsym)[1]
    dimirrep = numpy.array(dimirrep, dtype=numpy.int32)

    libfci.FCIcontract_2e_spin1_symm(eri.ctypes.data_as(ctypes.c_void_p),
                                     fcivec.ctypes.data_as(ctypes.c_void_p),
                                     ci1.ctypes.data_as(ctypes.c_void_p),
                                     ctypes.c_int(norb),
                                     ctypes.c_int(na), ctypes.c_int(nb),
                                     ctypes.c_int(nlinka), ctypes.c_int(nlinkb),
                                     link_indexa.ctypes.data_as(ctypes.c_void_p),
                                     link_indexb.ctypes.data_as(ctypes.c_void_p),
                                     dimirrep.ctypes.data_as(ctypes.c_void_p),
                                     ctypes.c_int(len(dimirrep)))
    return ci1
Ejemplo n.º 6
0
 def contract_h2 (self, h, ci, norb=None):
     if norb is None: norb = self.norb
     hci = h[0] * ci
     for neleca, nelecb in product (range (norb+1), repeat=2):
         nelec = (neleca, nelecb)
         h2eff = self.fcisolver.absorb_h1e (h[1], h[2], norb, nelec, 0.5)
         ci_h = np.squeeze (fockspace.fock2hilbert (ci, norb, nelec))
         hc = direct_spin1.contract_2e (h2eff, ci_h, norb, nelec)
         hci += np.squeeze (fockspace.hilbert2fock (hc, norb, nelec))
     return hci
Ejemplo n.º 7
0
    def test_spin0_contract(self):
        myci = selected_ci_spin0.SCI()
        civec_strs = selected_ci._as_SCIvector(spin0_ci_coeff, spin0_ci_strs)
        ci0 = selected_ci.to_fci(civec_strs, norb, nelec)
        e1 = numpy.dot(civec_strs.ravel(), myci.contract_2e(eri, civec_strs, norb, nelec).ravel())
        eref = numpy.dot(ci0.ravel(), direct_spin1.contract_2e(eri, ci0, norb, nelec).ravel())
        self.assertAlmostEqual(e1, eref, 9)

        e2 = numpy.dot(civec_strs.ravel(), myci.contract_2e(eri, spin0_ci_coeff, norb, nelec).ravel())
        self.assertAlmostEqual(e2, eref, 9)
Ejemplo n.º 8
0
 def print_line (c, ne):
     try:
         ss, smult = spin_square0 (c, norb, ne)
         hc = contract_2e (eri, c, norb, ne)
         chc = c.conj ().ravel ().dot (hc.ravel ())
     except AssertionError as e:
         assert (any ([n<0 for n in ne]))
         ss, smult, chc = (0.0, 1.0, 0.0)
     cc = linalg.norm (c)
     ndeta, ndetb = c.shape
     print (" {:>6d} {:>6d} {:>5d} {:>5d} {:5.3f} {:13.9f} {:5.3f} {:5.3f}".format (ne[0], ne[1], ndeta, ndetb, cc, chc, ss, smult))
Ejemplo n.º 9
0
 def test_contract(self):
     myci = select_ci.SelectCI()
     ci0 = select_ci.to_fci(civec_strs, norb, nelec)
     e1 = numpy.dot(civec_strs.ravel(), select_ci.contract_2e(eri, civec_strs, norb, nelec).ravel())
     e2 = numpy.dot(ci0.ravel(), direct_spin1.contract_2e(eri, ci0, norb, nelec).ravel())
     self.assertAlmostEqual(e1, e2, 9)
     dm1 = myci.make_rdm1(civec_strs, norb, nelec)
     self.assertAlmostEqual(finger(dm1), 0.70181046385686563, 9)
     dm1 = myci.trans_rdm1(civec_strs, civec_strs, norb, nelec)
     self.assertAlmostEqual(finger(dm1), 0.70181046385686563, 9)
     dm2 = myci.make_rdm2(civec_strs, norb, nelec)
     self.assertAlmostEqual(finger(dm2), -3.8397469683353962, 9)
Ejemplo n.º 10
0
 def test_contract(self):
     myci = select_ci.SCI()
     ci0 = select_ci.to_fci(civec_strs, norb, nelec)
     e1 = numpy.dot(
         civec_strs.ravel(),
         select_ci.contract_2e(eri, civec_strs, norb, nelec).ravel())
     e2 = numpy.dot(ci0.ravel(),
                    direct_spin1.contract_2e(eri, ci0, norb, nelec).ravel())
     self.assertAlmostEqual(e1, e2, 9)
     dm1 = myci.make_rdm1(civec_strs, norb, nelec)
     self.assertAlmostEqual(finger(dm1), 0.70181046385686563, 9)
     dm1 = myci.trans_rdm1(civec_strs, civec_strs, norb, nelec)
     self.assertAlmostEqual(finger(dm1), 0.70181046385686563, 9)
     dm2 = myci.make_rdm2(civec_strs, norb, nelec)
     self.assertAlmostEqual(finger(dm2), -3.8397469683353962, 9)
Ejemplo n.º 11
0
 def test_contract_2e_1(self):
     myci = selected_ci.SCI()
     nelec = (4,3)
     strsa = cistring.make_strings(range(norb), nelec[0])
     strsb = cistring.make_strings(range(norb), nelec[1])
     ci0 = selected_ci._as_SCIvector(numpy.random.random((len(strsa),len(strsb))), (strsa,strsb))
     h2 = ao2mo.restore(1, eri, norb)
     c1 = myci.contract_2e(h2, ci0, norb, nelec)
     c2 = direct_spin1.contract_2e(h2, ci0, norb, nelec)
     self.assertAlmostEqual(float(abs(c1-c2).sum()), 0, 9)
     dm1_1 = myci.make_rdm1(c1, norb, nelec)
     dm1_2 = direct_spin1.make_rdm1(c2, norb, nelec)
     self.assertAlmostEqual(abs(dm1_1 - dm1_2).sum(), 0, 9)
     dm2_1 = myci.make_rdm12(c1, norb, nelec)[1]
     dm2_2 = direct_spin1.make_rdm12(c2, norb, nelec)[1]
     self.assertAlmostEqual(abs(dm2_1 - dm2_2).sum(), 0, 9)
Ejemplo n.º 12
0
 def test_ham(self):
     for norb in range(2, 5):
         npair = norb * (norb + 1) // 2
         c = np.random.rand(2**(2 * norb))
         c /= linalg.norm(c)
         h0 = np.random.rand(1)[0]
         h1 = np.random.rand(norb, norb)
         h2 = np.random.rand(npair, npair)
         h1 += h1.T
         h2 += h2.T
         hc_ref = np.zeros_like(c)
         for nelec in product(range(norb + 1), repeat=2):
             c_h = np.squeeze(fockspace.fock2hilbert(c, norb, nelec))
             h2eff = direct_spin1.absorb_h1e(h1, h2, norb, nelec, 0.5)
             hc_h = h0 * c_h + direct_spin1.contract_2e(
                 h2eff, c_h, norb, nelec)
             hc_ref += fockspace.hilbert2fock(hc_h, norb, nelec).ravel()
         h1 = h1[np.tril_indices(norb)]
         hc_test = _op1h_spinsym(norb, [h0, h1, h2], c)
         with self.subTest(norb=norb):
             self.assertAlmostEqual(lib.fp(hc_test), lib.fp(hc_ref), 6)
Ejemplo n.º 13
0
    jk = jk.ravel()
    jk_sorted = abs(jk).argsort()[::-1]
    ci1 = [as_SCIvector(numpy.ones(1), hf_str)]

    myci = SelectedCI()
    myci.select_cutoff = .001
    myci.ci_coeff_cutoff = .001

    ci2 = enlarge_space(myci, ci1, h1, eri, jk, eri_sorted, jk_sorted, norb, nelec)
    print(len(ci2[0]))

    ci2 = enlarge_space(myci, ci1, h1, eri, jk, eri_sorted, jk_sorted, norb, nelec)
    numpy.random.seed(1)
    ci3 = numpy.random.random(ci2[0].size)
    ci3 *= 1./numpy.linalg.norm(ci3)
    ci3 = [ci3]
    ci3 = enlarge_space(myci, ci2, h1, eri, jk, eri_sorted, jk_sorted, norb, nelec)

    efci = direct_spin1.kernel(h1, eri, norb, nelec, verbose=5)[0]

    ci4 = contract_2e_ctypes((h1, eri), ci3[0], norb, nelec)

    fci3 = to_fci(ci3, norb, nelec)
    h2e = direct_spin1.absorb_h1e(h1, eri, norb, nelec, .5)
    fci4 = direct_spin1.contract_2e(h2e, fci3, norb, nelec)
    fci4 = from_fci(fci4, ci3[0]._strs, norb, nelec)
    print(abs(ci4-fci4).sum())

    e = myci.kernel(h1, eri, norb, nelec, verbose=5)[0]
    print(e, efci)
Ejemplo n.º 14
0
def contract_2e(eri,
                fcivec,
                norb,
                nelec,
                link_index=None,
                orbsym=None,
                wfnsym=0):
    if orbsym is None:
        return direct_spin1.contract_2e(eri, fcivec, norb, nelec, link_index)

    eri = ao2mo.restore(4, eri, norb)
    neleca, nelecb = _unpack_nelec(nelec)
    link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index)
    na, nlinka = link_indexa.shape[:2]
    nb, nlinkb = link_indexb.shape[:2]
    eri_irs, rank_eri, irrep_eri = reorder_eri(eri, norb, orbsym)

    strsa = cistring.gen_strings4orblist(range(norb), neleca)
    aidx, link_indexa = gen_str_irrep(strsa, orbsym, link_indexa, rank_eri,
                                      irrep_eri)
    if neleca == nelecb:
        bidx, link_indexb = aidx, link_indexa
    else:
        strsb = cistring.gen_strings4orblist(range(norb), nelecb)
        bidx, link_indexb = gen_str_irrep(strsb, orbsym, link_indexb, rank_eri,
                                          irrep_eri)

    Tirrep = ctypes.c_void_p * TOTIRREPS
    linka_ptr = Tirrep(
        *[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexa])
    linkb_ptr = Tirrep(
        *[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexb])
    eri_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in eri_irs])
    dimirrep = (ctypes.c_int * TOTIRREPS)(*[x.shape[0] for x in eri_irs])
    fcivec_shape = fcivec.shape
    fcivec = fcivec.reshape((na, nb), order='C')
    ci1new = numpy.zeros_like(fcivec)
    nas = (ctypes.c_int * TOTIRREPS)(*[x.size for x in aidx])
    nbs = (ctypes.c_int * TOTIRREPS)(*[x.size for x in bidx])

    # aa, ab
    ci0 = []
    ci1 = []
    for ir in range(TOTIRREPS):
        ma, mb = aidx[ir].size, bidx[wfnsym ^ ir].size
        ci0.append(numpy.zeros((ma, mb)))
        ci1.append(numpy.zeros((ma, mb)))
        if ma > 0 and mb > 0:
            lib.take_2d(fcivec, aidx[ir], bidx[wfnsym ^ ir], out=ci0[ir])
    ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0])
    ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1])
    libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs,
                                ctypes.c_int(norb), nas, nbs,
                                ctypes.c_int(nlinka), ctypes.c_int(nlinkb),
                                linka_ptr, linkb_ptr, dimirrep,
                                ctypes.c_int(wfnsym))
    for ir in range(TOTIRREPS):
        if ci0[ir].size > 0:
            lib.takebak_2d(ci1new, ci1[ir], aidx[ir], bidx[wfnsym ^ ir])


# bb, ba
    ci0T = []
    for ir in range(TOTIRREPS):
        mb, ma = bidx[ir].size, aidx[wfnsym ^ ir].size
        ci0T.append(numpy.zeros((mb, ma)))
        if ma > 0 and mb > 0:
            lib.transpose(ci0[wfnsym ^ ir], out=ci0T[ir])
    ci0, ci0T = ci0T, None
    ci1 = [numpy.zeros_like(x) for x in ci0]
    ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0])
    ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1])
    libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs,
                                ctypes.c_int(norb), nbs, nas,
                                ctypes.c_int(nlinkb), ctypes.c_int(nlinka),
                                linkb_ptr, linka_ptr, dimirrep,
                                ctypes.c_int(wfnsym))
    for ir in range(TOTIRREPS):
        if ci0[ir].size > 0:
            lib.takebak_2d(ci1new, lib.transpose(ci1[ir]), aidx[wfnsym ^ ir],
                           bidx[ir])
    return ci1new.reshape(fcivec_shape)
Ejemplo n.º 15
0
    na = cistring.num_strings(norb, nelec // 2 + 1)
    nb = cistring.num_strings(norb, nelec // 2)
    fcivec = numpy.random.random((na, nb))

    orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, m.mo_coeff)
    cis = FCISolver(mol)
    cis.orbsym = orbsym
    fcivec = addons.symmetrize_wfn(fcivec, norb, nelec, cis.orbsym, wfnsym=0)

    ci1 = cis.contract_2e(eri,
                          fcivec,
                          norb,
                          nelec,
                          orbsym=cis.orbsym,
                          wfnsym=0)
    ci1ref = direct_spin1.contract_2e(eri, fcivec, norb, nelec)
    print(numpy.allclose(ci1ref, ci1))

    ci1 = contract_2e(eri, fcivec, norb, nelec, orbsym=orbsym)
    ci1ref = direct_spin1.contract_2e(eri, fcivec, norb, nelec)
    print(numpy.allclose(ci1ref, ci1))
    cis.wfnsym = 3
    e = cis.kernel(h1e,
                   eri,
                   norb,
                   nelec,
                   ecore=m.energy_nuc(),
                   davidson_only=True)[0]
    print(e, e - -74.695029029452357)

    mol.atom = [['H', (0, 0, i)] for i in range(8)]
Ejemplo n.º 16
0
 def hop(c):
     hc = fcisolver.contract_2e(h2e, c, norb, nelec)
     return hc.reshape(-1)
Ejemplo n.º 17
0
 def contract_2e_ref(eri, fcivec, norb, nelec, *args, **kwargs):
     hc = direct_spin1.contract_2e(eri, numpy.diag(fcivec), norb, nelec)
     return hc.diagonal()
Ejemplo n.º 18
0
 def hop(c):
     hc = direct_spin1.contract_2e(h2e, c, norb, nelec)
     return hc.reshape(-1)
Ejemplo n.º 19
0
def get_cc_chc_smult (eri, c, norb, ne):
    cc = c.conj ().ravel ().dot (c.ravel ())
    chc = c.conj ().ravel ().dot (contract_2e (eri, c, norb, ne).ravel ())
    ss, smult = spin_square0 (c, norb, ne)
    return cc, chc, smult
Ejemplo n.º 20
0
def contract_2e(eri, fcivec, norb, nelec, link_index=None, orbsym=None, wfnsym=0):
    if orbsym is None:
        return direct_spin1.contract_2e(eri, fcivec, norb, nelec, link_index)

    eri = ao2mo.restore(4, eri, norb)
    neleca, nelecb = _unpack_nelec(nelec)
    link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index)
    na, nlinka = link_indexa.shape[:2]
    nb, nlinkb = link_indexb.shape[:2]
    eri_irs, rank_eri, irrep_eri = reorder_eri(eri, norb, orbsym)

    strsa = cistring.gen_strings4orblist(range(norb), neleca)
    aidx, link_indexa = gen_str_irrep(strsa, orbsym, link_indexa, rank_eri, irrep_eri)
    if neleca == nelecb:
        bidx, link_indexb = aidx, link_indexa
    else:
        strsb = cistring.gen_strings4orblist(range(norb), nelecb)
        bidx, link_indexb = gen_str_irrep(strsb, orbsym, link_indexb, rank_eri, irrep_eri)

    Tirrep = ctypes.c_void_p*TOTIRREPS
    linka_ptr = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexa])
    linkb_ptr = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexb])
    eri_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in eri_irs])
    dimirrep = (ctypes.c_int*TOTIRREPS)(*[x.shape[0] for x in eri_irs])
    fcivec_shape = fcivec.shape
    fcivec = fcivec.reshape((na,nb), order='C')
    ci1new = numpy.zeros_like(fcivec)
    nas = (ctypes.c_int*TOTIRREPS)(*[x.size for x in aidx])
    nbs = (ctypes.c_int*TOTIRREPS)(*[x.size for x in bidx])

# aa, ab
    ci0 = []
    ci1 = []
    for ir in range(TOTIRREPS):
        ma, mb = aidx[ir].size, bidx[wfnsym^ir].size
        ci0.append(numpy.zeros((ma,mb)))
        ci1.append(numpy.zeros((ma,mb)))
        if ma > 0 and mb > 0:
            lib.take_2d(fcivec, aidx[ir], bidx[wfnsym^ir], out=ci0[ir])
    ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0])
    ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1])
    libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs,
                                ctypes.c_int(norb), nas, nbs,
                                ctypes.c_int(nlinka), ctypes.c_int(nlinkb),
                                linka_ptr, linkb_ptr, dimirrep,
                                ctypes.c_int(wfnsym))
    for ir in range(TOTIRREPS):
        if ci0[ir].size > 0:
            lib.takebak_2d(ci1new, ci1[ir], aidx[ir], bidx[wfnsym^ir])

# bb, ba
    ci0T = []
    for ir in range(TOTIRREPS):
        mb, ma = bidx[ir].size, aidx[wfnsym^ir].size
        ci0T.append(numpy.zeros((mb,ma)))
        if ma > 0 and mb > 0:
            lib.transpose(ci0[wfnsym^ir], out=ci0T[ir])
    ci0, ci0T = ci0T, None
    ci1 = [numpy.zeros_like(x) for x in ci0]
    ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0])
    ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1])
    libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs,
                                ctypes.c_int(norb), nbs, nas,
                                ctypes.c_int(nlinkb), ctypes.c_int(nlinka),
                                linkb_ptr, linka_ptr, dimirrep,
                                ctypes.c_int(wfnsym))
    for ir in range(TOTIRREPS):
        if ci0[ir].size > 0:
            lib.takebak_2d(ci1new, lib.transpose(ci1[ir]), aidx[wfnsym^ir], bidx[ir])
    return ci1new.reshape(fcivec_shape)
Ejemplo n.º 21
0
    norb = m.mo_coeff.shape[1]
    nelec = mol.nelectron-1
    h1e = reduce(numpy.dot, (m.mo_coeff.T, scf.hf.get_hcore(mol), m.mo_coeff))
    eri = ao2mo.incore.full(m._eri, m.mo_coeff)
    numpy.random.seed(1)
    na = cistring.num_strings(norb, nelec//2+1)
    nb = cistring.num_strings(norb, nelec//2)
    fcivec = numpy.random.random((na,nb))

    orbsym = symm.label_orb_symm(mol, mol.irrep_id, mol.symm_orb, m.mo_coeff)
    cis = FCISolver(mol)
    cis.orbsym = orbsym
    fcivec = addons.symmetrize_wfn(fcivec, norb, nelec, cis.orbsym, wfnsym=0)

    ci1 = cis.contract_2e(eri, fcivec, norb, nelec, orbsym=cis.orbsym, wfnsym=0)
    ci1ref = direct_spin1.contract_2e(eri, fcivec, norb, nelec)
    print(numpy.allclose(ci1ref, ci1))

    ci1 = contract_2e(eri, fcivec, norb, nelec, orbsym=orbsym)
    ci1ref = direct_spin1.contract_2e(eri, fcivec, norb, nelec)
    print(numpy.allclose(ci1ref, ci1))
    cis.wfnsym = 3
    e = cis.kernel(h1e, eri, norb, nelec, ecore=m.energy_nuc(), davidson_only=True)[0]
    print(e, e - -74.695029029452357)

    mol.atom = [['H', (0, 0, i)] for i in range(8)]
    mol.basis = {'H': 'sto-3g'}
    mol.symmetry = True
    mol.build()
    m = scf.RHF(mol)
    ehf = m.scf()
Ejemplo n.º 22
0
    jk = jk.ravel()
    jk_sorted = abs(jk).argsort()[::-1]
    ci1 = [as_SCIvector(numpy.ones(1), hf_str)]

    myci = SelectedCI()
    myci.select_cutoff = .001
    myci.ci_coeff_cutoff = .001

    ci2 = enlarge_space(myci, ci1, h1, eri, jk, eri_sorted, jk_sorted, norb, nelec)
    print(len(ci2[0]))

    ci2 = enlarge_space(myci, ci1, h1, eri, jk, eri_sorted, jk_sorted, norb, nelec)
    numpy.random.seed(1)
    ci3 = numpy.random.random(ci2[0].size)
    ci3 *= 1./numpy.linalg.norm(ci3)
    ci3 = [ci3]
    ci3 = enlarge_space(myci, ci2, h1, eri, jk, eri_sorted, jk_sorted, norb, nelec)

    efci = direct_spin1.kernel(h1, eri, norb, nelec, verbose=5)[0]

    ci4 = contract_2e_ctypes((h1, eri), ci3[0], norb, nelec)

    fci3 = to_fci(ci3, norb, nelec)
    h2e = direct_spin1.absorb_h1e(h1, eri, norb, nelec, .5)
    fci4 = direct_spin1.contract_2e(h2e, fci3, norb, nelec)
    fci4 = from_fci(fci4, ci3[0]._strs, norb, nelec)
    print(abs(ci4-fci4).sum())

    e = myci.kernel(h1, eri, norb, nelec, verbose=5)[0]
    print(e, efci)
Ejemplo n.º 23
0
def energy(h1e, eri, fcivec, norb, nelec, link_index=None):
    from pyscf.fci import direct_spin1
    h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5)
    ci1 = direct_spin1.contract_2e(h2e, fcivec, norb, nelec, link_index)
    return numpy.dot(fcivec.reshape(-1), ci1.reshape(-1))
Ejemplo n.º 24
0
 def hop(c):
     hc = direct_spin1.contract_2e(h2e, c, norb, nelec)
     return hc.reshape(-1)
Ejemplo n.º 25
0
def kernel(mc, nroots):

    mc_1root = mc
    mc_1root = mcscf.CASCI(mc._scf, mc.ncas, mc.nelecas)
    mc_1root.fcisolver = fci.solver(mc._scf.mol, singlet=False, symm=False)
    mc_1root.mo_coeff = mc.mo_coeff
    nao, nmo = mc.mo_coeff.shape
    ncas, ncore = mc.ncas, mc.ncore
    nocc = ncas + ncore
    mo_cas = mc.mo_coeff[:, ncore:nocc]
    casdm1 = mc.fcisolver.states_make_rdm1(mc.ci, mc_1root.ncas,
                                           mc_1root.nelecas)
    dm1 = np.dot(casdm1, mo_cas.T)
    dm1 = np.dot(mo_cas, dm1).transpose(1, 0, 2)
    aeri = ao2mo.restore(1, mc.get_h2eff(mc.mo_coeff), mc.ncas)
    rows, col = np.tril_indices(nroots, k=-1)
    pairs = len(rows)
    ci_array = np.array(mc.ci)
    u = np.identity(nroots)
    t = np.zeros((nroots, nroots))
    t_old = np.zeros((nroots, nroots))

    trans12_tdm1, trans12_tdm2 = mc.fcisolver.states_trans_rdm12(
        ci_array[col], ci_array[rows], mc_1root.ncas, mc_1root.nelecas)
    trans12_tdm1_array = np.array(trans12_tdm1)
    tdm1 = np.dot(trans12_tdm1_array, mo_cas.T)
    tdm1 = np.dot(mo_cas, tdm1).transpose(1, 0, 2)

    log = lib.logger.new_logger(mc, mc.verbose)
    log.info("Entering cmspdft3.kernel")
    # MRH: PySCF convention is never to use the "print" function in method code.
    # All I/O in published PySCF code goes through the pyscf.lib.logger module.
    # This prints data to an output file specified by the user like
    # mol = gto.M (atom = ..., verbose = lib.logger.INFO, output = 'fname.log')
    # If no output file is specified, it goes to the STDOUT as if it were a print
    # command. The different pyscf.lib.logger functions, "note", "info", "debug",
    # and some others, correspond to different levels of verbosity. In the above
    # example, log.note and log.info commands would print information to
    # 'fname.log', but "debug" commands, which are a higher level, are skipped.
    # I changed all the print commands in this function to log.debug or log.info
    # commands.

    #Print the First Coulomb Energy
    j = mc_1root._scf.get_j(dm=dm1)
    e_coul = (j * dm1).sum((1, 2)) / 2
    log.debug("Reference state e_coul {}".format(e_coul))
    log.info("Reference state e_coul sum = %f", e_coul.sum())
    # MRH: There are a couple of things going on here. First of all, the two
    # statements share different levels of detail, so I use different verbosities:
    # "debug" (only printed if the user has verbose=DEBUG or higher) for the list
    # of all Coulomb energies and "info" (verbose=INFO is the default if an output
    # file is specified) for the sum. Secondly, I am showing two separate ways of
    # formatting strings in Python. log.xxx () knows how to parse the "old" Python
    # string-formatting rules, which is what I've used in the log.info command, but
    # it doesn't know how to interpret a list of arguments the way "print" does, so
    # you have to pass it only one single string. The other way to do this is with
    # "new" python formatting, which I think is simpler:
    # print ("{} and {} and {}".format (a, b, c))
    # is basically identical to
    # print (a, "and", b, "and", c)
    # but you can only use the former in log.xxx:
    # log.xxx ("{} and {} and {}".format (a, b, c))

    #Hessian Functions
    # MRH: Here's a way do not do those nested loops and conditionals and therefore
    # have less to worry about re indentation. Print out "rowscol2ind" and it should
    # be clear how this works.
    rowscol2ind = np.zeros((nroots, nroots), dtype=np.integer)
    rowscol2ind[(rows, col)] = list(range(pairs))  # 0,1,2,3,...
    rowscol2ind += rowscol2ind.T  # Now it can handle both k>l and l>k
    rowscol2ind[np.diag_indices(
        nroots)] = -1  # Makes sure it crashes if you look

    # for k==l, since that's the density
    # matrix and we compute that with a
    # different function.
    def w_klmn(k, l, m, n, dm, tdm):
        #        casdm1 = mc.fcisolver.states_make_rdm1 (ci,mc_1root.ncas,mc_1root.nelecas)
        # MRH: don't you also need to put casdm1 into the AO basis/recompute dm1?
        #        dm1 = np.dot(casdm1,mo_cas.T)
        #        dm1 = np.dot(mo_cas,dm1).transpose(1,0,2)
        # MRH: IMO it's more elegant to rewrite these functions to take the density
        # matrices dm1_cirot and tdm1 as you compute them for the gradient downstairs,
        # since it's the same density matrices for both derivatives. Then this whole
        # function could be like 5 lines long:
        d = dm[k] if k == l else tdm[rowscol2ind[k, l]]
        dm1_g = mc_1root._scf.get_j(dm=d)
        d = dm[m] if m == n else tdm[rowscol2ind[m, n]]
        w = (dm1_g * d).sum((0, 1))
        return w

    # But I'll leave it like this so you can see what's going on more clearly in
    # the github "files changed" tab.
#        trans12_tdm1, trans12_tdm2 = mc.fcisolver.states_trans_rdm12(ci[col],ci[rows],mc_1root.ncas,mc_1root.nelecas)
#        if k==l:
#            dm1_g = mc_1root._scf.get_j (dm=dm1[k])
#        else:
#            ind = rowscol2ind[k,l]
#            tdm1_2 = np.dot(trans12_tdm1[ind],mo_cas.T)
#            tdm1_2 = np.dot(mo_cas,tdm1_2).transpose(1,0)
#            dm1_g = mc_1root._scf.get_j(dm=tdm1_2)
#        if m==n:
#            w  = (dm1_g*dm1[n]).sum((0,1))
#        else:
#            ind2 = rowscol2ind[m,n]
#            tdm1_2 = np.dot(trans12_tdm1_array[ind2],mo_cas.T)
#            tdm1_2 = np.dot(mo_cas,tdm1_2).transpose(1,0)
#            w = (dm1_g*tdm1_2).sum((0,1))

    def v_klmn(k, l, m, n, dm, tdm):
        if l == m:
            v = w_klmn(k, n, k, k, dm, tdm) - w_klmn(
                k, n, l, l, dm, tdm) + w_klmn(n, k, n, n, dm, tdm) - w_klmn(
                    k, n, m, m, dm, tdm) - 4 * w_klmn(k, l, m, n, dm, tdm)

#Compute Classical Couloumb Energy

    casdm1 = mc.fcisolver.states_make_rdm1(mc.ci, mc_1root.ncas,
                                           mc_1root.nelecas)
    dm1 = np.dot(casdm1, mo_cas.T)
    dm1 = np.dot(mo_cas, dm1).transpose(1, 0, 2)

    print("dm1", np.shape(dm1))
    #    print("dm1",dm1)
    j = mc_1root._scf.get_j(dm=dm1)
    #    print("j",j)
    e_coul = (j * dm1).sum((1, 2)) / 2
    print("e_coul_1", e_coul)

    #Transition Density

    for i in range(0, nroots):
        ci_coeff = mc.ci[i]
        print("ci", i, ci_coeff)
    print("mc.ci", type(mc.ci))

    rows, col = np.tril_indices(nroots, k=-1)
    pairs = len(rows)
    print("rows", rows, "col", col, "pairs", pairs)
    print("mc.ci shape", np.shape(mc.ci))
    mc.ci_array = np.array(mc.ci)
    row_ci = mc.ci_array[rows]
    #    print ("mc.ci[rows]",row_ci)
    col_ci = mc.ci_array[col]
    trans12_tdm1, trans12_tdm2 = mc.fcisolver.states_trans_rdm12(
        col_ci, row_ci, mc_1root.ncas, mc_1root.nelecas)
    print("trans12_tdm1", np.shape(trans12_tdm1))

    #Load in the two-electron integrals
    aeri = ao2mo.restore(1, mc.get_h2eff(mc.mo_coeff), mc.ncas)
    #    print("aeri", aeri)
    #    print("eri shape", np.shape(aeri))

    #Initialize rotation matrix
    u = np.identity(mc.fcisolver.nroots)
    print("U :", u)

    t = np.zeros((nroots, nroots))

    u_lt = linalg.expm(t)

    print("u_lt", u_lt)

    ######################################################
    #Begin Loop
    ######################################################

    #Gradients
    trans12_tdm1_array = np.array(trans12_tdm1)
    grad = np.zeros(pairs)
    for i in range(pairs):
        ind = rows[i]
        grad[i] = (casdm1[ind] * trans12_tdm1_array[i] * aeri).sum(
            (0, 1, 2, 3))
        print('ind,i', ind, ',', i)
    grad = 4 * grad
    print('grad', grad)

    #    gradnorm = np.linalg.norm(grad)
    #    print ("grad norm", gradnorm)
    print("grad shape", np.shape(grad))
    #Try 2

    #    j1 = mc_1root._scf.get_jk(mc._scf.mol, dm1, 'ijkl,lk->ij', intor='int2e_ip1_sph', aosym='s2kl', comp=3)
    #    print("j1",j1)

    #Gradient try 3

    #    grad3 =  trans12_tdm1_array*casdm1 * aeri
    #    print ("grad3",grad3)
    #    print("dm1",np.shape(dm1))
    grad3 = np.zeros(pairs)
    #    for i in range (pairs):

    #    dg = mc_1root._scf.get_j (dm=dm1[col])
    #    print("dg shape",np.shape(dg))
    tdm1 = np.dot(trans12_tdm1_array, mo_cas.T)
    tdm1 = np.dot(mo_cas, tdm1).transpose(1, 0, 2)
    dg = mc_1root._scf.get_j(dm=tdm1)
    print("tdm1_array", trans12_tdm1)
    #    tdm1_1 = tdm1[i]
    #    grad3 = (dg*tdm1).sum((1,2))
    grad3 = 4 * (dg * dm1[rows]).sum((1, 2))
    print("grad 3 shape", np.shape(grad3))
    #    grad3=grad3.sum((1,2))
    print("grad3 rows", grad3)
    #    print("grad3*4", grad3*4)
    gradnorm3 = np.linalg.norm(grad3)
    print("grad norm", gradnorm3)

    grad4 = 4 * (dg * dm1[col]).sum((1, 2))
    print("grad3 col", grad4)

    gradnorm4 = np.linalg.norm(grad4)
    print("grad norm", gradnorm4)

    print("grad norm 3+4", gradnorm4 + gradnorm3)

    gradsum = grad4 + grad3
    print("grad sum", gradsum)
    print("grad sum norm", np.linalg.norm(gradsum))

    #GRADIENT TRY 5
    #    grad5 = np.zeros((nroots,pairs))
    #    for i in range(nroots):
    #        dg = mc_1root._scf.get_j(dm=dm1[i])
    #        for j in range(pairs):
    #            if rows[j]==i or col[j]==i:
    #                grad5[i,j]=(dg*tdm1[j]).sum((0,1))
    #    print("grad5",grad5)

    #Hessian

    def w_klmn(k, l, m, n):
        if k == l:
            dm1_g = mc_1root._scf.get_j(dm=dm1[k])
        else:
            for i in range(pairs):
                if rows[i] == k:
                    if col[i] == l:
                        ind = i
#                        print("ind",ind)
                if col[i] == k:
                    if rows[i] == l:
                        ind = i
#                        print("ind",ind)

            tdm1_2 = np.dot(trans12_tdm1[ind], mo_cas.T)
            #            print("tdm1",np.shape(tdm1_2))
            tdm1_2 = np.dot(mo_cas, tdm1_2).transpose(1, 0)
            #            print("tdm1", np.shape(tdm1_2))
            dm1_g = mc_1root._scf.get_j(dm=tdm1_2)
        if m == n:
            w = (dm1_g * dm1[n]).sum((0, 1))
        else:
            for i in range(pairs):
                if rows[i] == m:
                    if col[i] == n:
                        ind2 = i
#                       print("ind2",ind2)
                if col[i] == m:
                    if rows[i] == n:
                        ind2 = i
#                       print("ind2",ind2)

            tdm1_2 = np.dot(trans12_tdm1_array[ind2], mo_cas.T)
            tdm1_2 = np.dot(mo_cas, tdm1_2).transpose(1, 0)
            w = (dm1_g * tdm1_2).sum((0, 1))
        return w

#    for k in range (nroots):
#        for l in range(nroots):
#            for m in range(nroots):
#                for n in range nroots:

    def v_klmn(k, l, m, n):
        if l == m:
            v = w_klmn(k, n, k, k) - w_klmn(k, n, l, l) + w_klmn(
                n, k, n, n) - w_klmn(k, n, m, m) - 4 * w_klmn(k, l, m, n)
        else:
            v = 0
        return v

#Rotate to XMS States

    h1, h0 = mc.get_h1eff()

    #    print("fvecs_nstates",fvecs_nstates)

    #    ci_array = np.tensordot(fvecs_nstates, ci_array, 1)

    casdm1 = mc.fcisolver.states_make_rdm1(ci_array, mc_1root.ncas,
                                           mc_1root.nelecas)
    dm1 = np.dot(casdm1, mo_cas.T)
    dm1 = np.dot(mo_cas, dm1).transpose(1, 0, 2)

    #Loop Initializations
    dm1_old = dm1
    maxiter = 150
    ci_old = ci_array
    thrs = 1.0e-06
    e_coul_old = e_coul
    conv = False

    #################
    #Begin Loop
    #################

    for it in range(maxiter):
        log.info("****iter {} ***********".format(it))

        #       Form U
        U = linalg.expm(t)

        #       Rotate T
        ci_rot = np.tensordot(U, ci_old, 1)

        #       Form New DM1s
        casdm1_rot = mc.fcisolver.states_make_rdm1(ci_rot, mc_1root.ncas,
                                                   mc_1root.nelecas)
        dm1_cirot = np.dot(casdm1_rot, mo_cas.T)
        dm1_cirot = np.dot(mo_cas, dm1_cirot).transpose(1, 0, 2)
        dm1_cirot = np.array(dm1_cirot)

        #       Form New TDM
        trans12_tdm1_rot, trans12_tdm2 = mc.fcisolver.states_trans_rdm12(
            ci_rot[col], ci_rot[rows], mc_1root.ncas, mc_1root.nelecas)
        trans12_tdm1_array = np.array(trans12_tdm1_rot)
        tdm1 = np.dot(trans12_tdm1_array, mo_cas.T)
        tdm1 = np.dot(mo_cas, tdm1).transpose(1, 0, 2)

        #       Print New E coul and difference
        j = mc_1root._scf.get_j(dm=dm1_cirot)
        e_coul_new = (j * dm1_cirot).sum((1, 2)) / 2
        log.info("Sum e_coul = {} ; difference = {}".format(
            e_coul_new.sum(),
            e_coul_new.sum() - e_coul_old.sum()))

        #       Compute Gradient
        dg = mc_1root._scf.get_j(dm=tdm1)
        grad1 = (dg * dm1_cirot[rows]).sum((1, 2))
        grad2 = (dg * dm1_cirot[col]).sum((1, 2))
        grad = 2 * (grad1 - grad2)
        grad_norm = np.linalg.norm(grad)
        log.debug("grad: {}".format(grad))
        log.info("grad norm = %f", grad_norm)

        #        if grad_norm < thrs:
        #            conv = True
        # ci_final = ci_rot # best just to use ci_rot
        #            break
        #        print("hello")
        #       Hessian
        hess = np.zeros((pairs, pairs))
        #       MRH: you can do this whole nested loop, defining all six indices, in one (1) line:
        for (i, (k, l)), (j, (m, n)) in product(enumerate(zip(rows, col)),
                                                repeat=2):
            # To explain:
            # for k,l in zip (rows, col)
            #  ^ Puts elements of "rows" in "k" and elements of "col" in "l"
            #    Advances through "rows" and "col" simultaneously, so it's always
            #    the nth element of "rows" and the nth element of "col"
            #    So obviously, "rows" and "col" have to be the same size.
            #    You don't need parentheses on the right-hand side at this point
            # for i, (k, l) in enumerate (zip (rows,col)):
            #  ^ Iterates over the zip and puts its elements in (k, l), and also
            #    counts upwards from zero and puts the count in "i". Here, you do
            #    need parentheses so that the interpreter understands that "k"
            #    and "l" are grouped together, separate from "i".
            # the uncommented line
            #  ^ "Product" is like "zip", except instead of advancing through the
            #    arguments simultaneously, it gives you all combinations of all
            #    elements. Also, I've only entered one argument and asked it to
            #    repeat it twice. I would have gotten the same result with, i.e.,
            #    product (enumerate, enumerate). Note that I had to import the
            #    function "product" from the built-in Python module "itertools",
            #    which happens on line 3. Again, you need parentheses to show
            #    which indices are grouped together.
            # Using stuff like this really helps keep the indentations under
            # control. Nested loops and conditionals are really slow in Python,
            # so it's a good idea to combine them using tools like this whenever
            # possible.
            hess[i, j] = v_klmn(k, l, m, n, dm1_cirot, tdm1) + v_klmn(
                l, k, n, m, dm1_cirot, tdm1) - v_klmn(
                    k, l, n, m, dm1_cirot, tdm1) - v_klmn(
                        l, k, m, n, dm1_cirot, tdm1)

#       MRH: print some diagnostic stuff, but only do the potentially-expensive
#       diagonalization if the user-specified verbosity is high enough
#        if log.verbose >= lib.logger.DEBUG:
        evals, evecs = linalg.eigh(hess)
        evecs = np.array(evecs)
        log.info("Hessian eigenvalues: {}".format(evals))
        hess1 = hess
        #        print("hess1",hess)
        #        print("evals",evals)

        for i in range(pairs):
            if 1E-09 > evals[i] and evals[i] > -1E-09:
                log.info("Hess is singular!")
            if evals[i] > 0:
                neg = False
                break
            neg = True
        log.info("Hess diag is neg? {}".format(neg))
        #        If the diagonals are positive make them negative:
        if neg == False:
            for i in range(pairs):
                if evals[i] > 0:
                    evals[i] = -evals[i]
#      Remake the Hessian
        diag = np.identity(pairs) * evals
        hess = np.dot(np.dot(evecs, diag), evecs.T)
        hess2 = hess
        #        print("hess2", hess)
        #        print("difference between hessian", hess2-hess1)

        #       Make T

        t_add = linalg.solve(hess, -grad)
        t[:] = 0
        t[np.tril_indices(t.shape[0], k=-1)] = t_add

        t = t - t.T
        # t = t + t_old
        # MRH: I don't think you add them. They're expressed in different
        # bases, and anyway ci_rot already has the effect of t_old in it. On
        # iteration zero, say ci_rot is called ci0. Then on iteration 1, it's
        # ci1 = expm (t1) ci0
        # Then on iteration 2, it's
        # ci2 = expm (t2) ci1 = expm (t2) expm (t1) ci0
        # and so forth. So you don't need to keep the running sum.
        t_old = t.copy()

        #       Reset Old Values

        ci_old = ci_rot
        e_coul_old = e_coul_new

        if grad_norm < thrs and neg == True:
            conv = True
            break

#########################
# End Loop

    if conv:
        log.note("CMS-PDFT intermediate state determination CONVERGED")
    else:
        log.note(("CMS-PDFT intermediate state determination did not converge"
                  " after {} cycles").format(it))

# Intermediate Energies
# Run MC-PDFT
#mc.ci = ci_final
#E_int = np.zeros((nroots))
#with lib.temporary_env (mc, ci=ci_rot):
#    # This ^ ~temporarily sets mc.ci to ci_rot
#    # As soon as you leave this indent block, it returns to
#    # whatever it was before. Convenient! Of course, it would
#    # be WAY BETTER for me to just implement ci as a kwarg
#    # in mcpdft.kernel.
#    for i in range(nroots):
#        E_int [i]= mcpdft.mcpdft.kernel(mc,mc.otfnal,root=i)[0]
    E_int = np.asarray(
        [mcpdft.mcpdft.kernel(mc, ot=mc.otfnal, ci=c)[0] for c in ci_rot])
    log.info("CMS-PDFT intermediate state energies: {}".format(E_int))

    #Compute the full Hamiltonian

    h1, h0 = mc.get_h1eff()

    h2 = mc.get_h2eff()

    h2eff = direct_spin1.absorb_h1e(h1, h2, mc.ncas, mc.nelecas, 0.5)

    hc_all = [
        direct_spin1.contract_2e(h2eff, c, mc.ncas, mc.nelecas) for c in ci_rot
    ]

    Ham = np.tensordot(ci_rot, hc_all, axes=((1, 2), (1, 2)))

    #   print ("ham", Ham)

    for i in range(nroots):
        Ham[i, i] = E_int[i]


#    print("ham",Ham)

    log.info("Effective hamiltonian: {}".format(Ham))

    e_cms, e_vecs = linalg.eigh(Ham)

    #    print("e_cms", e_cms)

    log.info("CMS-PDFT final state energies: {}".format(e_cms))

    return conv, E_int, ci_rot