Example #1
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)
Example #2
0
def make_rdm1 (fci, fcivec, norb, nelec, **kwargs):
    dm1 = np.zeros ((norb, norb))
    for nelec in product (range (norb+1), repeat=2):
        ci = fockspace.fock2hilbert (fcivec, norb, nelec)
        d = direct_spin1.make_rdm1 (ci, norb, nelec, **kwargs)
        dm1 += d
    return dm1
Example #3
0
def transform_ci_for_orbital_rotation (fci, ci, norb, nelec, umat):
    fcivec = np.zeros_like (ci) 
    for ne in product (range (norb+1), repeat=2):
        c = np.squeeze (fockspace.fock2hilbert (ci, norb, ne))
        c = fci_addons.transform_ci_for_orbital_rotation (c, norb, ne, umat)
        fcivec += np.squeeze (fockspace.hilbert2fock (c, norb, ne))
    return fcivec
Example #4
0
def make_rdm1s (fci, fcivec, norb, nelec, **kwargs):
    dm1a = np.zeros ((norb,norb))
    dm1b = np.zeros ((norb,norb))
    for nelec in product (range (norb+1), repeat=2):
        ci = fockspace.fock2hilbert (fcivec, norb, nelec)
        da, db = direct_spin1.make_rdm1s (ci, norb, nelec, **kwargs)
        dm1a += da
        dm1b += db
    return dm1a, dm1b
Example #5
0
def spin_square (fci, fcivec, norb, nelec):
    ss = 0.0
    for ne in product (range (norb+1), repeat=2):
        c = fockspace.fock2hilbert (fcivec, norb, ne)
        ssc = spin_op.contract_ss (c, norb, ne)
        ss += c.conj ().ravel ().dot (ssc.ravel ())
    s = np.sqrt(ss+.25) - .5
    multip = s*2+1
    return ss, multip
Example #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
Example #7
0
 def check_ci0_constr (self):
     norb, nelec = self.norb, self.nelec
     ci0 = self.dp_ci (self.ci_f)
     neleca_min = max (0, nelec-norb)
     neleca_max = min (norb, nelec)
     w = 0.0
     for neleca in range (neleca_min, neleca_max+1):
         nelecb = nelec - neleca
         c = fockspace.fock2hilbert (ci0, norb, (neleca,nelecb)).ravel ()
         w += c.conj ().dot (c)
     return w>1e-8
Example #8
0
 def test_s2(self):
     for norb, c, uop in zip(range(2, 5), c_list, uop_s_list):
         ssc_ref = np.zeros_like(c)
         for nelec in product(range(norb + 1), repeat=2):
             c_h = np.squeeze(fockspace.fock2hilbert(c, norb, nelec))
             ssc_h = direct_spin1.contract_ss(c_h, norb, nelec)
             ssc_ref += fockspace.hilbert2fock(ssc_h, norb, nelec).ravel()
         ssc = contract_s2(c, norb)
         with self.subTest(norb=norb, checking='s2 op'):
             self.assertAlmostEqual(lib.fp(ssc), lib.fp(ssc_ref), 6)
         uc = uop(c)
         ussc = uop(ssc)
         ssuc = contract_s2(uc, norb)
         commutator = ussc - ssuc
         with self.subTest(norb=norb, checking='singles operator symmetry'):
             self.assertLessEqual(linalg.norm(commutator), 1e-8)
Example #9
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)
Example #10
0
    def pbin (n, k=norb):
        s = bin (n)[2:]
        m = (2*k) - len (s)
        if m: s = ''.join (['0',]*m) + s
        return s
    psi = np.zeros (2**(2*norb))
    psi[51] = 1.0

    from pyscf.fci import cistring, spin_op
    from mrh.exploratory.citools import fockspace

    t1_rand = np.random.rand (norb,norb)
    t2_rand = np.random.rand (norb,norb,norb,norb)
    uop_s = get_uccs_op (norb, t1=t1_rand)
    upsi = uop_s (psi)
    upsi_h = fockspace.fock2hilbert (upsi, norb, nelec)
    uTupsi = uop_s (upsi, transpose=True)
    for ix in range (2**(2*norb)):
        if np.any (np.abs ([psi[ix], upsi[ix], uTupsi[ix]]) > 1e-8):
            print (pbin (ix), psi[ix], upsi[ix], uTupsi[ix])
    print ("<psi|psi> =",psi.dot (psi), "<psi|U|psi> =",psi.dot (upsi),"<psi|U'U|psi> =",upsi.dot (upsi))
    print ("<psi|S**2|psi> =",spin_square (psi, norb)[0],
           "<psi|U'S**2U|psi> =",spin_square (upsi, norb)[0],spin_op.spin_square (upsi_h, norb, nelec)[0])

    uop_sd = get_uccsd_op (norb)
    x_rand = (1 - 2*np.random.rand (uop_sd.ngen_uniq)) * math.pi/4
    uop_sd.set_uniq_amps_(x_rand)
    upsi = uop_sd (psi)
    upsi_h = fockspace.fock2hilbert (upsi, norb, nelec)
    uTupsi = uop_sd (upsi, transpose=True)
    for ix in range (2**(2*norb)):
Example #11
0
fcivec = psi.get_fcivec()  # |LASUCC> itself as a CI vector
ss, multip = mc.fcisolver.spin_square(fcivec, 4, 'ThisArgDoesntMatter')
print("<LASUCC|S^2|LASUCC> = {:.3f}; apparent S = {:.1f}".format(
    ss, 0.5 * (multip - 1)))
print("But is that really the case?")
print("Singlet weight: {:.2f}".format(
    fockspace.hilbert_sector_weight(fcivec, 4, (2, 2), 1)))
print("Triplet weight: {:.2f}".format(
    fockspace.hilbert_sector_weight(fcivec, 4, (2, 2), 3)))
print("Quintet weight: {:.2f}".format(
    fockspace.hilbert_sector_weight(fcivec, 4, (2, 2), 5)))
print("Oh well, I guess it couldn't have been anything else.\n")

ci_f = psi.ci_f  # list of optimized CI vectors for each fragment
ci_h = [fockspace.fock2hilbert(c, 2, (1, 1)) for c in ci_f]
w_nb = [
    linalg.norm(c_f)**2 - linalg.norm(c_h)**2
    for (c_f, c_h) in zip(ci_f, ci_h)
]
print(("Wave function weight outside of the singlet 2-electron "
       "Hilbert space"))
print(("(If these numbers are nonzero, then my implementation "
       "of UCC doesn't pointlessly waste memory)"))
for ix in range(2):
    print("Fragment {}: {:.1e}".format(ix, w_nb[ix]))

# U'HU for a single fragment can be retrieved as a
# LASUCCEffectiveHamiltonian object, which is just the ndarray (in
# the member "full") and some convenience functions
heff = psi.get_dense_heff(x, h, 0)