Beispiel #1
0
def Wooov(t1, t2, eris):
    t1a, t1b = t1
    t2aa, t2ab, t2bb = t2
    dtype = np.result_type(t1a, t1b, t2aa, t2ab, t2bb)

    eris_ovoo = np.asarray(eris.ovoo)
    eris_OVOO = np.asarray(eris.OVOO)
    eris_OVoo = np.asarray(eris.OVoo)
    eris_ovOO = np.asarray(eris.ovOO)
    ovoo = eris_ovoo - eris_ovoo.transpose(2,1,0,3)
    OVOO = eris_OVOO - eris_OVOO.transpose(2,1,0,3)
    wooov = np.array(     ovoo.transpose(2,3,0,1), dtype=dtype)
    wOOOV = np.array(     OVOO.transpose(2,3,0,1), dtype=dtype)
    wooOV = np.array(eris_OVoo.transpose(2,3,0,1), dtype=dtype)
    wOOov = np.array(eris_ovOO.transpose(2,3,0,1), dtype=dtype)
    eris_ovoo = eris_OVOO = eris_ovOO = eris_OVoo = None

    eris_ovov = np.asarray(eris.ovov)
    eris_OVOV = np.asarray(eris.OVOV)
    eris_ovOV = np.asarray(eris.ovOV)
    ovov = eris_ovov - eris_ovov.transpose(0,3,2,1)
    OVOV = eris_OVOV - eris_OVOV.transpose(0,3,2,1)

    wooov += lib.einsum('if,mfne->mine', t1a,      ovov)
    wOOOV += lib.einsum('if,mfne->mine', t1b,      OVOV)
    wooOV += lib.einsum('if,mfNE->miNE', t1a, eris_ovOV)
    wOOov += lib.einsum('IF,neMF->MIne', t1b, eris_ovOV)
    return wooov, wooOV, wOOov, wOOOV
Beispiel #2
0
def Wvvov(t1, t2, eris):
    t1a, t1b = t1
    t2aa, t2ab, t2bb = t2
    nocca, noccb, nvira, nvirb = t2ab.shape
    dtype = np.result_type(t1a, t1b, t2aa, t2ab, t2bb)

    #:Wamef = einsum('na,nmef->amef', -t1, eris.oovv)
    #:Wamef -= np.asarray(eris.ovvv).transpose(1,0,2,3)
    eris_ovov = np.asarray(eris.ovov)
    eris_OVOV = np.asarray(eris.OVOV)
    eris_ovOV = np.asarray(eris.ovOV)
    Waemf = lib.einsum('na,nemf->aemf',-t1a, eris_ovov)
    Waemf+= np.asarray(eris.get_ovvv()).transpose(2,3,0,1)
    Waemf = Waemf - Waemf.transpose(0,3,2,1)

    WaeMF = lib.einsum('na,nemf->aemf',-t1a, eris_ovOV)
    WaeMF+= np.asarray(eris.get_OVvv()).transpose(2,3,0,1)

    WAEmf = lib.einsum('na,mfne->aemf',-t1b, eris_ovOV)
    WAEmf+= np.asarray(eris.get_ovVV()).transpose(2,3,0,1)

    WAEMF = lib.einsum('na,nemf->aemf',-t1b, eris_OVOV)
    WAEMF+= np.asarray(eris.get_OVVV()).transpose(2,3,0,1)
    WAEMF = WAEMF - WAEMF.transpose(0,3,2,1)
    return Waemf, WaeMF, WAEmf, WAEMF
Beispiel #3
0
    def test_spin_squre(self):
        ss = fci.spin_op.spin_square(ci0, norb, nelec)
        self.assertAlmostEqual(ss[0], 6, 9)
        ss = fci.spin_op.spin_square0(ci0, norb, nelec)
        self.assertAlmostEqual(ss[0], 6, 9)

        numpy.random.seed(1)
        u,w,v = numpy.linalg.svd(numpy.random.random((norb,6)))
        u = u[:,:6]
        h1a = h1[:6,:6]
        h1b = reduce(numpy.dot, (v.T, h1a, v))
        h2aa = ao2mo.restore(1, h2, norb)[:6,:6,:6,:6]
        h2ab = lib.einsum('klpq,pi,qj->klij', h2aa, v, v)
        h2bb = lib.einsum('pqkl,pi,qj->ijkl', h2ab, v, v)
        e1, ci1 = fci.direct_uhf.kernel((h1a,h1b), (h2aa,h2ab,h2bb), 6, (3,2))
        ss = fci.spin_op.spin_square(ci1, 6, (3,2), mo_coeff=(numpy.eye(6),v))[0]
        self.assertAlmostEqual(ss, 3.75, 8)

        numpy.random.seed(1)
        n = fci.cistring.num_strings(6,3)
        ci1 = numpy.random.random((n,n))
        ss1 = numpy.einsum('ij,ij->', ci1, fci.spin_op.contract_ss(ci1, 6, 6))
        self.assertAlmostEqual(ss1, fci.spin_op.spin_square(ci1, 6, 6)[0], 12)

        na = fci.cistring.num_strings(6,4)
        nb = fci.cistring.num_strings(6,2)
        ci1 = numpy.random.random((na,nb))
        ss1 = numpy.einsum('ij,ij->', ci1, fci.spin_op.contract_ss(ci1, 6, (4,2)))
        self.assertAlmostEqual(ss1, fci.spin_op.spin_square(ci1, 6, (4,2))[0], 12)

        numpy.random.seed(1)
        n = fci.cistring.num_strings(10,5)
        ci1 = numpy.random.random((n,n))
        ss1 = numpy.einsum('ij,ij->', ci1, fci.spin_op.contract_ss(ci1, 10, 10))
        self.assertAlmostEqual(ss1, fci.spin_op.spin_square(ci1, 10, 10)[0], 8)
Beispiel #4
0
    def test_eris_contract_vvvv_t2(self):
        mol = gto.Mole()
        nocc, nvir = 5, 12
        nvir_pair = nvir*(nvir+1)//2
        numpy.random.seed(9)
        t2 = numpy.random.random((nocc,nocc,nvir,nvir)) - .5
        t2 = t2 + t2.transpose(1,0,3,2)
        eris = ccsd._ChemistsERIs()
        vvvv = numpy.random.random((nvir_pair,nvir_pair)) - .5
        eris.vvvv = vvvv + vvvv.T
        eris.mol = mol
        mycc.max_memory, bak = 0, mycc.max_memory
        vt2 = eris._contract_vvvv_t2(mycc, t2, eris.vvvv)
        mycc.max_memory = bak
        self.assertAlmostEqual(lib.finger(vt2), -39.572579908080087, 11)
        vvvv = ao2mo.restore(1, eris.vvvv, nvir)
        ref = lib.einsum('acbd,ijcd->ijab', vvvv, t2)
        self.assertAlmostEqual(abs(vt2 - ref).max(), 0, 11)

        # _contract_s1vvvv_t2, testing complex and real mixed contraction
        vvvv =(numpy.random.random((nvir,nvir,nvir,nvir)) +
               numpy.random.random((nvir,nvir,nvir,nvir))*1j - (.5+.5j))
        vvvv = vvvv + vvvv.transpose(1,0,3,2).conj()
        vvvv = vvvv + vvvv.transpose(2,3,0,1)
        eris.vvvv = vvvv
        eris.mol = mol
        mycc.max_memory, bak = 0, mycc.max_memory
        vt2 = eris._contract_vvvv_t2(mycc, t2, eris.vvvv)
        mycc.max_memory = bak
        self.assertAlmostEqual(lib.finger(vt2), 23.502736435296871+113.90422480013488j, 11)
        ref = lib.einsum('acbd,ijcd->ijab', eris.vvvv, t2)
        self.assertAlmostEqual(abs(vt2 - ref).max(), 0, 11)
Beispiel #5
0
    def test_eris_contract_vvvv_t2(self):
        mol = gto.Mole()
        nocca, noccb, nvira, nvirb = 5, 4, 12, 13
        nvira_pair = nvira*(nvira+1)//2
        nvirb_pair = nvirb*(nvirb+1)//2
        numpy.random.seed(9)
        t2 = numpy.random.random((nocca,noccb,nvira,nvirb))
        eris = uccsd._ChemistsERIs()
        eris.vvVV = numpy.random.random((nvira_pair,nvirb_pair))
        eris.mol = mol
        myucc.max_memory, bak = 0, myucc.max_memory
        vt2 = eris._contract_vvVV_t2(myucc, t2, eris.vvVV)
        myucc.max_memory = bak
        self.assertAlmostEqual(lib.finger(vt2), 12.00904827896089, 11)
        idxa = lib.square_mat_in_trilu_indices(nvira)
        idxb = lib.square_mat_in_trilu_indices(nvirb)
        vvVV = eris.vvVV[:,idxb][idxa]
        ref = lib.einsum('acbd,ijcd->ijab', vvVV, t2)
        self.assertAlmostEqual(abs(vt2 - ref).max(), 0, 11)

        # _contract_VVVV_t2, testing complex and real mixed contraction
        VVVV =(numpy.random.random((nvirb,nvirb,nvirb,nvirb)) +
               numpy.random.random((nvirb,nvirb,nvirb,nvirb))*1j - (.5+.5j))
        VVVV = VVVV + VVVV.transpose(1,0,3,2).conj()
        VVVV = VVVV + VVVV.transpose(2,3,0,1)
        eris.VVVV = VVVV
        t2 = numpy.random.random((noccb,noccb,nvirb,nvirb))
        t2 = t2 - t2.transpose(0,1,3,2)
        t2 = t2 - t2.transpose(1,0,3,2)
        myucc.max_memory, bak = 0, myucc.max_memory
        vt2 = eris._contract_VVVV_t2(myucc, t2, eris.VVVV)
        myucc.max_memory = bak
        self.assertAlmostEqual(lib.finger(vt2), 47.903883794299404-50.501573400833429j, 11)
        ref = lib.einsum('acbd,ijcd->ijab', eris.VVVV, t2)
        self.assertAlmostEqual(abs(vt2 - ref).max(), 0, 11)
Beispiel #6
0
    def vind(xys):
        nz = len(xys)
        dm1a = numpy.empty((nz,nao,nao))
        dm1b = numpy.empty((nz,nao,nao))
        for i in range(nz):
            xa, xb, ya, yb = numpy.split(xys[i], offsets)
            dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca)  , orboa.T))
            dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T, orbva.T))
            dm1a[i] = dmx + dmy  # AX + BY
            dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb)  , orbob.T))
            dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T, orbvb.T))
            dm1b[i] = dmx + dmy  # AX + BY

        v1ao = vresp(numpy.stack((dm1a,dm1b)))
        v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz,-1)
        v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz,-1)
        v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz,-1)
        v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz,-1)

        for i in range(nz):
            xa, xb, ya, yb = numpy.split(xys[i], offsets)
            v1voa[i] += (e_ai_a - freq - diag[0]) * xa
            v1voa[i] /= diag[0]
            v1vob[i] += (e_ai_b - freq - diag[1]) * xb
            v1vob[i] /= diag[1]
            v1ova[i] += (e_ai_a + freq - diag[2]) * ya
            v1ova[i] /= diag[2]
            v1ovb[i] += (e_ai_b + freq - diag[3]) * yb
            v1ovb[i] /= diag[3]
        v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb))
        return v
Beispiel #7
0
def _add_vvvv_full(mycc, t1T, t2T, eris, out=None, with_ovvv=False):
    '''Ht2 = numpy.einsum('ijcd,acdb->ijab', t2, vvvv)
    without using symmetry t2[ijab] = t2[jiba] in t2 or Ht2
    '''
    time0 = time.clock(), time.time()
    log = logger.Logger(mycc.stdout, mycc.verbose)

    nvir_seg, nvir, nocc = t2T.shape[:3]
    vloc0, vloc1 = _task_location(nvir, rank)
    nocc2 = nocc*(nocc+1)//2
    if t1T is None:
        tau = lib.pack_tril(t2T.reshape(nvir_seg*nvir,nocc2))
    else:
        tau = t2T + numpy.einsum('ai,bj->abij', t1T[vloc0:vloc1], t1T)
        tau = lib.pack_tril(tau.reshape(nvir_seg*nvir,nocc2))
    tau = tau.reshape(nvir_seg,nvir,nocc2)

    if mycc.direct:   # AO-direct CCSD
        if with_ovvv:
            raise NotImplementedError
        mo = getattr(eris, 'mo_coeff', None)
        if mo is None:  # If eris does not have the attribute mo_coeff
            mo = _mo_without_core(mycc, mycc.mo_coeff)

        ao_loc = mycc.mol.ao_loc_nr()
        nao, nmo = mo.shape
        ntasks = mpi.pool.size
        task_sh_locs = lib.misc._balanced_partition(ao_loc, ntasks)
        ao_loc0 = ao_loc[task_sh_locs[rank  ]]
        ao_loc1 = ao_loc[task_sh_locs[rank+1]]

        orbv = mo[:,nocc:]
        tau = lib.einsum('abij,pb->apij', tau, orbv)
        tau_priv = numpy.zeros((ao_loc1-ao_loc0,nao,nocc,nocc))
        for task_id, tau in _rotate_tensor_block(tau):
            loc0, loc1 = _task_location(nvir, task_id)
            tau_priv += lib.einsum('pa,abij->pbij', orbv[ao_loc0:ao_loc1,loc0:loc1], tau)
        tau = None
        time1 = log.timer_debug1('vvvv-tau mo2ao', *time0)

        buf = _contract_vvvv_t2(mycc, None, tau_priv, task_sh_locs, None, log)
        buf = buf.reshape(tau_priv.shape)
        tau_priv = None
        time1 = log.timer_debug1('vvvv-tau contraction', *time1)

        buf = lib.einsum('apij,pb->abij', buf, orbv)
        Ht2 = numpy.ndarray(t2T.shape, buffer=out)
        Ht2[:] = 0
        for task_id, buf in _rotate_tensor_block(buf):
            ao_loc0 = ao_loc[task_sh_locs[task_id  ]]
            ao_loc1 = ao_loc[task_sh_locs[task_id+1]]
            Ht2 += lib.einsum('pa,pbij->abij', orbv[ao_loc0:ao_loc1,vloc0:vloc1], buf)

        time1 = log.timer_debug1('vvvv-tau ao2mo', *time1)
    else:
        raise NotImplementedError
    return Ht2.reshape(t2T.shape)
Beispiel #8
0
def para(magobj, gauge_orig=None, h1=None, s1=None, with_cphf=None):
    '''Paramagnetic susceptibility tensor

    Kwargs:
        h1: A list of arrays. Shapes are [(3,nmo_a,nocc_a), (3,nmo_b,nocc_b)]
            First order Fock matrices in MO basis.
        s1: A list of arrays. Shapes are [(3,nmo_a,nocc_a), (3,nmo_b,nocc_b)]
            First order overlap matrices in MO basis.
        with_cphf : boolean or  function(dm_mo) => v1_mo
            If a boolean value is given, the value determines whether CPHF
            equation will be solved or not. The induced potential will be
            generated by the function gen_vind.
            If a function is given, CPHF equation will be solved, and the
            given function is used to compute induced potential
    '''
    log = logger.Logger(magobj.stdout, magobj.verbose)
    cput1 = (time.clock(), time.time())

    mol = magobj.mol
    mf = magobj._scf
    mo_energy = magobj._scf.mo_energy
    mo_coeff = magobj._scf.mo_coeff
    mo_occ = magobj._scf.mo_occ
    orboa = mo_coeff[0][:,mo_occ[0] > 0]
    orbob = mo_coeff[1][:,mo_occ[1] > 0]

    if h1 is None:
        # Imaginary part of F10
        dm0 = (numpy.dot(orboa, orboa.T), numpy.dot(orbob, orbob.T))
        h1 = magobj.get_fock(dm0, gauge_orig)
        h1 = (lib.einsum('xpq,pi,qj->xij', h1[0], mo_coeff[0].conj(), orboa),
              lib.einsum('xpq,pi,qj->xij', h1[1], mo_coeff[1].conj(), orbob))
        cput1 = log.timer('first order Fock matrix', *cput1)
    if s1 is None:
        # Imaginary part of S10
        s1 = magobj.get_ovlp(mol, gauge_orig)
        s1 = (lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[0].conj(), orboa),
              lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[1].conj(), orbob))

    with_cphf = magobj.cphf
    mo1, mo_e1 = uhf_nmr.solve_mo1(magobj, mo_energy, mo_coeff, mo_occ,
                                   h1, s1, with_cphf)
    cput1 = logger.timer(magobj, 'solving mo1 eqn', *cput1)

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    mag_para = numpy.einsum('yji,xji->xy', mo1[0], h1[0])
    mag_para+= numpy.einsum('yji,xji->xy', mo1[1], h1[1])
    mag_para-= numpy.einsum('yji,xji,i->xy', mo1[0], s1[0], mo_energy[0][occidxa])
    mag_para-= numpy.einsum('yji,xji,i->xy', mo1[1], s1[1], mo_energy[1][occidxb])
    # + c.c.
    mag_para = mag_para + mag_para.conj()

    mag_para-= numpy.einsum('xij,yij->xy', s1[0][:,occidxa], mo_e1[0])
    mag_para-= numpy.einsum('xij,yij->xy', s1[1][:,occidxb], mo_e1[1])
    return -mag_para
Beispiel #9
0
def hyper_polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import uhf as uhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    mo0a, mo0b = mo_coeff
    orboa = mo0a[:, occidxa]
    orbva = mo0a[:,~occidxa]
    orbob = mo0b[:, occidxb]
    orbvb = mo0b[:,~occidxb]

    charges = mol.atom_charges()
    coords  = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa)
    h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob)
    s1a = numpy.zeros_like(h1a)
    s1b = numpy.zeros_like(h1b)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1, e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), (s1a,s1b),
                              polobj.max_cycle_cphf, polobj.conv_tol, verbose=log)
    else:
        mo1, e1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a,h1b),
                                               (s1a,s1b))
    mo1a = lib.einsum('xqi,pq->xpi', mo1[0], mo0a)
    mo1b = lib.einsum('xqi,pq->xpi', mo1[1], mo0b)

    dm1a = lib.einsum('xpi,qi->xpq', mo1a, orboa)
    dm1b = lib.einsum('xpi,qi->xpq', mo1b, orbob)
    dm1a = dm1a + dm1a.transpose(0,2,1)
    dm1b = dm1b + dm1b.transpose(0,2,1)
    vresp = _gen_uhf_response(mf, hermi=1)
    h1ao = int_r + vresp(numpy.stack((dm1a, dm1b)))
    s0 = mf.get_ovlp()
    e3  = lib.einsum('xpq,ypi,zqi->xyz', h1ao[0], mo1a, mo1a)
    e3 += lib.einsum('xpq,ypi,zqi->xyz', h1ao[1], mo1b, mo1b)
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1a, mo1a, e1[0])
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1b, mo1b, e1[1])
    e3 = (e3 + e3.transpose(1,2,0) + e3.transpose(2,0,1) +
          e3.transpose(0,2,1) + e3.transpose(1,0,2) + e3.transpose(2,1,0))
    e3 = -e3
    log.debug('Static hyper polarizability tensor\n%s', e3)
    return e3
Beispiel #10
0
def para(magobj, gauge_orig=None, h1=None, s1=None, with_cphf=None):
    '''Paramagnetic susceptibility tensor

    Kwargs:
        h1: (3,nmo,nocc) array
            First order Fock matrix in MO basis.
        s1: (3,nmo,nocc) array
            First order overlap matrix in MO basis.
        with_cphf : boolean or  function(dm_mo) => v1_mo
            If a boolean value is given, the value determines whether CPHF
            equation will be solved or not. The induced potential will be
            generated by the function gen_vind.
            If a function is given, CPHF equation will be solved, and the
            given function is used to compute induced potential
    '''
    log = logger.Logger(magobj.stdout, magobj.verbose)
    cput1 = (time.clock(), time.time())

    mol = magobj.mol
    mf = magobj._scf
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = mo_occ > 0
    orbo = mo_coeff[:,occidx]

    if h1 is None:
        # Imaginary part of F10
        dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        h1 = lib.einsum('xpq,pi,qj->xij', magobj.get_fock(dm0, gauge_orig),
                        mo_coeff.conj(), orbo)
    if s1 is None:
        # Imaginary part of S10
        s1 = lib.einsum('xpq,pi,qj->xij', magobj.get_ovlp(mol, gauge_orig),
                        mo_coeff.conj(), orbo)
    cput1 = log.timer('first order Fock matrix', *cput1)

    with_cphf = magobj.cphf
    mo1, mo_e1 = rhf_nmr.solve_mo1(magobj, mo_energy, mo_coeff, mo_occ,
                                   h1, s1, with_cphf)
    cput1 = logger.timer(magobj, 'solving mo1 eqn', *cput1)

    mag_para = numpy.einsum('yji,xji->xy', mo1, h1)
    mag_para-= numpy.einsum('yji,xji,i->xy', mo1, s1, mo_energy[occidx])
    # + c.c.
    mag_para = mag_para + mag_para.conj()

    mag_para-= numpy.einsum('xij,yij->xy', s1[:,occidx], mo_e1)

    # *2 for double occupancy.
    mag_para *= 2
    return -mag_para
Beispiel #11
0
 def vind(mo1):
     mo1 = mo1.reshape(-1,nmoa*nocca+nmob*noccb)
     mo1a = mo1[:,:nmoa*nocca].reshape(-1,nmoa,nocca)
     mo1b = mo1[:,nmoa*nocca:].reshape(-1,nmob,noccb)
     dm1a = lib.einsum('xai,pa,qi->xpq', mo1a, mo0a, orboa.conj())
     dm1b = lib.einsum('xai,pa,qi->xpq', mo1b, mo0b, orbob.conj())
     dm1a = dm1a + dm1a.transpose(0,2,1).conj()
     dm1b = dm1b + dm1b.transpose(0,2,1).conj()
     v1ao = vresp(numpy.stack((dm1a,dm1b)))
     v1a = lib.einsum('xpq,pi,qj->xij', v1ao[0], mo0a.conj(), orboa)
     v1b = lib.einsum('xpq,pi,qj->xij', v1ao[1], mo0b.conj(), orbob)
     v1mo = numpy.hstack((v1a.reshape(-1,nmoa*nocca),
                          v1b.reshape(-1,nmob*noccb)))
     return v1mo.ravel()
Beispiel #12
0
def _make_rdm1(mycc, d1, with_frozen=True, ao_repr=False):
    doo, dOO = d1[0]
    dov, dOV = d1[1]
    dvo, dVO = d1[2]
    dvv, dVV = d1[3]
    nocca, nvira = dov.shape
    noccb, nvirb = dOV.shape
    nmoa = nocca + nvira
    nmob = noccb + nvirb

    dm1a = numpy.empty((nmoa,nmoa), dtype=doo.dtype)
    dm1a[:nocca,:nocca] = doo + doo.conj().T
    dm1a[:nocca,nocca:] = dov + dvo.conj().T
    dm1a[nocca:,:nocca] = dm1a[:nocca,nocca:].conj().T
    dm1a[nocca:,nocca:] = dvv + dvv.conj().T
    dm1a *= .5
    dm1a[numpy.diag_indices(nocca)] += 1

    dm1b = numpy.empty((nmob,nmob), dtype=dOO.dtype)
    dm1b[:noccb,:noccb] = dOO + dOO.conj().T
    dm1b[:noccb,noccb:] = dOV + dVO.conj().T
    dm1b[noccb:,:noccb] = dm1b[:noccb,noccb:].conj().T
    dm1b[noccb:,noccb:] = dVV + dVV.conj().T
    dm1b *= .5
    dm1b[numpy.diag_indices(noccb)] += 1

    if with_frozen and not (mycc.frozen is 0 or mycc.frozen is None):
        nmoa = mycc.mo_occ[0].size
        nmob = mycc.mo_occ[1].size
        nocca = numpy.count_nonzero(mycc.mo_occ[0] > 0)
        noccb = numpy.count_nonzero(mycc.mo_occ[1] > 0)
        rdm1a = numpy.zeros((nmoa,nmoa), dtype=dm1a.dtype)
        rdm1b = numpy.zeros((nmob,nmob), dtype=dm1b.dtype)
        rdm1a[numpy.diag_indices(nocca)] = 1
        rdm1b[numpy.diag_indices(noccb)] = 1
        moidx = mycc.get_frozen_mask()
        moidxa = numpy.where(moidx[0])[0]
        moidxb = numpy.where(moidx[1])[0]
        rdm1a[moidxa[:,None],moidxa] = dm1a
        rdm1b[moidxb[:,None],moidxb] = dm1b
        dm1a = rdm1a
        dm1b = rdm1b

    if ao_repr:
        mo_a, mo_b = mycc.mo_coeff
        dm1a = lib.einsum('pi,ij,qj->pq', mo_a, dm1a, mo_a)
        dm1b = lib.einsum('pi,ij,qj->pq', mo_b, dm1b, mo_b)
    return dm1a, dm1b
Beispiel #13
0
def kernel(method, efg_nuc=None):
    log = lib.logger.Logger(method.stdout, method.verbose)
    cell = method.cell
    if efg_nuc is None:
        efg_nuc = range(cell.natm)

    dm = method.make_rdm1()
    if isinstance(method, scf.khf.KSCF):
        if isinstance(dm[0][0], numpy.ndarray) and dm[0][0].ndim == 2:
            dm = dm[0] + dm[1]  # KUHF density matrix
    elif isinstance(method, scf.hf.SCF):
        if isinstance(dm[0], numpy.ndarray) and dm[0].ndim == 2:
            dm = dm[0] + dm[1]  # UHF density matrix
    else:
        mo = method.mo_coeff
        if isinstance(dm[0][0], numpy.ndarray) and dm[0][0].ndim == 2:
            dm_a = [lib.einsum('pi,ij,qj->pq', c, dm[0][k], c.conj())
                    for k, c in enumerate(mo)]
            dm_b = [lib.einsum('pi,ij,qj->pq', c, dm[1][k], c.conj())
                    for k, c in enumerate(mo)]
            dm = lib.asarray(dm_a) + lib.asarray(dm_b)
        else:
            dm = lib.asarray([lib.einsum('pi,ij,qj->pq', c, dm[k], c.conj())
                              for k, c in enumerate(mo)])

    if isinstance(method, scf.hf.SCF):
        with_df = getattr(method, 'with_df', None)
        with_x2c = getattr(method, 'with_x2c', None)
    else:
        with_df = getattr(method._scf, 'with_df', None)
        with_x2c = getattr(method._scf, 'with_x2c', None)
    if with_x2c:
        raise NotImplementedError

    log.info('\nElectric Field Gradient Tensor Results')
    if isinstance(with_df, df.fft.FFTDF):
        efg_e = _fft_quad_integrals(with_df, dm, efg_nuc)
    else:
        efg_e = _aft_quad_integrals(with_df, dm, efg_nuc)
    efg = []
    for i, atm_id in enumerate(efg_nuc):
        efg_nuc = _get_quad_nuc(cell, atm_id)
        v = efg_nuc - efg_e[i]
        efg.append(v)

        rhf_efg._analyze(cell, atm_id, v, log)

    return numpy.asarray(efg)
Beispiel #14
0
    def test_uccsd_rdm2_mo2ao(self):
        mol = gto.Mole()
        mol.verbose = 0
        mol.atom = [
            [8 , (0. , 0.     , 0.)],
            [1 , (0. , -0.757 , 0.587)],
            [1 , (0. , 0.757  , 0.587)]]
        mol.spin = 2
        mol.basis = '631g'
        mol.build(0, 0)
        mf = scf.UHF(mol)
        mf.conv_tol_grad = 1e-8
        mf.kernel()
        mycc = cc.UCCSD(mf)
        mycc.diis_start_cycle = 1
        mycc.conv_tol = 1e-10
        eris = mycc.ao2mo()
        ecc, t1, t2 = mycc.kernel(eris=eris)
        l1, l2 = mycc.solve_lambda(eris=eris)
        fdm2 = lib.H5TmpFile()
        d2 = cc.uccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True)

        nao = mycc.mo_coeff[0].shape[0]
        ref = cc.uccsd_rdm._make_rdm2(mycc, None, d2, with_dm1=False)
        aa = lib.einsum('ijkl,pi,qj,rk,sl->pqrs', ref[0], mycc.mo_coeff[0],
                        mycc.mo_coeff[0], mycc.mo_coeff[0], mycc.mo_coeff[0])
        ab = lib.einsum('ijkl,pi,qj,rk,sl->pqrs', ref[1], mycc.mo_coeff[0],
                        mycc.mo_coeff[0], mycc.mo_coeff[1], mycc.mo_coeff[1])
        bb = lib.einsum('ijkl,pi,qj,rk,sl->pqrs', ref[2], mycc.mo_coeff[1],
                        mycc.mo_coeff[1], mycc.mo_coeff[1], mycc.mo_coeff[1])
        aa = aa + aa.transpose(0,1,3,2)
        aa = aa + aa.transpose(1,0,2,3)
        aa = ao2mo.restore(4, aa, nao) * .5
        bb = bb + bb.transpose(0,1,3,2)
        bb = bb + bb.transpose(1,0,2,3)
        bb = ao2mo.restore(4, bb, nao) * .5
        ab = ab + ab.transpose(0,1,3,2)
        ab = ab + ab.transpose(1,0,2,3)
        ab = ao2mo.restore(4, ab, nao) * .5
        ref = (aa+ab, bb+ab.T)
        rdm2 = uccsd_grad._rdm2_mo2ao(mycc, d2, mycc.mo_coeff)
        self.assertAlmostEqual(abs(ref[0]-rdm2[0]).max(), 0, 10)
        self.assertAlmostEqual(abs(ref[1]-rdm2[1]).max(), 0, 10)
        uccsd_grad._rdm2_mo2ao(mycc, d2, mycc.mo_coeff, fdm2)
        self.assertAlmostEqual(abs(ref[0]-fdm2['dm2aa+ab'].value).max(), 0, 10)
        self.assertAlmostEqual(abs(ref[1]-fdm2['dm2bb+ab'].value).max(), 0, 10)
        self.assertAlmostEqual(lib.finger(rdm2[0]), -1.6247203743431637, 7)
        self.assertAlmostEqual(lib.finger(rdm2[1]), -0.44062825991527471, 7)
Beispiel #15
0
def project_dm_nr2nr(mol1, dm1, mol2):
    r''' Project density matrix representation from basis set 1 (mol1) to basis
    set 2 (mol2).

    .. math::

        |AO2\rangle DM_AO2 \langle AO2|

        = |AO2\rangle P DM_AO1 P \langle AO2|

        DM_AO2 = P DM_AO1 P

        P = S_{AO2}^{-1}\langle AO2|AO1\rangle

    There are three relevant functions:
    :func:`project_dm_nr2nr` is the projection for non-relativistic (scalar) basis.
    :func:`project_dm_nr2r` projects from non-relativistic to relativistic basis.
    :func:`project_dm_r2r`  is the projection between relativistic (spinor) basis.
    '''
    s22 = mol2.intor_symmetric('int1e_ovlp')
    s21 = mole.intor_cross('int1e_ovlp', mol2, mol1)
    p21 = lib.cho_solve(s22, s21)
    if isinstance(dm1, numpy.ndarray) and dm1.ndim == 2:
        return reduce(numpy.dot, (p21, dm1, p21.conj().T))
    else:
        return lib.einsum('pi,nij,qj->npq', p21, dm1, p21.conj())
Beispiel #16
0
def get_mo_pairs_G(mydf, mo_coeffs, kpts=numpy.zeros((2,3)), q=None,
                   compact=getattr(__config__, 'pbc_df_mo_pairs_compact', False)):
    '''Calculate forward fourier transform (G|ij) of all MO pairs.

    Args:
        mo_coeff: length-2 list of (nao,nmo) ndarrays
            The two sets of MO coefficients to use in calculating the
            product |ij).

    Returns:
        mo_pairs_G : (ngrids, nmoi*nmoj) ndarray
            The FFT of the real-space MO pairs.
    '''
    if kpts is None: kpts = numpy.zeros((2,3))
    cell = mydf.cell
    kpts = numpy.asarray(kpts)
    q = kpts[1] - kpts[0]
    coords = cell.gen_uniform_grids(mydf.mesh)
    nmoi = mo_coeffs[0].shape[1]
    nmoj = mo_coeffs[1].shape[1]
    ngrids = len(coords)

    mo_pairs_G = numpy.empty((ngrids,nmoi,nmoj), dtype=numpy.complex)
    for pqkR, pqkI, p0, p1 \
            in mydf.pw_loop(mydf.mesh, kptijkl[:2], q,
                            max_memory=max_memory, aosym='s2'):
        pqk = (pqkR + pqkI*1j).reshape(nao,nao,-1)
        mo_pairs_G[p0:p1] = lib.einsum('pqk,pi,qj->kij', pqk, *mo_coeffs[:2])
    return mo_pairs_G.reshape(ngrids,nmoi*nmoj)
Beispiel #17
0
def _make_rdm1(mycc, d1, with_frozen=True, ao_repr=False):
    '''dm1[p,q] = <q_alpha^\dagger p_alpha> + <q_beta^\dagger p_beta>

    The convention of 1-pdm is based on McWeeney's book, Eq (5.4.20).
    The contraction between 1-particle Hamiltonian and rdm1 is
    E = einsum('pq,qp', h1, rdm1)
    '''
    doo, dov, dvo, dvv = d1
    nocc, nvir = dov.shape
    nmo = nocc + nvir
    dm1 = numpy.empty((nmo,nmo), dtype=doo.dtype)
    dm1[:nocc,:nocc] = doo + doo.conj().T
    dm1[:nocc,nocc:] = dov + dvo.conj().T
    dm1[nocc:,:nocc] = dm1[:nocc,nocc:].conj().T
    dm1[nocc:,nocc:] = dvv + dvv.conj().T
    dm1[numpy.diag_indices(nocc)] += 2

    if with_frozen and not (mycc.frozen is 0 or mycc.frozen is None):
        nmo = mycc.mo_occ.size
        nocc = numpy.count_nonzero(mycc.mo_occ > 0)
        rdm1 = numpy.zeros((nmo,nmo), dtype=dm1.dtype)
        rdm1[numpy.diag_indices(nocc)] = 2
        moidx = numpy.where(mycc.get_frozen_mask())[0]
        rdm1[moidx[:,None],moidx] = dm1
        dm1 = rdm1

    if ao_repr:
        mo = mycc.mo_coeff
        dm1 = lib.einsum('pi,ij,qj->pq', mo, dm1, mo.conj())
    return dm1
Beispiel #18
0
def _gamma1_intermediates(mycc, t1, t2, l1, l2):
    nocc, nvir = t1.shape
    doo =-numpy.einsum('ja,ia->ij', t1, l1)
    dvv = numpy.einsum('ia,ib->ab', t1, l1)
    xtv = numpy.einsum('ie,me->im', t1, l1)
    dvo = t1.T - numpy.einsum('im,ma->ai', xtv, t1)
    theta = t2 * 2 - t2.transpose(0,1,3,2)
    doo -= lib.einsum('jkab,ikab->ij', theta, l2)
    dvv += lib.einsum('jica,jicb->ab', theta, l2)
    xt1  = lib.einsum('mnef,inef->mi', l2, theta)
    xt2  = lib.einsum('mnaf,mnef->ea', l2, theta)
    dvo += numpy.einsum('imae,me->ai', theta, l1)
    dvo -= numpy.einsum('mi,ma->ai', xt1, t1)
    dvo -= numpy.einsum('ie,ae->ai', t1, xt2)
    dov = l1
    return doo, dov, dvo, dvv
Beispiel #19
0
def contract_2e(eri, fcivec, norb, nelec, opt=None):
    if isinstance(nelec, (int, numpy.integer)):
        nelecb = nelec//2
        neleca = nelec - nelecb
    else:
        neleca, nelecb = nelec
    link_indexa = cistring.gen_linkstr_index(range(norb), neleca)
    link_indexb = cistring.gen_linkstr_index(range(norb), nelecb)
    na = cistring.num_strings(norb, neleca)
    nb = cistring.num_strings(norb, nelecb)
    ci0 = fcivec.reshape(na,nb)
    t1 = numpy.zeros((norb,norb,na,nb))
    for str0, tab in enumerate(link_indexa):
        for a, i, str1, sign in tab:
            t1[a,i,str1] += sign * ci0[str0]
    for str0, tab in enumerate(link_indexb):
        for a, i, str1, sign in tab:
            t1[a,i,:,str1] += sign * ci0[:,str0]

    t1 = lib.einsum('bjai,aiAB->bjAB', eri.reshape([norb]*4), t1)

    fcinew = numpy.zeros_like(ci0)
    for str0, tab in enumerate(link_indexa):
        for a, i, str1, sign in tab:
            fcinew[str1] += sign * t1[a,i,str0]
    for str0, tab in enumerate(link_indexb):
        for a, i, str1, sign in tab:
            fcinew[:,str1] += sign * t1[a,i,:,str0]
    return fcinew.reshape(fcivec.shape)
Beispiel #20
0
def polarizability_with_freq(polobj, freq=None):
    from pyscf.prop.nmr import rhf as rhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = mo_occ > 0
    orbo = mo_coeff[:, occidx]
    orbv = mo_coeff[:,~occidx]

    charges = mol.atom_charges()
    coords  = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1 = lib.einsum('xpq,pi,qj->xij', int_r, orbv.conj(), orbo)
    mo1 = cphf_with_freq(mf, mo_energy, mo_occ, h1, freq,
                         polobj.max_cycle_cphf, polobj.conv_tol, verbose=log)[0]

    e2 =  numpy.einsum('xpi,ypi->xy', h1, mo1[0])
    e2 += numpy.einsum('xpi,ypi->xy', h1, mo1[1])

    # *-1 from the definition of dipole moment. *2 for double occupancy
    e2 *= -2
    log.debug('Polarizability tensor with freq %s', freq)
    log.debug('%s', e2)
    return e2
Beispiel #21
0
    def test_add_vvVV(self):
        myucc = uccsd.UCCSD(mf_s2)
        nocca, noccb = 6,4
        nmo = mf_s2.mo_occ[0].size
        nvira, nvirb = nmo-nocca, nmo-noccb
        numpy.random.seed(9)
        t1 = [numpy.zeros((nocca,nvira)),
              numpy.zeros((noccb,nvirb))]
        t2 = [numpy.random.random((nocca,nocca,nvira,nvira))-.9,
              numpy.random.random((nocca,noccb,nvira,nvirb))-.9,
              numpy.random.random((noccb,noccb,nvirb,nvirb))-.9]
        t2[0] = t2[0] - t2[0].transpose(1,0,2,3)
        t2[0] = t2[0] - t2[0].transpose(0,1,3,2)
        t2[2] = t2[2] - t2[2].transpose(1,0,2,3)
        t2[2] = t2[2] - t2[2].transpose(0,1,3,2)

        eris1 = copy.copy(eris)
        idxa = lib.square_mat_in_trilu_indices(nvira)
        idxb = lib.square_mat_in_trilu_indices(nvirb)
        vvVV = eris1.vvVV[:,idxb][idxa]
        ref = lib.einsum('acbd,ijcd->ijab', vvVV, t2[1])

        t2a = myucc._add_vvVV((t1[0]*0,t1[1]*0), t2[1], eris)
        self.assertAlmostEqual(abs(ref-t2a).max(), 0, 12)

        myucc.direct = True
        eris1.vvvv = None  # == with_ovvv=True in the call below
        eris1.VVVV = None
        eris1.vvVV = None
        t1 = None
        myucc.mo_coeff, eris1.mo_coeff = eris1.mo_coeff, None
        t2b = myucc._add_vvVV(t1, t2[1], eris1)
        self.assertAlmostEqual(abs(ref-t2b).max(), 0, 12)
Beispiel #22
0
def para(magobj, gauge_orig=None, h1=None, s1=None, with_cphf=None):
    '''Part of rotational g-tensors from the first order wavefunctions. Unit
    hbar/mu_N is not included.  This part may be different to the conventional
    para-magnetic contributions of rotational g-tensors.
    '''
    mol = magobj.mol
    im, mass_center = rhf_g.inertia_tensor(mol)

    if gauge_orig is None:
        # The first order Hamiltonian for rotation part is the same to the
        # first order Hamiltonian for magnetic field except a factor of 2. It can
        # be computed using the magnetizability code.
        mag_para = uhf_mag.para(magobj, gauge_orig, h1, s1, with_cphf) * 2

    else:
        mf = magobj._scf
        mo_energy = mf.mo_energy
        mo_coeff = mf.mo_coeff
        mo_occ = mf.mo_occ
        orboa = mo_coeff[0][:,mo_occ[0]>0]
        orbob = mo_coeff[1][:,mo_occ[1]>0]

        # for magnetic field
        with mol.with_common_origin(mass_center):
            h10 = .5 * mol.intor('int1e_cg_irxp', 3)
            h10a = lib.einsum('xpq,pi,qj->xij', h10, mo_coeff[0].conj(), orboa)
            h10b = lib.einsum('xpq,pi,qj->xij', h10, mo_coeff[1].conj(), orbob)

        # for rotation part
        with mol.with_common_origin(gauge_orig):
            h01 = -mol.intor('int1e_cg_irxp', 3)
            h01a = lib.einsum('xpq,pi,qj->xij', h01, mo_coeff[0].conj(), orboa)
            h01b = lib.einsum('xpq,pi,qj->xij', h01, mo_coeff[1].conj(), orbob)

        s10a = numpy.zeros_like(h10a)
        s10b = numpy.zeros_like(h10b)
        mo10 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ,
                                            (h10a,h10b), (s10a,s10b))[0]

        mag_para = numpy.einsum('xji,yji->xy', mo10[0].conj(), h01a)
        mag_para+= numpy.einsum('xji,yji->xy', mo10[1].conj(), h01b)
        mag_para = mag_para + mag_para.conj()

    mag_para = rhf_g._safe_solve(im, mag_para)
    # unit = hbar/mu_N, mu_N is nuclear magneton
    unit = -2 * nist.PROTON_MASS_AU
    return mag_para * unit
Beispiel #23
0
def grad_elec(mc, mf_grad):
    mf = mf_grad.base
    mol = mf_grad.mol
    mo_energy = mc.mo_energy
    mo_coeff = mc.mo_coeff

    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    nao, nmo = mo_coeff.shape

    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    casdm1, casdm2 = mc.fcisolver.make_rdm12(mc.ci, ncas, nelecas)
    dm1 = numpy.zeros((nmo,nmo))
    dm1[numpy.diag_indices(ncore)] = 2
    dm1[ncore:nocc,ncore:nocc] = casdm1

    dm2 = numpy.zeros((nmo,nmo,nmo,nmo))
    for i in range(ncore):
        for j in range(ncore):
            dm2[i,i,j,j] += 4
            dm2[i,j,j,i] -= 2
        dm2[i,i,ncore:nocc,ncore:nocc] = casdm1 * 2
        dm2[ncore:nocc,ncore:nocc,i,i] = casdm1 * 2
        dm2[i,ncore:nocc,ncore:nocc,i] =-casdm1
        dm2[ncore:nocc,i,i,ncore:nocc] =-casdm1
    dm2[ncore:nocc,ncore:nocc,ncore:nocc,ncore:nocc] = casdm2

    h1 = reduce(numpy.dot, (mo_coeff.T, mc._scf.get_hcore(), mo_coeff))
    h2 = ao2mo.kernel(mf._eri, mo_coeff, compact=False).reshape([nmo]*4)

# Generalized Fock, according to generalized Brillouin theorm
# Adv. Chem. Phys., 69, 63
    gfock = numpy.dot(h1, dm1)
    gfock+= numpy.einsum('iqrs,qjsr->ij', h2, dm2)
    gfock = (gfock + gfock.T) * .5
    dme0 = reduce(numpy.dot, (mo_coeff[:,:nocc], gfock[:nocc,:nocc], mo_coeff[:,:nocc].T))

    dm1 = reduce(numpy.dot, (mo_coeff, dm1, mo_coeff.T))
    dm2 = lib.einsum('ijkl,pi,qj,rk,sl->pqrs', dm2,
                     mo_coeff, mo_coeff, mo_coeff, mo_coeff)

    eri_deriv1 = mol.intor('int2e_ip1', comp=3).reshape(3,nao,nao,nao,nao)

    atmlst = range(mol.natm)
    aoslices = mol.aoslice_by_atom()
    de = numpy.zeros((len(atmlst),3))

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        h1ao = hcore_deriv(ia)
        de[k] += numpy.einsum('xij,ij->x', h1ao, dm1)
        de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], dme0[p0:p1]) * 2
        de[k] -= numpy.einsum('xijkl,ijkl->x', eri_deriv1[:,p0:p1], dm2[p0:p1]) * 2

    return de
Beispiel #24
0
def polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import uhf as uhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    mo0a, mo0b = mo_coeff
    orboa = mo0a[:, occidxa]
    orbva = mo0a[:,~occidxa]
    orbob = mo0b[:, occidxb]
    orbvb = mo0b[:,~occidxb]

    charges = mol.atom_charges()
    coords  = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa)
    h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob)
    s1a = numpy.zeros_like(h1a)
    s1b = numpy.zeros_like(h1b)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), (s1a,s1b),
                          polobj.max_cycle_cphf, polobj.conv_tol,
                          verbose=log)[0]
    else:
        mo1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a,h1b),
                                           (s1a,s1b))[0]

    e2 = numpy.einsum('xpi,ypi->xy', h1a, mo1[0])
    e2+= numpy.einsum('xpi,ypi->xy', h1b, mo1[1])
    e2 = -(e2 + e2.T)

    if mf.verbose >= logger.INFO:
        xx, yy, zz = e2.diagonal()
        log.note('Isotropic polarizability %.12g', (xx+yy+zz)/3)
        log.note('Polarizability anisotropy %.12g',
                 (.5 * ((xx-yy)**2 + (yy-zz)**2 + (zz-xx)**2))**.5)
        log.debug('Static polarizability tensor\n%s', e2)
    return e2
Beispiel #25
0
def solve_mo1(nmrobj, mo_energy=None, mo_coeff=None, mo_occ=None,
              h1=None, s1=None, with_cphf=None):
    '''Solve the first order equation

    Kwargs:
        with_cphf : boolean or  function(dm_mo) => v1_mo
            If a boolean value is given, the value determines whether CPHF
            equation will be solved or not. The induced potential will be
            generated by the function gen_vind.
            If a function is given, CPHF equation will be solved, and the
            given function is used to compute induced potential
    '''
    cput1 = (time.clock(), time.time())
    log = logger.Logger(nmrobj.stdout, nmrobj.verbose)
    if mo_energy is None: mo_energy = nmrobj._scf.mo_energy
    if mo_coeff  is None: mo_coeff = nmrobj._scf.mo_coeff
    if mo_occ    is None: mo_occ = nmrobj._scf.mo_occ
    if with_cphf is None: with_cphf = nmrobj.cphf

    mol = nmrobj.mol
    orboa = mo_coeff[0][:,mo_occ[0]>0]
    orbob = mo_coeff[1][:,mo_occ[1]>0]
    if h1 is None:
        dm0 = nmrobj._scf.make_rdm1(mo_coeff, mo_occ)
        h1 = nmrobj.get_fock(dm0)
        h1 = (lib.einsum('xpq,pi,qj->xij', h1[0], mo_coeff[0].conj(), orboa),
              lib.einsum('xpq,pi,qj->xij', h1[1], mo_coeff[1].conj(), orbob))
        cput1 = log.timer('first order Fock matrix', *cput1)
    if s1 is None:
        s1 = nmrobj.get_ovlp(mol)
        s1 = (lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[0].conj(), orboa),
              lib.einsum('xpq,pi,qj->xij', s1, mo_coeff[1].conj(), orbob))

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(nmrobj._scf, mo_coeff, mo_occ)
        mo10, mo_e10 = ucphf.solve(vind, mo_energy, mo_occ, h1, s1,
                                   nmrobj.max_cycle_cphf, nmrobj.conv_tol,
                                   verbose=log)
    else:
        mo10, mo_e10 = _solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)

    logger.timer(nmrobj, 'solving mo1 eqn', *cput1)
    return mo10, mo_e10
Beispiel #26
0
def Woooo(t1, t2, eris):
    t1a, t1b = t1
    t2aa, t2ab, t2bb = t2
    eris_ovoo = np.asarray(eris.ovoo)
    eris_OVOO = np.asarray(eris.OVOO)
    eris_OVoo = np.asarray(eris.OVoo)
    eris_ovOO = np.asarray(eris.ovOO)
    ovoo = eris_ovoo - eris_ovoo.transpose(2,1,0,3)
    OVOO = eris_OVOO - eris_OVOO.transpose(2,1,0,3)
    woooo = lib.einsum('je,nemi->minj', t1a,      ovoo)
    wOOOO = lib.einsum('je,nemi->minj', t1b,      OVOO)
    wooOO = lib.einsum('JE,NEmi->miNJ', t1b, eris_OVoo)
    woOOo = lib.einsum('je,meNI->mINj',-t1a, eris_ovOO)

    woooo += np.asarray(eris.oooo)
    wOOOO += np.asarray(eris.OOOO)
    wooOO += np.asarray(eris.ooOO)
    woooo = woooo - woooo.transpose(0,3,2,1)
    wOOOO = wOOOO - wOOOO.transpose(0,3,2,1)
    wooOO = wooOO - woOOo.transpose(0,3,2,1)

    eris_ovov = np.asarray(eris.ovov)
    eris_OVOV = np.asarray(eris.OVOV)
    eris_ovOV = np.asarray(eris.ovOV)
    ovov = eris_ovov - eris_ovov.transpose(0,3,2,1)
    OVOV = eris_OVOV - eris_OVOV.transpose(0,3,2,1)
    tauaa, tauab, taubb = make_tau(t2, t1, t1)
    woooo += 0.5*lib.einsum('ijef,menf->minj', tauaa,      ovov)
    wOOOO += 0.5*lib.einsum('ijef,menf->minj', taubb,      OVOV)
    wooOO +=     lib.einsum('iJeF,meNF->miNJ', tauab, eris_ovOV)
    wOOoo = None
    return woooo, wooOO, wOOoo, wOOOO
Beispiel #27
0
def e(*args):
    """Numpy optimized einsum."""
    for i in args:
        if isinstance(i, Number) and i == 0:
            return 0
    try:
        return numpy.einsum(*args, optimize=True)
    except TypeError:
        return lib.einsum(*args)
Beispiel #28
0
def _gamma1_intermediates(mp, t2):
    t2aa, t2ab, t2bb = t2
    dooa  = lib.einsum('imef,jmef->ij', t2aa.conj(), t2aa) *-.5
    dooa -= lib.einsum('imef,jmef->ij', t2ab.conj(), t2ab)
    doob  = lib.einsum('imef,jmef->ij', t2bb.conj(), t2bb) *-.5
    doob -= lib.einsum('mief,mjef->ij', t2ab.conj(), t2ab)

    dvva  = lib.einsum('mnae,mnbe->ba', t2aa.conj(), t2aa) * .5
    dvva += lib.einsum('mnae,mnbe->ba', t2ab.conj(), t2ab)
    dvvb  = lib.einsum('mnae,mnbe->ba', t2bb.conj(), t2bb) * .5
    dvvb += lib.einsum('mnea,mneb->ba', t2ab.conj(), t2ab)
    return ((dooa, doob), (dvva, dvvb))
Beispiel #29
0
def make_h1_fcsd(mol, mo_coeff, mo_occ, atmlst):
    '''FC + SD'''
    orboa = mo_coeff[0][:,mo_occ[0]> 0]
    orbva = mo_coeff[0][:,mo_occ[0]==0]
    orbob = mo_coeff[1][:,mo_occ[1]> 0]
    orbvb = mo_coeff[1][:,mo_occ[1]==0]
    nao = mo_coeff[0].shape[0]
    h1aa = []
    h1ab = []
    h1ba = []
    h1bb = []
    for ia in atmlst:
        h1ao = rhf_ssc._get_integrals_fcsd(mol, ia)
        # *.5 due to s = 1/2 * pauli-matrix
        h1aa.append(lib.einsum('xypq,pi,qj->xyij', h1ao, orbva.conj(), orboa) * .5)
        h1ab.append(lib.einsum('xypq,pi,qj->xyij', h1ao, orbva.conj(), orbob) * .5)
        h1ba.append(lib.einsum('xypq,pi,qj->xyij', h1ao, orbvb.conj(), orboa) * .5)
        h1bb.append(lib.einsum('xypq,pi,qj->xyij', h1ao, orbvb.conj(), orbob) *-.5)
    return (lib.asarray(h1aa), lib.asarray(h1ab),
            lib.asarray(h1ba), lib.asarray(h1bb))
Beispiel #30
0
    def test_ao2mo_r_e2(self):
        n2c = mol.nao_2c()
        numpy.random.seed(1)
        mo = numpy.random.random((n2c,n2c)) + numpy.random.random((n2c,n2c))*1j
        tao = numpy.asarray(mol.tmap(), dtype=numpy.int32)
        buf = ao2mo._ao2mo.r_e1('int2e_spinor', mo, (0,4,0,3), (0, 2, 8),
                                mol._atm, mol._bas, mol._env, tao, 's1')
        buf = buf.reshape(8,12).T
        ref = lib.einsum('pqkl,pi,qj->ijkl', eri0, mo[:,:4].conj(), mo[:,:3])
        self.assertAlmostEqual(lib.finger(buf), 0.30769732102451997-0.58664393190628461j, 8)
        self.assertAlmostEqual(abs(buf[:,:4]-ref[:,:,:2,:2].reshape(12,4)).max(), 0, 9)
        self.assertAlmostEqual(abs(buf[:,4:]-ref[:,:,:2,2:4].reshape(12,4)).max(), 0, 9)

        buf = ao2mo._ao2mo.r_e2(eri0.reshape(n2c**2,n2c,n2c), mo, (0,2,0,4), tao, None, 's1')
        ref = lib.einsum('xpq,pk,ql->xkl', eri0.reshape(n2c**2,n2c,n2c),
                         mo[:,:2].conj(), mo[:,:4])
        self.assertAlmostEqual(lib.finger(buf), 14.183520455200011+10.179224253811057j, 8)
        self.assertAlmostEqual(abs(buf.reshape(n2c**2,2,4)-ref).max(), 0, 9)

        buf = ao2mo._ao2mo.r_e2(eri0.reshape(n2c**2,n2c,n2c), mo, (0,0,4,4), tao, None, 's1')
        self.assertEqual(buf.size, 0)
Beispiel #31
0
def dia(magobj, gauge_orig=None):
    mol = magobj.mol
    mf = magobj._scf
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    orbo = mo_coeff[:, mo_occ > 0]
    dm0 = numpy.dot(orbo, orbo.T) * 2
    dm0 = lib.tag_array(dm0, mo_coeff=mo_coeff, mo_occ=mo_occ)
    dme0 = numpy.dot(orbo * mo_energy[mo_occ > 0], orbo.T) * 2

    e2 = rhf_mag._get_dia_1e(magobj, gauge_orig, dm0, dme0)

    if gauge_orig is not None:
        return -e2

    # Computing the 2nd order Vxc integrals from GIAO
    grids = mf.grids
    ni = mf._numint
    xc_code = mf.xc
    xctype = ni._xc_type(xc_code)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(xc_code, mol.spin)

    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dm0, hermi=1)
    ngrids = len(grids.weights)
    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .9 - mem_now)
    BLKSIZE = numint.BLKSIZE
    blksize = min(
        int(max_memory / 12 * 1e6 / 8 / nao / BLKSIZE) * BLKSIZE, ngrids)

    vmat = numpy.zeros((3, 3, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 0
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory,
                                 blksize=blksize):
            rho = make_rho(0, ao, mask, 'LDA')
            vxc = ni.eval_xc(xc_code, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            r_ao = numpy.einsum('pi,px->pxi', ao, coords)
            aow = numpy.einsum('pxi,p,p->pxi', r_ao, weight, vrho)
            vmat += lib.einsum('pxi,pyj->xyij', r_ao, aow)
            rho = vxc = vrho = aow = None

    elif xctype == 'GGA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory,
                                 blksize=blksize):
            rho = make_rho(0, ao, mask, 'GGA')
            vxc = ni.eval_xc(xc_code, rho, 0, deriv=1)[1]
            wv = numint._rks_gga_wv0(rho, vxc, weight)

            # Computing \nabla (r * AO) = r * \nabla AO + [\nabla,r]_- * AO
            r_ao = numpy.einsum('npi,px->npxi', ao, coords)
            r_ao[1, :, 0] += ao[0]
            r_ao[2, :, 1] += ao[0]
            r_ao[3, :, 2] += ao[0]

            aow = numpy.einsum('npxi,np->pxi', r_ao, wv)
            vmat += lib.einsum('pxi,pyj->xyij', r_ao[0], aow)
            rho = vxc = vrho = vsigma = wv = aow = None

        vmat = vmat + vmat.transpose(0, 1, 3, 2)

    elif xctype == 'MGGA':
        raise NotImplementedError('meta-GGA')

    vmat = _add_giao_phase(mol, vmat)
    e2 += numpy.einsum('qp,xypq->xy', dm0, vmat)
    vmat = None

    e2 = e2.ravel()
    # Handle the hybrid functional and the range-separated functional
    if abs(hyb) > 1e-10:
        vs = jk.get_jk(mol, [dm0] * 3,
                       ['ijkl,ji->s2kl', 'ijkl,jk->s1il', 'ijkl,li->s1kj'],
                       'int2e_gg1',
                       's4',
                       9,
                       hermi=1)
        e2 += numpy.einsum('xpq,qp->x', vs[0], dm0)
        e2 -= numpy.einsum('xpq,qp->x', vs[1], dm0) * .25 * hyb
        e2 -= numpy.einsum('xpq,qp->x', vs[2], dm0) * .25 * hyb
        vk = jk.get_jk(mol,
                       dm0,
                       'ijkl,jk->s1il',
                       'int2e_g1g2',
                       'aa4',
                       9,
                       hermi=0)
        e2 -= numpy.einsum('xpq,qp->x', vk, dm0) * .5 * hyb

        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vs = jk.get_jk(mol, [dm0] * 2,
                               ['ijkl,jk->s1il', 'ijkl,li->s1kj'],
                               'int2e_gg1',
                               's4',
                               9,
                               hermi=1)
                e2 -= numpy.einsum('xpq,qp->x', vs[0],
                                   dm0) * .25 * (alpha - hyb)
                e2 -= numpy.einsum('xpq,qp->x', vs[1],
                                   dm0) * .25 * (alpha - hyb)
                vk = jk.get_jk(mol,
                               dm0,
                               'ijkl,jk->s1il',
                               'int2e_g1g2',
                               'aa4',
                               9,
                               hermi=0)
                e2 -= numpy.einsum('xpq,qp->x', vk, dm0) * .5 * (alpha - hyb)

    else:
        vj = jk.get_jk(mol,
                       dm0,
                       'ijkl,ji->s2kl',
                       'int2e_gg1',
                       's4',
                       9,
                       hermi=1)
        e2 += numpy.einsum('xpq,qp->x', vj, dm0)

    return -e2.reshape(3, 3)
Beispiel #32
0
def overlap(cibra, ciket, nmo, nocc, s=None):
    '''Overlap between two CISD wavefunctions.

    Args:
        s : 2D array
            The overlap matrix of non-orthogonal one-particle basis
    '''
    if s is None:
        return dot(cibra, ciket, nmo, nocc)

    DEBUG = True

    nvir = nmo - nocc
    nov = nocc * nvir
    bra0, bra1, bra2 = cisdvec_to_amplitudes(cibra, nmo, nocc)
    ket0, ket1, ket2 = cisdvec_to_amplitudes(ciket, nmo, nocc)

    # Sort the ket orbitals to make the orbitals in bra one-one mapt to orbitals
    # in ket.
    if ((not DEBUG) and abs(numpy.linalg.det(s[:nocc, :nocc]) - 1) < 1e-2
            and abs(numpy.linalg.det(s[nocc:, nocc:]) - 1) < 1e-2):
        ket_orb_idx = numpy.where(abs(s) > 0.9)[1]
        s = s[:, ket_orb_idx]
        oidx = ket_orb_idx[:nocc]
        vidx = ket_orb_idx[nocc:] - nocc
        ket1 = ket1[oidx[:, None], vidx]
        ket2 = ket2[oidx[:, None, None, None], oidx[:, None, None],
                    vidx[:, None], vidx]

    ooidx = numpy.tril_indices(nocc, -1)
    vvidx = numpy.tril_indices(nvir, -1)
    bra2aa = bra2 - bra2.transpose(1, 0, 2, 3)
    bra2aa = lib.take_2d(bra2aa.reshape(nocc**2,
                                        nvir**2), ooidx[0] * nocc + ooidx[1],
                         vvidx[0] * nvir + vvidx[1])
    ket2aa = ket2 - ket2.transpose(1, 0, 2, 3)
    ket2aa = lib.take_2d(ket2aa.reshape(nocc**2,
                                        nvir**2), ooidx[0] * nocc + ooidx[1],
                         vvidx[0] * nvir + vvidx[1])

    occlist0 = numpy.arange(nocc).reshape(1, nocc)
    occlists = numpy.repeat(occlist0, 1 + nov + bra2aa.size, axis=0)
    occlist0 = occlists[:1]
    occlist1 = occlists[1:1 + nov]
    occlist2 = occlists[1 + nov:]

    ia = 0
    for i in range(nocc):
        for a in range(nocc, nmo):
            occlist1[ia, i] = a
            ia += 1

    ia = 0
    for i in range(nocc):
        for j in range(i):
            for a in range(nocc, nmo):
                for b in range(nocc, a):
                    occlist2[ia, i] = a
                    occlist2[ia, j] = b
                    ia += 1

    na = len(occlists)
    if DEBUG:
        trans = numpy.empty((na, na))
        for i, idx in enumerate(occlists):
            s_sub = s[idx].T.copy()
            minors = s_sub[occlists]
            trans[i, :] = numpy.linalg.det(minors)

        # Mimic the transformation einsum('ab,ap->pb', FCI, trans).
        # The wavefunction FCI has the [excitation_alpha,excitation_beta]
        # representation.  The zero blocks like FCI[S_alpha,D_beta],
        # FCI[D_alpha,D_beta], are explicitly excluded.
        bra_mat = numpy.zeros((na, na))
        bra_mat[0, 0] = bra0
        bra_mat[0, 1:1 + nov] = bra_mat[1:1 + nov, 0] = bra1.ravel()
        bra_mat[0, 1 + nov:] = bra_mat[1 + nov:, 0] = bra2aa.ravel()
        bra_mat[1:1 + nov, 1:1 + nov] = bra2.transpose(0, 2, 1,
                                                       3).reshape(nov, nov)
        ket_mat = numpy.zeros((na, na))
        ket_mat[0, 0] = ket0
        ket_mat[0, 1:1 + nov] = ket_mat[1:1 + nov, 0] = ket1.ravel()
        ket_mat[0, 1 + nov:] = ket_mat[1 + nov:, 0] = ket2aa.ravel()
        ket_mat[1:1 + nov, 1:1 + nov] = ket2.transpose(0, 2, 1,
                                                       3).reshape(nov, nov)
        ovlp = lib.einsum('ab,ap,bq,pq->', bra_mat, trans, trans, ket_mat)

    else:
        nov1 = 1 + nov
        noovv = bra2aa.size
        bra_SS = numpy.zeros((nov1, nov1))
        bra_SS[0, 0] = bra0
        bra_SS[0, 1:] = bra_SS[1:, 0] = bra1.ravel()
        bra_SS[1:, 1:] = bra2.transpose(0, 2, 1, 3).reshape(nov, nov)
        ket_SS = numpy.zeros((nov1, nov1))
        ket_SS[0, 0] = ket0
        ket_SS[0, 1:] = ket_SS[1:, 0] = ket1.ravel()
        ket_SS[1:, 1:] = ket2.transpose(0, 2, 1, 3).reshape(nov, nov)

        trans_SS = numpy.empty((nov1, nov1))
        trans_SD = numpy.empty((nov1, noovv))
        trans_DS = numpy.empty((noovv, nov1))
        occlist01 = occlists[:nov1]
        for i, idx in enumerate(occlist01):
            s_sub = s[idx].T.copy()
            minors = s_sub[occlist01]
            trans_SS[i, :] = numpy.linalg.det(minors)

            minors = s_sub[occlist2]
            trans_SD[i, :] = numpy.linalg.det(minors)

            s_sub = s[:, idx].copy()
            minors = s_sub[occlist2]
            trans_DS[:, i] = numpy.linalg.det(minors)

        ovlp = lib.einsum('ab,ap,bq,pq->', bra_SS, trans_SS, trans_SS, ket_SS)
        ovlp += lib.einsum('ab,a ,bq, q->', bra_SS, trans_SS[:, 0], trans_SD,
                           ket2aa.ravel())
        ovlp += lib.einsum('ab,ap,b ,p ->', bra_SS, trans_SD, trans_SS[:, 0],
                           ket2aa.ravel())

        ovlp += lib.einsum(' b, p,bq,pq->', bra2aa.ravel(), trans_SS[0, :],
                           trans_DS, ket_SS)
        ovlp += lib.einsum(' b, p,b ,p ->', bra2aa.ravel(), trans_SD[0, :],
                           trans_DS[:, 0], ket2aa.ravel())

        ovlp += lib.einsum('a ,ap, q,pq->', bra2aa.ravel(), trans_DS,
                           trans_SS[0, :], ket_SS)
        ovlp += lib.einsum('a ,a , q, q->', bra2aa.ravel(), trans_DS[:, 0],
                           trans_SD[0, :], ket2aa.ravel())

        # FIXME: whether to approximate the overlap between double excitation coefficients
        if numpy.linalg.norm(bra2aa) * numpy.linalg.norm(ket2aa) < 1e-4:
            # Skip the overlap if coefficients of double excitation are small enough
            pass
        if (abs(numpy.linalg.det(s[:nocc, :nocc]) - 1) < 1e-2
                and abs(numpy.linalg.det(s[nocc:, nocc:]) - 1) < 1e-2):
            # If the overlap matrix close to identity enough, use the <D|D'> overlap
            # for orthogonal single-particle basis to approximate the overlap
            # for non-orthogonal basis.
            ovlp += numpy.dot(bra2aa.ravel(), ket2aa.ravel()) * trans_SS[0,
                                                                         0] * 2
        else:
            from multiprocessing import sharedctypes, Process
            buf_ctypes = sharedctypes.RawArray('d', noovv)
            trans_ket = numpy.ndarray(noovv, buffer=buf_ctypes)

            def trans_dot_ket(i0, i1):
                for i in range(i0, i1):
                    s_sub = s[occlist2[i]].T.copy()
                    minors = s_sub[occlist2]
                    trans_ket[i] = numpy.linalg.det(minors).dot(ket2aa.ravel())

            nproc = lib.num_threads()
            if nproc > 1:
                seg = (noovv + nproc - 1) // nproc
                ps = []
                for i0, i1 in lib.prange(0, noovv, seg):
                    p = Process(target=trans_dot_ket, args=(i0, i1))
                    ps.append(p)
                    p.start()
                [p.join() for p in ps]
            else:
                trans_dot_ket(0, noovv)

            ovlp += numpy.dot(bra2aa.ravel(), trans_ket) * trans_SS[0, 0] * 2

    return ovlp
Beispiel #33
0
def get_fno(mp, mo_energy=None, mo_coeff=None, eris=None, thresh_vir=THRESH_VIR, 
            verbose=logger.NOTE):

    lib.logger.info(mp,"\n* Fno procedure")
    lib.logger.info(mp,"* Threshold for virtual occupation %g", thresh_vir)

    if mo_energy is None:
        mo_energy = mp.mo_energy[mp.get_frozen_mask()]
    else:
        mo_energy = mo_energy[mp.get_frozen_mask()]

    if eris is None: eris = mp.ao2mo(mo_coeff)

    nocc = mp.nocc
    nvir = mp.nmo - nocc
    eo = mo_energy[:nocc] 
    ev = mo_energy[nocc:]

    dab = numpy.zeros((len(ev),len(ev)), dtype=numpy.complex128)
    vv_denom = -ev.reshape(-1,1)-ev
    for i in range(nocc):
        eps_i = eo[i]
        i_Qv = eris.ov[:, i, :].copy()
        for j in range(nocc):
            eps_j = eo[j]
            j_Qv = eris.ov[:, j, :].copy()
            viajb = lib.einsum('Qa,Qb->ab', i_Qv, j_Qv)
            vibja = lib.einsum('Qb,Qa->ab', i_Qv, j_Qv)
            v = viajb - vibja
            div = 1.0/(eps_i + eps_j + vv_denom)
            t2ij = v.conj()*div
            dab += lib.einsum('ea,eb->ab', t2ij,t2ij.conj())*0.5

    dm1 = dab + dab.conj().T
    dm1 *= 0.5

    natoccvir, natorbvir = numpy.linalg.eigh(-dm1)
    for i, k in enumerate(numpy.argmax(abs(natorbvir), axis=0)):
        if natorbvir[k,i] < 0:
            natorbvir[:,i] *= -1
    natoccvir = -natoccvir
    lib.logger.debug(mp,"* Occupancies")
    lib.logger.debug(mp,"* %s" % natoccvir)
    lib.logger.debug(mp,"* The sum is %8.6f" % numpy.sum(natoccvir)) 
    active = (thresh_vir <= natoccvir)
    lib.logger.info(mp,"* Natural Orbital selection")
    for i in range(nvir):
        lib.logger.debug(mp,"orb: %d %s %8.6f" % (i,active[i],natoccvir[i]))
        actIndices = numpy.where(active)[0]
    lib.logger.info(mp,"* Original active orbitals %d" % nvir)
    lib.logger.info(mp,"* Virtual core orbitals: %d" % (nvir-len(actIndices)))
    lib.logger.info(mp,"* New active orbitals %d" % len(actIndices))
    lib.logger.debug(mp,"* Active orbital indices %s" % actIndices)
    natorbvir = natorbvir[:,actIndices]                                    
    ev = mo_energy[nocc:]
    fvv = numpy.diag(ev)
    fvv = reduce(numpy.dot, (natorbvir.conj().T, fvv, natorbvir))
    ev, fnov = numpy.linalg.eigh(fvv)
    cv = mp.mo_coeff[:,mp.get_frozen_mask()]
    cv = cv[:,nocc:]
    cv = reduce(numpy.dot, (cv, natorbvir, fnov))
    co = mp.mo_coeff[:,mp.mo_occ>0]
    eo = mp.mo_energy[mp.mo_occ>0]
    coeff = numpy.hstack([co,cv])
    energy = numpy.hstack([eo,ev]) 
    occ = numpy.zeros(coeff.shape[1])
    for i in range(mp.mol.nelectron):
        occ[i] = 1.0
    return coeff, energy, occ
Beispiel #34
0
def grad_elec(cc_grad, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None,
              d1=None, d2=None, verbose=logger.INFO):
    mycc = cc_grad.base
    if eris is not None:
        if (abs(eris.focka - numpy.diag(eris.focka.diagonal())).max() > 1e-3 or
            abs(eris.fockb - numpy.diag(eris.fockb.diagonal())).max() > 1e-3):
            raise RuntimeError('UCCSD gradients does not support NHF (non-canonical HF)')

    if t1 is None: t1 = mycc.t1
    if t2 is None: t2 = mycc.t2
    if l1 is None: l1 = mycc.l1
    if l2 is None: l2 = mycc.l2

    log = logger.new_logger(mycc, verbose)
    time0 = logger.process_clock(), logger.perf_counter()

    log.debug('Build uccsd rdm1 intermediates')
    if d1 is None:
        d1 = uccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2)
    time1 = log.timer_debug1('rdm1 intermediates', *time0)
    log.debug('Build uccsd rdm2 intermediates')
    fdm2 = lib.H5TmpFile()
    if d2 is None:
        d2 = uccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True)
    time1 = log.timer_debug1('rdm2 intermediates', *time1)

    mol = cc_grad.mol
    mo_a, mo_b = mycc.mo_coeff
    mo_ea, mo_eb = mycc._scf.mo_energy
    nao, nmoa = mo_a.shape
    nmob = mo_b.shape[1]
    nocca = numpy.count_nonzero(mycc.mo_occ[0] > 0)
    noccb = numpy.count_nonzero(mycc.mo_occ[1] > 0)
    with_frozen = not ((mycc.frozen is None)
                       or (isinstance(mycc.frozen, (int, numpy.integer)) and mycc.frozen == 0)
                       or (len(mycc.frozen) == 0))
    moidx = mycc.get_frozen_mask()
    OA_a, VA_a, OF_a, VF_a = ccsd_grad._index_frozen_active(moidx[0], mycc.mo_occ[0])
    OA_b, VA_b, OF_b, VF_b = ccsd_grad._index_frozen_active(moidx[1], mycc.mo_occ[1])

    log.debug('symmetrized rdm2 and MO->AO transformation')
# Roughly, dm2*2 is computed in _rdm2_mo2ao
    mo_active = (mo_a[:,numpy.hstack((OA_a,VA_a))],
                 mo_b[:,numpy.hstack((OA_b,VA_b))])
    _rdm2_mo2ao(mycc, d2, mo_active, fdm2)  # transform the active orbitals
    time1 = log.timer_debug1('MO->AO transformation', *time1)
    hf_dm1a, hf_dm1b = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ)
    hf_dm1 = hf_dm1a + hf_dm1b

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    diagidx = numpy.arange(nao)
    diagidx = diagidx*(diagidx+1)//2 + diagidx
    de = numpy.zeros((len(atmlst),3))
    Imata = numpy.zeros((nao,nao))
    Imatb = numpy.zeros((nao,nao))
    vhf1 = fdm2.create_dataset('vhf1', (len(atmlst),2,3,nao,nao), 'f8')

# 2e AO integrals dot 2pdm
    max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
    blksize = max(1, int(max_memory*.9e6/8/(nao**3*2.5)))

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]
        ip1 = p0
        vhf = numpy.zeros((2,3,nao,nao))
        for b0, b1, nf in ccsd_grad._shell_prange(mol, shl0, shl1, blksize):
            ip0, ip1 = ip1, ip1 + nf
            dm2bufa = ccsd_grad._load_block_tril(fdm2['dm2aa+ab'], ip0, ip1, nao)
            dm2bufb = ccsd_grad._load_block_tril(fdm2['dm2bb+ab'], ip0, ip1, nao)
            dm2bufa[:,:,diagidx] *= .5
            dm2bufb[:,:,diagidx] *= .5
            shls_slice = (b0,b1,0,mol.nbas,0,mol.nbas,0,mol.nbas)
            eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice)
            Imata += lib.einsum('ipx,iqx->pq', eri0.reshape(nf,nao,-1), dm2bufa)
            Imatb += lib.einsum('ipx,iqx->pq', eri0.reshape(nf,nao,-1), dm2bufb)
            eri0 = None

            eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl',
                             shls_slice=shls_slice).reshape(3,nf,nao,-1)
            de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2bufa) * 2
            de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2bufb) * 2
            dm2bufa = dm2bufb = None
# HF part
            for i in range(3):
                eri1tmp = lib.unpack_tril(eri1[i].reshape(nf*nao,-1))
                eri1tmp = eri1tmp.reshape(nf,nao,nao,nao)
                vhf[:,i] += numpy.einsum('ijkl,ij->kl', eri1tmp, hf_dm1[ip0:ip1])
                vhf[0,i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1a[ip0:ip1])
                vhf[1,i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1b[ip0:ip1])
                vhf[:,i,ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1)
                vhf[0,i,ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1a)
                vhf[1,i,ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1b)
            eri1 = eri1tmp = None
        vhf1[k] = vhf
        log.debug('2e-part grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k])
        time1 = log.timer_debug1('2e-part grad of atom %d'%ia, *time1)

    s0 = mycc._scf.get_ovlp()
    Imata = reduce(numpy.dot, (mo_a.T, Imata, s0, mo_a)) * -1
    Imatb = reduce(numpy.dot, (mo_b.T, Imatb, s0, mo_b)) * -1

    dm1a = numpy.zeros((nmoa,nmoa))
    dm1b = numpy.zeros((nmob,nmob))
    doo, dOO = d1[0]
    dov, dOV = d1[1]
    dvo, dVO = d1[2]
    dvv, dVV = d1[3]
    if with_frozen:
        dco = Imata[OF_a[:,None],OA_a] / (mo_ea[OF_a,None] - mo_ea[OA_a])
        dfv = Imata[VF_a[:,None],VA_a] / (mo_ea[VF_a,None] - mo_ea[VA_a])
        dm1a[OA_a[:,None],OA_a] = (doo + doo.T) * .5
        dm1a[OF_a[:,None],OA_a] = dco
        dm1a[OA_a[:,None],OF_a] = dco.T
        dm1a[VA_a[:,None],VA_a] = (dvv + dvv.T) * .5
        dm1a[VF_a[:,None],VA_a] = dfv
        dm1a[VA_a[:,None],VF_a] = dfv.T
        dco = Imatb[OF_b[:,None],OA_b] / (mo_eb[OF_b,None] - mo_eb[OA_b])
        dfv = Imatb[VF_b[:,None],VA_b] / (mo_eb[VF_b,None] - mo_eb[VA_b])
        dm1b[OA_b[:,None],OA_b] = (dOO + dOO.T) * .5
        dm1b[OF_b[:,None],OA_b] = dco
        dm1b[OA_b[:,None],OF_b] = dco.T
        dm1b[VA_b[:,None],VA_b] = (dVV + dVV.T) * .5
        dm1b[VF_b[:,None],VA_b] = dfv
        dm1b[VA_b[:,None],VF_b] = dfv.T
    else:
        dm1a[:nocca,:nocca] = (doo + doo.T) * .5
        dm1a[nocca:,nocca:] = (dvv + dvv.T) * .5
        dm1b[:noccb,:noccb] = (dOO + dOO.T) * .5
        dm1b[noccb:,noccb:] = (dVV + dVV.T) * .5

    dm1 = (reduce(numpy.dot, (mo_a, dm1a, mo_a.T)),
           reduce(numpy.dot, (mo_b, dm1b, mo_b.T)))
    vhf = mycc._scf.get_veff(mycc.mol, dm1)
    Xvo = reduce(numpy.dot, (mo_a[:,nocca:].T, vhf[0], mo_a[:,:nocca]))
    XVO = reduce(numpy.dot, (mo_b[:,noccb:].T, vhf[1], mo_b[:,:noccb]))
    Xvo+= Imata[:nocca,nocca:].T - Imata[nocca:,:nocca]
    XVO+= Imatb[:noccb,noccb:].T - Imatb[noccb:,:noccb]

    dm1_resp = _response_dm1(mycc, (Xvo,XVO), eris)
    dm1a += dm1_resp[0]
    dm1b += dm1_resp[1]
    time1 = log.timer_debug1('response_rdm1 intermediates', *time1)

    Imata[nocca:,:nocca] = Imata[:nocca,nocca:].T
    Imatb[noccb:,:noccb] = Imatb[:noccb,noccb:].T
    im1 = reduce(numpy.dot, (mo_a, Imata, mo_a.T))
    im1+= reduce(numpy.dot, (mo_b, Imatb, mo_b.T))
    time1 = log.timer_debug1('response_rdm1', *time1)

    log.debug('h1 and JK1')
    # Initialize hcore_deriv with the underlying SCF object because some
    # extensions (e.g. QM/MM, solvent) modifies the SCF object only.
    mf_grad = cc_grad.base._scf.nuc_grad_method()
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    zeta = (mo_ea[:,None] + mo_ea) * .5
    zeta[nocca:,:nocca] = mo_ea[:nocca]
    zeta[:nocca,nocca:] = mo_ea[:nocca].reshape(-1,1)
    zeta_a = reduce(numpy.dot, (mo_a, zeta*dm1a, mo_a.T))
    zeta = (mo_eb[:,None] + mo_eb) * .5
    zeta[noccb:,:noccb] = mo_eb[:noccb]
    zeta[:noccb,noccb:] = mo_eb[:noccb].reshape(-1,1)
    zeta_b = reduce(numpy.dot, (mo_b, zeta*dm1b, mo_b.T))

    dm1 = (reduce(numpy.dot, (mo_a, dm1a, mo_a.T)),
           reduce(numpy.dot, (mo_b, dm1b, mo_b.T)))
    vhf_s1occ = mycc._scf.get_veff(mol, (dm1[0]+dm1[0].T, dm1[1]+dm1[1].T))
    p1a = numpy.dot(mo_a[:,:nocca], mo_a[:,:nocca].T)
    p1b = numpy.dot(mo_b[:,:noccb], mo_b[:,:noccb].T)
    vhf_s1occ = (reduce(numpy.dot, (p1a, vhf_s1occ[0], p1a)) +
                 reduce(numpy.dot, (p1b, vhf_s1occ[1], p1b))) * .5
    time1 = log.timer_debug1('h1 and JK1', *time1)

    # Hartree-Fock part contribution
    dm1pa = hf_dm1a + dm1[0]*2
    dm1pb = hf_dm1b + dm1[1]*2
    dm1 = dm1[0] + dm1[1] + hf_dm1
    zeta_a += rhf_grad.make_rdm1e(mo_ea, mo_a, mycc.mo_occ[0])
    zeta_b += rhf_grad.make_rdm1e(mo_eb, mo_b, mycc.mo_occ[1])
    zeta = zeta_a + zeta_b

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]
# s[1] dot I, note matrix im1 is not hermitian
        de[k] += numpy.einsum('xij,ij->x', s1[:,p0:p1], im1[p0:p1])
        de[k] += numpy.einsum('xji,ij->x', s1[:,p0:p1], im1[:,p0:p1])
# h[1] \dot DM, contribute to f1
        h1ao = hcore_deriv(ia)
        de[k] += numpy.einsum('xij,ji->x', h1ao, dm1)
# -s[1]*e \dot DM,  contribute to f1
        de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], zeta[p0:p1]  )
        de[k] -= numpy.einsum('xji,ij->x', s1[:,p0:p1], zeta[:,p0:p1])
# -vhf[s_ij[1]],  contribute to f1, *2 for s1+s1.T
        de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], vhf_s1occ[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ij->x', vhf1[k,0], dm1pa)
        de[k] -= numpy.einsum('xij,ij->x', vhf1[k,1], dm1pb)

    log.timer('%s gradients' % mycc.__class__.__name__, *time0)
    return de
Beispiel #35
0
def grad_elec(mc_grad, mo_coeff=None, ci=None, atmlst=None, verbose=None):
    mc = mc_grad.base
    if mo_coeff is None: mo_coeff = mc._scf.mo_coeff
    if ci is None: ci = mc.ci

    time0 = logger.process_clock(), logger.perf_counter()
    log = logger.new_logger(mc_grad, verbose)
    mol = mc_grad.mol
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao + 1) // 2
    mo_energy = mc._scf.mo_energy

    mo_occ = mo_coeff[:, :nocc]
    mo_core = mo_coeff[:, :ncore]
    mo_cas = mo_coeff[:, ncore:nocc]
    neleca, nelecb = mol.nelec
    assert (neleca == nelecb)
    orbo = mo_coeff[:, :neleca]
    orbv = mo_coeff[:, neleca:]

    casdm1, casdm2 = mc.fcisolver.make_rdm12(ci, ncas, nelecas)
    dm_core = numpy.dot(mo_core, mo_core.T) * 2
    dm_cas = reduce(numpy.dot, (mo_cas, casdm1, mo_cas.T))
    aapa = ao2mo.kernel(mol, (mo_cas, mo_cas, mo_coeff, mo_cas), compact=False)
    aapa = aapa.reshape(ncas, ncas, nmo, ncas)
    vj, vk = mc._scf.get_jk(mol, (dm_core, dm_cas))
    h1 = mc.get_hcore()
    vhf_c = vj[0] - vk[0] * .5
    vhf_a = vj[1] - vk[1] * .5
    # Imat = h1_{pi} gamma1_{iq} + h2_{pijk} gamma_{iqkj}
    Imat = numpy.zeros((nmo, nmo))
    Imat[:, :nocc] = reduce(numpy.dot,
                            (mo_coeff.T, h1 + vhf_c + vhf_a, mo_occ)) * 2
    Imat[:, ncore:nocc] = reduce(numpy.dot,
                                 (mo_coeff.T, h1 + vhf_c, mo_cas, casdm1))
    Imat[:, ncore:nocc] += lib.einsum('uviw,vuwt->it', aapa, casdm2)
    aapa = vj = vk = vhf_c = vhf_a = h1 = None

    ee = mo_energy[:, None] - mo_energy
    zvec = numpy.zeros_like(Imat)
    zvec[:ncore,
         ncore:neleca] = Imat[:ncore, ncore:neleca] / -ee[:ncore, ncore:neleca]
    zvec[ncore:neleca, :ncore] = Imat[
        ncore:neleca, :ncore] / -ee[ncore:neleca, :ncore]
    zvec[nocc:,
         neleca:nocc] = Imat[nocc:, neleca:nocc] / -ee[nocc:, neleca:nocc]
    zvec[neleca:nocc,
         nocc:] = Imat[neleca:nocc, nocc:] / -ee[neleca:nocc, nocc:]

    zvec_ao = reduce(numpy.dot, (mo_coeff, zvec + zvec.T, mo_coeff.T))
    vhf = mc._scf.get_veff(mol, zvec_ao) * 2
    xvo = reduce(numpy.dot, (orbv.T, vhf, orbo))
    xvo += Imat[neleca:, :neleca] - Imat[:neleca, neleca:].T

    def fvind(x):
        x = x.reshape(xvo.shape)
        dm = reduce(numpy.dot, (orbv, x, orbo.T))
        v = mc._scf.get_veff(mol, dm + dm.T)
        v = reduce(numpy.dot, (orbv.T, v, orbo))
        return v * 2

    dm1resp = cphf.solve(fvind, mo_energy, mc._scf.mo_occ, xvo,
                         max_cycle=30)[0]
    zvec[neleca:, :neleca] = dm1resp

    zeta = numpy.einsum('ij,j->ij', zvec, mo_energy)
    zeta = reduce(numpy.dot, (mo_coeff, zeta, mo_coeff.T))

    zvec_ao = reduce(numpy.dot, (mo_coeff, zvec + zvec.T, mo_coeff.T))
    p1 = numpy.dot(mo_coeff[:, :neleca], mo_coeff[:, :neleca].T)
    vhf_s1occ = reduce(numpy.dot, (p1, mc._scf.get_veff(mol, zvec_ao), p1))

    Imat[:ncore, ncore:neleca] = 0
    Imat[ncore:neleca, :ncore] = 0
    Imat[nocc:, neleca:nocc] = 0
    Imat[neleca:nocc, nocc:] = 0
    Imat[neleca:, :neleca] = Imat[:neleca, neleca:].T
    im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T))

    casci_dm1 = dm_core + dm_cas
    hf_dm1 = mc._scf.make_rdm1(mo_coeff, mc._scf.mo_occ)
    hcore_deriv = mc_grad.hcore_generator(mol)
    s1 = mc_grad.get_ovlp(mol)

    diag_idx = numpy.arange(nao)
    diag_idx = diag_idx * (diag_idx + 1) // 2 + diag_idx
    casdm2_cc = casdm2 + casdm2.transpose(0, 1, 3, 2)
    dm2buf = ao2mo._ao2mo.nr_e2(casdm2_cc.reshape(ncas**2, ncas**2), mo_cas.T,
                                (0, nao, 0, nao)).reshape(ncas**2, nao, nao)
    dm2buf = lib.pack_tril(dm2buf)
    dm2buf[:, diag_idx] *= .5
    dm2buf = dm2buf.reshape(ncas, ncas, nao_pair)
    casdm2 = casdm2_cc = None

    if atmlst is None:
        atmlst = range(mol.natm)
    aoslices = mol.aoslice_by_atom()
    de = numpy.zeros((len(atmlst), 3))

    max_memory = mc_grad.max_memory - lib.current_memory()[0]
    blksize = int(max_memory * .9e6 / 8 /
                  ((aoslices[:, 3] - aoslices[:, 2]).max() * nao_pair))
    blksize = min(nao, max(2, blksize))

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        h1ao = hcore_deriv(ia)
        de[k] += numpy.einsum('xij,ij->x', h1ao, casci_dm1)
        de[k] += numpy.einsum('xij,ij->x', h1ao, zvec_ao)

        q1 = 0
        for b0, b1, nf in _shell_prange(mol, 0, mol.nbas, blksize):
            q0, q1 = q1, q1 + nf
            dm2_ao = lib.einsum('ijw,pi,qj->pqw', dm2buf, mo_cas[p0:p1],
                                mo_cas[q0:q1])
            shls_slice = (shl0, shl1, b0, b1, 0, mol.nbas, 0, mol.nbas)
            eri1 = mol.intor('int2e_ip1',
                             comp=3,
                             aosym='s2kl',
                             shls_slice=shls_slice).reshape(
                                 3, p1 - p0, nf, nao_pair)
            de[k] -= numpy.einsum('xijw,ijw->x', eri1, dm2_ao) * 2

            for i in range(3):
                eri1tmp = lib.unpack_tril(eri1[i].reshape((p1 - p0) * nf, -1))
                eri1tmp = eri1tmp.reshape(p1 - p0, nf, nao, nao)
                de[k, i] -= numpy.einsum('ijkl,ij,kl', eri1tmp,
                                         hf_dm1[p0:p1, q0:q1], zvec_ao) * 2
                de[k, i] -= numpy.einsum('ijkl,kl,ij', eri1tmp, hf_dm1,
                                         zvec_ao[p0:p1, q0:q1]) * 2
                de[k, i] += numpy.einsum('ijkl,il,kj', eri1tmp, hf_dm1[p0:p1],
                                         zvec_ao[q0:q1])
                de[k, i] += numpy.einsum('ijkl,jk,il', eri1tmp, hf_dm1[q0:q1],
                                         zvec_ao[p0:p1])

                #:vhf1c, vhf1a = mc_grad.get_veff(mol, (dm_core, dm_cas))
                #:de[k] += numpy.einsum('xij,ij->x', vhf1c[:,p0:p1], casci_dm1[p0:p1]) * 2
                #:de[k] += numpy.einsum('xij,ij->x', vhf1a[:,p0:p1], dm_core[p0:p1]) * 2
                de[k, i] -= numpy.einsum('ijkl,lk,ij', eri1tmp, dm_core[q0:q1],
                                         casci_dm1[p0:p1]) * 2
                de[k, i] += numpy.einsum('ijkl,jk,il', eri1tmp, dm_core[q0:q1],
                                         casci_dm1[p0:p1])
                de[k, i] -= numpy.einsum('ijkl,lk,ij', eri1tmp, dm_cas[q0:q1],
                                         dm_core[p0:p1]) * 2
                de[k, i] += numpy.einsum('ijkl,jk,il', eri1tmp, dm_cas[q0:q1],
                                         dm_core[p0:p1])
            eri1 = eri1tmp = None

        de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1])
        de[k] -= numpy.einsum('xij,ji->x', s1[:, p0:p1], im1[:, p0:p1])

        de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ji->x', s1[:, p0:p1], zeta[:, p0:p1]) * 2

        de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf_s1occ[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ji->x', s1[:, p0:p1], vhf_s1occ[:,
                                                                   p0:p1]) * 2

    log.timer('CASCI nuclear gradients', *time0)
    return de
Beispiel #36
0
tdB = mfB.TDA().run()

# CIS coeffcients
state_id = 2  # The third excited state
t1_A = tdA.xy[state_id][0] * np.sqrt(2)
t1_B = tdB.xy[state_id][0] * np.sqrt(2)

# The intermolecular 2e integrals
molAB = molA + molB
naoA = molA.nao
eri = molAB.intor('int2e')
eri_AABB = eri[:naoA, :naoA, naoA:, naoA:]
eri_ABBA = eri[:naoA, naoA:, naoA:, :naoA]

# Transform integrals to MO basis
eri_iabj = lib.einsum('pqrs,pi,qa,rb,sj->iabj', eri_AABB, o_A, v_A, v_B, o_B)
eri_ijba = lib.einsum('pqrs,pi,qj,rb,sa->ijba', eri_ABBA, o_A, o_B, v_B, v_A)

# J-type coupling and K-type coupling
cJ = np.einsum('iabj,ia,jb->', eri_iabj, t1_A, t1_B)
cK = np.einsum('ijba,ia,jb->', eri_ijba, t1_A, t1_B)
print(cJ, cK)


#
# Below is an efficient implementation
#
def jk_ints(molA, molB, dm_ia, dm_jb):
    from pyscf.scf import jk, _vhf
    naoA = molA.nao
    naoB = molB.nao
Beispiel #37
0
def get_ab(mf, mo_energy=None, mo_coeff=None, mo_occ=None):
    r'''A and B matrices for TDDFT response function.

    A[i,a,j,b] = \delta_{ab}\delta_{ij}(E_a - E_i) + (ia||bj)
    B[i,a,j,b] = (ia||jb)
    '''
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_coeff is None: mo_coeff = mf.mo_coeff
    if mo_occ is None: mo_occ = mf.mo_occ
    assert(mo_coeff.dtype == numpy.double)

    mol = mf.mol
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]
    nvir = orbv.shape[1]
    nocc = orbo.shape[1]
    mo = numpy.hstack((orbo,orbv))
    nmo = nocc + nvir

    e_ia = lib.direct_sum('a-i->ia', mo_energy[viridx], mo_energy[occidx])
    a = numpy.diag(e_ia.ravel()).reshape(nocc,nvir,nocc,nvir)
    b = numpy.zeros_like(a)

    def add_hf_(a, b, hyb=1):
        eri_mo = ao2mo.general(mol, [orbo,mo,mo,mo], compact=False)
        eri_mo = eri_mo.reshape(nocc,nmo,nmo,nmo)
        a += numpy.einsum('iabj->iajb', eri_mo[:nocc,nocc:,nocc:,:nocc]) * 2
        a -= numpy.einsum('ijba->iajb', eri_mo[:nocc,:nocc,nocc:,nocc:]) * hyb

        b += numpy.einsum('iajb->iajb', eri_mo[:nocc,nocc:,:nocc,nocc:]) * 2
        b -= numpy.einsum('jaib->iajb', eri_mo[:nocc,nocc:,:nocc,nocc:]) * hyb

    if getattr(mf, 'xc', None) and getattr(mf, '_numint', None):
        from pyscf.dft import rks
        from pyscf.dft import numint
        ni = mf._numint
        ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True)
        if getattr(mf, 'nlc', '') != '':
            logger.warn(mf, 'NLC functional found in DFT object.  Its second '
                        'deriviative is not available. Its contribution is '
                        'not included in the response function.')
        omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)

        add_hf_(a, b, hyb)

        xctype = ni._xc_type(mf.xc)
        dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        make_rho = ni._gen_rho_evaluator(mol, dm0, hermi=1)[0]
        mem_now = lib.current_memory()[0]
        max_memory = max(2000, mf.max_memory*.8-mem_now)

        if xctype == 'LDA':
            ao_deriv = 0
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, mf.grids, nao, ao_deriv, max_memory):
                rho = make_rho(0, ao, mask, 'LDA')
                fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[2]
                frr = fxc[0]

                rho_o = lib.einsum('rp,pi->ri', ao, orbo)
                rho_v = lib.einsum('rp,pi->ri', ao, orbv)
                rho_ov = numpy.einsum('ri,ra->ria', rho_o, rho_v)
                w_ov = numpy.einsum('ria,r->ria', rho_ov, weight*frr)
                iajb = lib.einsum('ria,rjb->iajb', rho_ov, w_ov) * 2
                a += iajb
                b += iajb

        elif xctype == 'GGA':
            ao_deriv = 1
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, mf.grids, nao, ao_deriv, max_memory):
                rho = make_rho(0, ao, mask, 'GGA')
                vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
                vgamma = vxc[1]
                frho, frhogamma, fgg = fxc[:3]

                rho_o = lib.einsum('xrp,pi->xri', ao, orbo)
                rho_v = lib.einsum('xrp,pi->xri', ao, orbv)
                rho_ov = numpy.einsum('xri,ra->xria', rho_o, rho_v[0])
                rho_ov[1:4] += numpy.einsum('ri,xra->xria', rho_o[0], rho_v[1:4])
                # sigma1 ~ \nabla(\rho_\alpha+\rho_\beta) dot \nabla(|b><j|) z_{bj}
                sigma1 = numpy.einsum('xr,xria->ria', rho[1:4], rho_ov[1:4])

                w_ov = numpy.empty_like(rho_ov)
                w_ov[0]  = numpy.einsum('r,ria->ria', frho, rho_ov[0])
                w_ov[0] += numpy.einsum('r,ria->ria', 2*frhogamma, sigma1)
                f_ov = numpy.einsum('r,ria->ria', 4*fgg, sigma1)
                f_ov+= numpy.einsum('r,ria->ria', 2*frhogamma, rho_ov[0])
                w_ov[1:] = numpy.einsum('ria,xr->xria', f_ov, rho[1:4])
                w_ov[1:]+= numpy.einsum('r,xria->xria', 2*vgamma, rho_ov[1:4])
                w_ov *= weight[:,None,None]
                iajb = lib.einsum('xria,xrjb->iajb', rho_ov, w_ov) * 2
                a += iajb
                b += iajb

        elif xctype == 'NLC':
            raise NotImplementedError('NLC')
        elif xctype == 'MGGA':
            raise NotImplementedError('meta-GGA')

    else:
        add_hf_(a, b)

    return a, b
Beispiel #38
0
def get_fno(mp,
            mo_energy=None,
            mo_coeff=None,
            eris=None,
            thresh_vir=THRESH_VIR,
            verbose=logger.NOTE):

    lib.logger.info(mp, "\n* Fno procedure")
    lib.logger.info(mp, "* Threshold for virtual occupation %g", thresh_vir)

    if mo_energy is None:
        mo_energy = mp.mo_energy[mp.get_frozen_mask()]
    else:
        mo_energy = mo_energy[mp.get_frozen_mask()]

    if eris is None: eris = mp.ao2mo(mo_coeff)

    nocc = mp.nocc
    nvir = mp.nmo - nocc
    eia = mo_energy[:nocc, None] - mo_energy[None, nocc:]
    t2 = numpy.empty((nocc, nocc, nvir, nvir), dtype=numpy.complex128)

    for i in range(nocc):
        gi = numpy.asarray(eris.oovv[i]).reshape(nocc, nvir, nvir)
        t2i = gi.conj() / lib.direct_sum('jb+a->jba', eia, eia[i])
        t2[i] = t2i

    dvv = lib.einsum('mnea,mneb->ab', t2, t2.conj()) * 0.5
    dm1 = dvv + dvv.conj().T
    dm1 *= 0.5

    natoccvir, natorbvir = numpy.linalg.eigh(-dm1)
    for i, k in enumerate(numpy.argmax(abs(natorbvir), axis=0)):
        if natorbvir[k, i] < 0:
            natorbvir[:, i] *= -1
    natoccvir = -natoccvir
    lib.logger.debug(mp, "* Occupancies")
    lib.logger.debug(mp, "* %s" % natoccvir)
    lib.logger.debug(mp, "* The sum is %8.6f" % numpy.sum(natoccvir))
    active = (thresh_vir <= natoccvir)
    lib.logger.info(mp, "* Natural Orbital selection")
    for i in range(nvir):
        lib.logger.debug(mp, "orb: %d %s %8.6f" % (i, active[i], natoccvir[i]))
        actIndices = numpy.where(active)[0]
    lib.logger.info(mp, "* Original active orbitals %d" % nvir)
    lib.logger.info(mp,
                    "* Virtual core orbitals: %d" % (nvir - len(actIndices)))
    lib.logger.info(mp, "* New active orbitals %d" % len(actIndices))
    lib.logger.debug(mp, "* Active orbital indices %s" % actIndices)
    natorbvir = natorbvir[:, actIndices]
    ev = mo_energy[nocc:]
    fvv = numpy.diag(ev)
    fvv = reduce(numpy.dot, (natorbvir.conj().T, fvv, natorbvir))
    ev, fnov = numpy.linalg.eigh(fvv)
    cv = mp.mo_coeff[:, mp.get_frozen_mask()]
    cv = cv[:, nocc:]
    cv = reduce(numpy.dot, (cv, natorbvir, fnov))
    co = mp.mo_coeff[:, mp.mo_occ > 0]
    eo = mp.mo_energy[mp.mo_occ > 0]
    coeff = numpy.hstack([co, cv])
    energy = numpy.hstack([eo, ev])
    occ = numpy.zeros(coeff.shape[1])
    for i in range(mp.mol.nelectron):
        occ[i] = 1.0
    return coeff, energy, occ
Beispiel #39
0
def make_rdm1_vv(mp, t2=None):
    if t2 is None: t2 = mp.t2
    dvv = lib.einsum('mnea,mneb->ab', t2, t2.conj()) * 0.5
    dm1 = dvv + dvv.conj().T
    dm1 *= 0.5
    return dm1
Beispiel #40
0
def contract(myci, civec, eris):
    nocc = myci.nocc
    nmo = myci.nmo

    c0, c1, c2 = cisdvec_to_amplitudes(civec, nmo, nocc)

    fock = eris.fock
    foo = fock[:nocc,:nocc]
    fov = fock[:nocc,nocc:]
    fvo = fock[nocc:,:nocc]
    fvv = fock[nocc:,nocc:]

    t1  = lib.einsum('ie,ae->ia', c1, fvv)
    t1 -= lib.einsum('ma,mi->ia', c1, foo)
    t1 += lib.einsum('imae,me->ia', c2, fov)
    t1 += lib.einsum('nf,nafi->ia', c1, eris.ovvo)
    t1 -= 0.5*lib.einsum('imef,maef->ia', c2, eris.ovvv)
    t1 -= 0.5*lib.einsum('mnae,mnie->ia', c2, eris.ooov)

    tmp = lib.einsum('ijae,be->ijab', c2, fvv)
    t2  = tmp - tmp.transpose(0,1,3,2)
    tmp = lib.einsum('imab,mj->ijab', c2, foo)
    t2 -= tmp - tmp.transpose(1,0,2,3)
    t2 += 0.5*lib.einsum('mnab,mnij->ijab', c2, eris.oooo)
    t2 += 0.5*lib.einsum('ijef,abef->ijab', c2, eris.vvvv)
    tmp = lib.einsum('imae,mbej->ijab', c2, eris.ovvo)
    tmp+= numpy.einsum('ia,bj->ijab', c1, fvo)
    tmp = tmp - tmp.transpose(0,1,3,2)
    t2 += tmp - tmp.transpose(1,0,2,3)
    tmp = lib.einsum('ie,jeba->ijab', c1, numpy.asarray(eris.ovvv).conj())
    t2 += tmp - tmp.transpose(1,0,2,3)
    tmp = lib.einsum('ma,ijmb->ijab', c1, numpy.asarray(eris.ooov).conj())
    t2 -= tmp - tmp.transpose(0,1,3,2)

    eris_oovv = numpy.asarray(eris.oovv)
    t1 += fov.conj() * c0
    t2 += eris_oovv.conj() * c0
    t0  = numpy.einsum('ia,ia', fov, c1)
    t0 += numpy.einsum('ijab,ijab', eris_oovv, c2) * .25

    return amplitudes_to_cisdvec(t0, t1, t2)
Beispiel #41
0
def update_amps(cc, t1, t2, eris):
    # Ref: Hirata et al., J. Chem. Phys. 120, 2581 (2004) Eqs.(35)-(36)
    assert(isinstance(eris, ccsd._ChemistsERIs))
    nocc, nvir = t1.shape
    fock = eris.fock
    mo_e_o = eris.mo_energy[:nocc]
    mo_e_v = eris.mo_energy[nocc:] + cc.level_shift

    fov = fock[:nocc,nocc:].copy()
    foo = fock[:nocc,:nocc].copy()
    fvv = fock[nocc:,nocc:].copy()

    Foo = imd.cc_Foo(t1,t2,eris)
    Fvv = imd.cc_Fvv(t1,t2,eris)
    Fov = imd.cc_Fov(t1,t2,eris)

    # Move energy terms to the other side
    Foo[np.diag_indices(nocc)] -= mo_e_o
    Fvv[np.diag_indices(nvir)] -= mo_e_v

    #occ_act = np.arange(cc.frozen_occ,nocc)
    occ_act = np.arange(nocc)
    vir_act = np.arange(cc.nvir_act)
    #print("occ_act =", occ_act)
    #print("vir_act =", vir_act)
    ia_act = np.ix_(occ_act,vir_act)
    ijab_act = np.ix_(occ_act,occ_act,vir_act,vir_act)
    #print("ia =", ia_act)
    #print("ijab =", ijab_act)

    # T1 equation
    t1new = np.copy(fov.conj())
    t1new[ia_act] -= 2*np.einsum('kc,ka,ic->ia', fov, t1, t1)[ia_act]
    t1new[ia_act] +=   np.einsum('ac,ic->ia', Fvv, t1)[ia_act]
    t1new[ia_act] +=  -np.einsum('ki,ka->ia', Foo, t1)[ia_act]
    t1new[ia_act] += 2*np.einsum('kc,kica->ia', Fov, t2)[ia_act]
    t1new[ia_act] +=  -np.einsum('kc,ikca->ia', Fov, t2)[ia_act]
    t1new[ia_act] +=   np.einsum('kc,ic,ka->ia', Fov, t1, t1)[ia_act]
    t1new[ia_act] += 2*np.einsum('kcai,kc->ia', eris.ovvo, t1)[ia_act]
    t1new[ia_act] +=  -np.einsum('kiac,kc->ia', eris.oovv, t1)[ia_act]
    eris_ovvv = np.asarray(eris.get_ovvv())
    t1new[ia_act] += 2*lib.einsum('kdac,ikcd->ia', eris_ovvv, t2)[ia_act]
    t1new[ia_act] +=  -lib.einsum('kcad,ikcd->ia', eris_ovvv, t2)[ia_act]
    t1new[ia_act] += 2*lib.einsum('kdac,kd,ic->ia', eris_ovvv, t1, t1)[ia_act]
    t1new[ia_act] +=  -lib.einsum('kcad,kd,ic->ia', eris_ovvv, t1, t1)[ia_act]
    eris_ovoo = np.asarray(eris.ovoo, order='C')
    t1new[ia_act] +=-2*lib.einsum('lcki,klac->ia', eris_ovoo, t2)[ia_act]
    t1new[ia_act] +=   lib.einsum('kcli,klac->ia', eris_ovoo, t2)[ia_act]
    t1new[ia_act] +=-2*lib.einsum('lcki,lc,ka->ia', eris_ovoo, t1, t1)[ia_act]
    t1new[ia_act] +=   lib.einsum('kcli,lc,ka->ia', eris_ovoo, t1, t1)[ia_act]

    # T2 equation
    t2new = np.copy(np.asarray(eris.ovov).conj().transpose(0,2,1,3))
    tmp2  = lib.einsum('kibc,ka->abic', eris.oovv, -t1)
    tmp2 += np.asarray(eris_ovvv).conj().transpose(1,3,0,2)
    tmp = lib.einsum('abic,jc->ijab', tmp2, t1)
    t2new[ijab_act] += (tmp + tmp.transpose(1,0,3,2))[ijab_act]
    tmp2  = lib.einsum('kcai,jc->akij', eris.ovvo, t1)
    tmp2 += eris_ovoo.transpose(1,3,0,2).conj()
    tmp = lib.einsum('akij,kb->ijab', tmp2, t1)
    t2new[ijab_act] -= (tmp + tmp.transpose(1,0,3,2))[ijab_act]

    Loo = imd.Loo(t1, t2, eris)
    Lvv = imd.Lvv(t1, t2, eris)
    Loo[np.diag_indices(nocc)] -= mo_e_o
    Lvv[np.diag_indices(nvir)] -= mo_e_v

    Woooo = imd.cc_Woooo(t1, t2, eris)
    Wvoov = imd.cc_Wvoov(t1, t2, eris)
    Wvovo = imd.cc_Wvovo(t1, t2, eris)
    Wvvvv = imd.cc_Wvvvv(t1, t2, eris)

    tau = t2 + np.einsum('ia,jb->ijab', t1, t1)
    t2new[ijab_act] += lib.einsum('klij,klab->ijab', Woooo, tau)[ijab_act]
    t2new[ijab_act] += lib.einsum('abcd,ijcd->ijab', Wvvvv, tau)[ijab_act]
    tmp = lib.einsum('ac,ijcb->ijab', Lvv, t2)
    t2new[ijab_act] += (tmp + tmp.transpose(1,0,3,2))[ijab_act]
    tmp = lib.einsum('ki,kjab->ijab', Loo, t2)
    t2new[ijab_act] -= (tmp + tmp.transpose(1,0,3,2))[ijab_act]
    tmp  = 2*lib.einsum('akic,kjcb->ijab', Wvoov, t2)
    tmp -=   lib.einsum('akci,kjcb->ijab', Wvovo, t2)
    t2new[ijab_act] += (tmp + tmp.transpose(1,0,3,2))[ijab_act]
    tmp = lib.einsum('akic,kjbc->ijab', Wvoov, t2)
    t2new[ijab_act] -= (tmp + tmp.transpose(1,0,3,2))[ijab_act]
    tmp = lib.einsum('bkci,kjac->ijab', Wvovo, t2)
    t2new[ijab_act] -= (tmp + tmp.transpose(1,0,3,2))[ijab_act]

    eia = mo_e_o[:,None] - mo_e_v
    eijab = lib.direct_sum('ia,jb->ijab',eia,eia)
    t1new /= eia
    t2new /= eijab

    return t1new, t2new
Beispiel #42
0
def grad_elec_dferi (mc_grad, mo_cas=None, ci=None, dfcasdm2=None, casdm2=None, atmlst=None, max_memory=None):
    ''' Evaluate the (P|i'j) d_Pij contribution to the electronic gradient, where d_Pij is the
    DF-2RDM obtained by solve_df_rdm2. The caller must symmetrize (i.e., [(P|i'j) + (P|ij')] d_Pij / 2)
    if necessary. 

    Args:
        mc_grad: MC-SCF gradients method object

    Kwargs:
        mc_cas: ndarray, list, or tuple containing active-space MO coefficients
            If a tuple of length 2, the same pair of MO sets are assumed to apply to
            the internally-contracted and externally-contracted indices of the DF-2rdm:
            (P|Q)d_Qij = (P|kl)d_ijkl -> (P|Q)d_Qij = (P|ij)d_ijij
            If a tuple of length 4, the 4 MO sets are applied to ijkl above in that order
            (first two external, last two internal).
        ci: ndarray, tuple, or list containing CI coefficients in mo_cas basis.
            Not used if dfcasdm2 is provided.
        dfcasdm2: ndarray, tuple, or list containing DF-2rdm in mo_cas basis.
            Computed by solve_df_rdm2 if omitted.
        casdm2: ndarray, tuple, or list containing rdm2 in mo_cas basis.
            Computed by mc_grad.fcisolver.make_rdm12 (ci,...) if omitted.
        atmlst: list of integers
            List of nonfrozen atoms, as in grad_elec functions.
            Defaults to list (range (mol.natm))
        max_memory: int
            Maximum memory usage in MB

    Returns:
        dE: ndarray of shape (len (dfcasdm2), len (atmlst), 3) '''
    if isinstance (mc_grad, GradientsBasics):
        mc = mc_grad.base
    else:
        mc = mc_grad
    mol = mc_grad.mol
    auxmol = mc.with_df.auxmol
    ncore, ncas, nao, naux, nbas = mc.ncore, mc.ncas, mol.nao, auxmol.nao, mol.nbas
    nocc = ncore + ncas
    if mo_cas is None: mo_cas = mc.mo_coeff[:,ncore:nocc]
    if max_memory is None: max_memory = mc_grad.max_memory
    if isinstance (mo_cas, np.ndarray) and mo_cas.ndim == 2:
        mo_cas = (mo_cas,)*4
    elif len (mo_cas) == 2:
        mo_cas = (mo_cas[0], mo_cas[1], mo_cas[0], mo_cas[1])
    elif len (mo_cas) == 4:
        mo_cas = tuple (mo_cas)
    else:
        raise RuntimeError ('Invalid shape of np.asarray (mo_cas): {}'.format (mo_cas.shape))
    nmo = [mo.shape[1] for mo in mo_cas]
    if atmlst is None: atmlst = list (range (mol.natm))
    if ci is None: ci = mc.ci
    if dfcasdm2 is None: dfcasdm2 = solve_df_rdm2 (mc, mo_cas=mo_cas[2:], ci=ci, casdm2=casdm2) # d_Pij
    nset = len (dfcasdm2)
    dE = np.zeros ((nset, nao, 3))
    dfcasdm2 = np.array (dfcasdm2)

    # Set up (P|u'v) calculation
    get_int3c = _int3c_wrapper(mol, auxmol, 'int3c2e_ip1', 's1')
    max_memory -= lib.current_memory()[0]  
    blklen = nao*((3*nao) + (3*nmo[1]) + (nset*nmo[1]))
    blksize = int (min (max (max_memory * 1e6 / 8 / blklen, 20), 240))
    aux_loc = auxmol.ao_loc
    aux_ranges = balance_partition(aux_loc, blksize)

    # Iterate over auxbasis range
    for shl0, shl1, nL in aux_ranges:
        p0, p1 = aux_loc[shl0], aux_loc[shl1]
        int3c = get_int3c ((0, nbas, 0, nbas, shl0, shl1))  # (u'v|P); shape = (3,nao,nao,p1-p0)
        intbuf = lib.einsum ('xuvp,vj->xupj', int3c, mo_cas[1])
        dm2buf = lib.einsum ('ui,npij->nupj', mo_cas[0], dfcasdm2[:,p0:p1,:,:])
        dE -= np.einsum ('nupj,xupj->nux', dm2buf, intbuf) 
        intbuf = dm2buf = None
        intbuf = lib.einsum ('xuvp,vj->xupj', int3c, mo_cas[0])
        dm2buf = lib.einsum ('uj,npij->nupi', mo_cas[1], dfcasdm2[:,p0:p1,:,:])
        dE -= np.einsum ('nupj,xupj->nux', dm2buf, intbuf) 
        intbuf = dm2buf = int3c = None

    aoslices = mol.aoslice_by_atom ()
    dE = np.array ([dE[:,p0:p1].sum (axis=1) for p0, p1 in aoslices[:,2:]]).transpose (1,0,2)
    return np.ascontiguousarray (dE)
Beispiel #43
0
    def update_amps(self, t1, t2, eris):

        cc = self
        # Ref: Taube and Bartlett J. Chem. Phys. 130, 144112 (2009) Eq. 13 and 15
        assert isinstance(eris, ccsd._ChemistsERIs)
        nocc, nvir = t1.shape
        fock = eris.fock
        mo_e_o = eris.mo_energy[:nocc]
        mo_e_v = eris.mo_energy[nocc:] + cc.level_shift

        fov = fock[:nocc, nocc:].copy()
        foo = fock[:nocc, :nocc].copy()
        fvv = fock[nocc:, nocc:].copy()

        Foo = foo
        Fvv = fvv
        Fov = fov

        # Move energy terms to the other side
        Foo[np.diag_indices(nocc)] -= mo_e_o
        Fvv[np.diag_indices(nvir)] -= mo_e_v

        ###############
        # T1 equation #
        ###############
        t1new = np.zeros_like(t1)

        # Term 1
        t1new += fov.conj()

        # Term 2
        t1new += np.einsum("ac,ic->ia", Fvv, t1)

        # Term 3
        t1new += -np.einsum("ki,ka->ia", Foo, t1)

        # Term 4
        t1new += 2 * np.einsum("kcai,kc->ia", eris.ovvo, t1)
        t1new += -np.einsum("kiac,kc->ia", eris.oovv, t1)

        # Term 5
        eris_ovvv = np.asarray(eris.get_ovvv())
        t1new += 2 * lib.einsum("kdac,ikcd->ia", eris_ovvv, t2)
        t1new += -lib.einsum("kcad,ikcd->ia", eris_ovvv, t2)

        # Term 6
        eris_ovoo = np.asarray(eris.ovoo, order="C")
        t1new += -2 * lib.einsum("lcki,klac->ia", eris_ovoo, t2)
        t1new += lib.einsum("kcli,klac->ia", eris_ovoo, t2)

        # Term 7
        t1new += 2 * np.einsum("kc,kica->ia", Fov, t2)
        t1new += -np.einsum("kc,ikca->ia", Fov, t2)

        ###############
        # T2 equation #
        ###############
        t2new = np.zeros_like(t2)
        # Term 1
        t2new += np.asarray(eris.ovov).conj().transpose(0, 2, 1, 3)

        # Term 2
        tmp = lib.einsum("ki,kjab->ijab", Foo, t2)
        t2new -= tmp + tmp.transpose(1, 0, 3, 2)

        # Term 3
        tmp = lib.einsum("ac,ijcb->ijab", Fvv, t2)
        t2new += tmp + tmp.transpose(1, 0, 3, 2)

        Woooo = np.asarray(eris.oooo).transpose(0, 2, 1, 3)
        Wvoov = np.asarray(eris.ovvo).transpose(2, 0, 3, 1)
        Wvovo = np.asarray(eris.oovv).transpose(2, 0, 3, 1)
        Wvvvv = np.asarray(imd._get_vvvv(eris)).transpose(0, 2, 1, 3)

        # Term 4
        t2new += lib.einsum("abcd,ijcd->ijab", Wvvvv, t2)

        # Term 5
        t2new += lib.einsum("klij,klab->ijab", Woooo, t2)

        # Term 6
        tmp = 2 * lib.einsum("akic,kjcb->ijab", Wvoov, t2)
        tmp -= lib.einsum("akci,kjcb->ijab", Wvovo, t2)
        t2new += tmp + tmp.transpose(1, 0, 3, 2)
        tmp = lib.einsum("akic,kjbc->ijab", Wvoov, t2)
        t2new -= tmp + tmp.transpose(1, 0, 3, 2)
        tmp = lib.einsum("bkci,kjac->ijab", Wvovo, t2)
        t2new -= tmp + tmp.transpose(1, 0, 3, 2)

        # Term 7
        tmp2 = eris_ovoo.transpose(1, 3, 0, 2).conj()
        tmp = lib.einsum("akij,kb->ijab", tmp2, t1)
        t2new -= tmp + tmp.transpose(1, 0, 3, 2)

        # Term 8
        tmp2 = np.asarray(eris_ovvv).conj().transpose(1, 3, 0, 2)
        tmp = lib.einsum("abic,jc->ijab", tmp2, t1)
        t2new += tmp + tmp.transpose(1, 0, 3, 2)

        eia = mo_e_o[:, None] - mo_e_v
        eijab = lib.direct_sum("ia,jb->ijab", eia, eia)
        t1new /= eia
        t2new /= eijab

        return t1new, t2new
Beispiel #44
0
    def construct_tdm(self):

        # Indexes of td_x:
        # - k_transfer
        # - k
        # - o: k
        # - v: fw[k]

        # Indexes of td_y:
        # - k_transfer
        # - k
        # - o: k
        # - v: bw[k]

        # Original code:
        # tdm_oo = einsum('vxia,ipaq->vxpq', td_xy, self["oovo"])
        # tdm_ov = einsum('vxia,ipaq->vxpq', td_xy, self["oovv"])
        # tdm_vv = einsum('vxia,ipaq->vxpq', td_xy, self["ovvv"])

        # ERI k:
        # ki, kp, ka=?, kq

        # Now fw[kp] = kq, bw[kq] = kp -> bw[ki] = ka, fw[ka] = ki
        # for x amplitudes, the transfer is bw[0] such that ov -> k, bw[k]
        # for y amplitudes, the transfer is also fw[0] such that ov -> k, bw[k]

        result = []

        for k_transfer in range(self.nk):
            xy_k = self.td_xy[k_transfer]

            fw, bw, _, _ = get_block_k_ix(self.eri, k_transfer)
            result.append([[], []])

            for xy_kx, ix_fw, ix_bw, storage in (
                (xy_k[:, 0], fw, bw, result[k_transfer][0]),  # X
                (xy_k[:, 1], bw, fw, result[k_transfer][1]),  # Y
            ):

                for kp in range(self.nk):

                    tdm_oo = tdm_ov = tdm_vv = 0

                    tdm_vo = 0

                    for ki in range(self.nk):

                        x = xy_kx[:, ki] * 2
                        tdm_oo = tdm_oo + einsum(
                            'via,ipaq->vpq', x, self["oovo", ki, kp, ix_fw[ki],
                                                     ix_bw[kp]])
                        tdm_ov = tdm_ov + einsum(
                            'via,ipaq->vpq', x, self["oovv", ki, kp, ix_fw[ki],
                                                     ix_bw[kp]])
                        tdm_vv = tdm_vv + einsum(
                            'via,ipaq->vpq', x, self["ovvv", ki, kp, ix_fw[ki],
                                                     ix_bw[kp]])
                        tdm_vo = tdm_vo + einsum(
                            'via,ipaq->vpq', x, self["ovvo", ki, kp, ix_fw[ki],
                                                     ix_bw[kp]])

                    tdm = numpy.concatenate(
                        (numpy.concatenate((tdm_oo, tdm_ov), axis=2),
                         numpy.concatenate((tdm_vo, tdm_vv), axis=2)),
                        axis=1,
                    )

                    storage.append(tdm)
        # The output is the following:
        # for each kp, kq pair two 3-tensors are given
        # The last two indexes in each tensor correspond to kp, kq
        # Given fw, bw, _, _ = get_block_k_ix(self.eri, (kp, kq)),
        # The first index of the two tensors will correspond to tdhf.e[bw[0]], tdhf.e[fw[0]] correspondingly
        return numpy.array(result)
Beispiel #45
0
def _gamma1_intermediates(mp, t2):
    doo = lib.einsum('imef,jmef->ij', t2.conj(), t2) * -.5
    dvv = lib.einsum('mnea,mneb->ab', t2, t2.conj()) * .5
    return doo, dvv
Beispiel #46
0
    def test_update_amps2(self):  # compare to gccsd.update_amps
        mol = mol_s2
        mf = mf_s2
        myucc = uccsd.UCCSD(mf)
        nocca, noccb = 6, 4
        nmo = mol.nao_nr()
        nvira, nvirb = nmo - nocca, nmo - noccb
        numpy.random.seed(9)
        t1 = [
            numpy.random.random((nocca, nvira)) - .9,
            numpy.random.random((noccb, nvirb)) - .9
        ]
        t2 = [
            numpy.random.random((nocca, nocca, nvira, nvira)) - .9,
            numpy.random.random((nocca, noccb, nvira, nvirb)) - .9,
            numpy.random.random((noccb, noccb, nvirb, nvirb)) - .9
        ]
        t2[0] = t2[0] - t2[0].transpose(1, 0, 2, 3)
        t2[0] = t2[0] - t2[0].transpose(0, 1, 3, 2)
        t2[2] = t2[2] - t2[2].transpose(1, 0, 2, 3)
        t2[2] = t2[2] - t2[2].transpose(0, 1, 3, 2)

        mo_a = mf.mo_coeff[0] + numpy.sin(mf.mo_coeff[0]) * .01j
        mo_b = mf.mo_coeff[1] + numpy.sin(mf.mo_coeff[1]) * .01j
        nao = mo_a.shape[0]
        eri = ao2mo.restore(1, mf._eri, nao)
        eri0aa = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a,
                            mo_a.conj(), mo_a)
        eri0ab = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_a.conj(), mo_a,
                            mo_b.conj(), mo_b)
        eri0bb = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_b.conj(), mo_b,
                            mo_b.conj(), mo_b)
        eri0ba = eri0ab.transpose(2, 3, 0, 1)

        nvira = nao - nocca
        nvirb = nao - noccb
        eris = uccsd._ChemistsERIs(mol)
        eris.oooo = eri0aa[:nocca, :nocca, :nocca, :nocca].copy()
        eris.ovoo = eri0aa[:nocca, nocca:, :nocca, :nocca].copy()
        eris.oovv = eri0aa[:nocca, :nocca, nocca:, nocca:].copy()
        eris.ovvo = eri0aa[:nocca, nocca:, nocca:, :nocca].copy()
        eris.ovov = eri0aa[:nocca, nocca:, :nocca, nocca:].copy()
        eris.ovvv = eri0aa[:nocca, nocca:, nocca:, nocca:].copy()
        eris.vvvv = eri0aa[nocca:, nocca:, nocca:, nocca:].copy()

        eris.OOOO = eri0bb[:noccb, :noccb, :noccb, :noccb].copy()
        eris.OVOO = eri0bb[:noccb, noccb:, :noccb, :noccb].copy()
        eris.OOVV = eri0bb[:noccb, :noccb, noccb:, noccb:].copy()
        eris.OVVO = eri0bb[:noccb, noccb:, noccb:, :noccb].copy()
        eris.OVOV = eri0bb[:noccb, noccb:, :noccb, noccb:].copy()
        eris.OVVV = eri0bb[:noccb, noccb:, noccb:, noccb:].copy()
        eris.VVVV = eri0bb[noccb:, noccb:, noccb:, noccb:].copy()

        eris.ooOO = eri0ab[:nocca, :nocca, :noccb, :noccb].copy()
        eris.ovOO = eri0ab[:nocca, nocca:, :noccb, :noccb].copy()
        eris.ooVV = eri0ab[:nocca, :nocca, noccb:, noccb:].copy()
        eris.ovVO = eri0ab[:nocca, nocca:, noccb:, :noccb].copy()
        eris.ovOV = eri0ab[:nocca, nocca:, :noccb, noccb:].copy()
        eris.ovVV = eri0ab[:nocca, nocca:, noccb:, noccb:].copy()
        eris.vvVV = eri0ab[nocca:, nocca:, noccb:, noccb:].copy()

        eris.OOoo = eri0ba[:noccb, :noccb, :nocca, :nocca].copy()
        eris.OVoo = eri0ba[:noccb, noccb:, :nocca, :nocca].copy()
        eris.OOvv = eri0ba[:noccb, :noccb, nocca:, nocca:].copy()
        eris.OVvo = eri0ba[:noccb, noccb:, nocca:, :nocca].copy()
        eris.OVov = eri0ba[:noccb, noccb:, :nocca, nocca:].copy()
        eris.OVvv = eri0ba[:noccb, noccb:, nocca:, nocca:].copy()
        eris.VVvv = eri0ba[noccb:, noccb:, nocca:, nocca:].copy()

        eris.focka = numpy.diag(mf.mo_energy[0])
        eris.fockb = numpy.diag(mf.mo_energy[1])
        eris.mo_energy = mf.mo_energy

        t1[0] = t1[0] + numpy.sin(t1[0]) * .05j
        t1[1] = t1[1] + numpy.sin(t1[1]) * .05j
        t2[0] = t2[0] + numpy.sin(t2[0]) * .05j
        t2[1] = t2[1] + numpy.sin(t2[1]) * .05j
        t2[2] = t2[2] + numpy.sin(t2[2]) * .05j
        t1new_ref, t2new_ref = uccsd.update_amps(myucc, t1, t2, eris)

        nocc = nocca + noccb
        orbspin = numpy.zeros(nao * 2, dtype=int)
        orbspin[1::2] = 1
        orbspin[nocc - 1] = 0
        orbspin[nocc] = 1
        eri1 = numpy.zeros([nao * 2] * 4, dtype=numpy.complex128)
        idxa = numpy.where(orbspin == 0)[0]
        idxb = numpy.where(orbspin == 1)[0]
        eri1[idxa[:, None, None, None], idxa[:, None, None], idxa[:, None],
             idxa] = eri0aa
        eri1[idxa[:, None, None, None], idxa[:, None, None], idxb[:, None],
             idxb] = eri0ab
        eri1[idxb[:, None, None, None], idxb[:, None, None], idxa[:, None],
             idxa] = eri0ba
        eri1[idxb[:, None, None, None], idxb[:, None, None], idxb[:, None],
             idxb] = eri0bb
        eri1 = eri1.transpose(0, 2, 1, 3) - eri1.transpose(0, 2, 3, 1)
        erig = gccsd._PhysicistsERIs()
        erig.oooo = eri1[:nocc, :nocc, :nocc, :nocc].copy()
        erig.ooov = eri1[:nocc, :nocc, :nocc, nocc:].copy()
        erig.ovov = eri1[:nocc, nocc:, :nocc, nocc:].copy()
        erig.ovvo = eri1[:nocc, nocc:, nocc:, :nocc].copy()
        erig.oovv = eri1[:nocc, :nocc, nocc:, nocc:].copy()
        erig.ovvv = eri1[:nocc, nocc:, nocc:, nocc:].copy()
        erig.vvvv = eri1[nocc:, nocc:, nocc:, nocc:].copy()
        mo_e = numpy.empty(nao * 2)
        mo_e[orbspin == 0] = mf.mo_energy[0]
        mo_e[orbspin == 1] = mf.mo_energy[1]
        erig.fock = numpy.diag(mo_e)
        erig.mo_energy = mo_e.real

        myccg = gccsd.GCCSD(scf.addons.convert_to_ghf(mf))
        t1 = myccg.spatial2spin(t1, orbspin)
        t2 = myccg.spatial2spin(t2, orbspin)
        t1new, t2new = gccsd.update_amps(myccg, t1, t2, erig)
        t1new = myccg.spin2spatial(t1new, orbspin)
        t2new = myccg.spin2spatial(t2new, orbspin)
        self.assertAlmostEqual(abs(t1new[0] - t1new_ref[0]).max(), 0, 12)
        self.assertAlmostEqual(abs(t1new[1] - t1new_ref[1]).max(), 0, 12)
        self.assertAlmostEqual(abs(t2new[0] - t2new_ref[0]).max(), 0, 12)
        self.assertAlmostEqual(abs(t2new[1] - t2new_ref[1]).max(), 0, 12)
        self.assertAlmostEqual(abs(t2new[2] - t2new_ref[2]).max(), 0, 12)
Beispiel #47
0
def k2s(model,
        grid_spec,
        mf_constructor,
        threshold=None,
        degeneracy_threshold=None,
        imaginary_threshold=None):
    """
    Converts k-point model into a supercell with real orbitals.
    Args:
        model: a mean-field pbc model;
        grid_spec (Iterable): integer dimensions of the k-grid in the mean-field model;
        mf_constructor (Callable): a function constructing the mean-field object;
        threshold (float): a threshold for determining the negative k-point index;
        degeneracy_threshold (float): a threshold for assuming degeneracy when composing real-valued orbitals;
        imaginary_threshold (float): a threshold for asserting real-valued supercell orbitals;

    Returns:
        The same class where the Cell object was replaced by the supercell and all fields were adjusted accordingly.
    """
    # This hack works as follows. Provided TRS Hamiltonian
    #    H(k) = H(-k)*,
    # with same real eigenvalues and eigenfunctions related as
    #    psi(k) = c psi(-k)*,
    # c - arbitrary phase, it is easy to construct real (non-Bloch) eigenvectors of the whole Hamiltonian
    #    real1(|k|) = c* psi(k) + psi(-k) = psi(-k)* + psi(-k)
    # and
    #    real2(|k|) = 1.j * (c* psi(k) - psi(-k)) = 1.j* (psi(-k)* - psi(-k)).
    # The coefficient c is determined as
    #    psi(k) * psi(-k) = c psi(-k)* * psi(-k) = c
    if imaginary_threshold is None:
        imaginary_threshold = 1e-7

    mk = minus_k(model,
                 threshold=threshold,
                 degeneracy_threshold=degeneracy_threshold)

    # Fix phases
    ovlp = model.get_ovlp()
    phases = {}
    for k1, k2 in enumerate(mk):
        if k1 <= k2:
            c1 = model.mo_coeff[k1]
            c2 = model.mo_coeff[k2]
            o = ovlp[k1]
            r = reduce(numpy.dot, (c2.T, o, c1))
            delta = abs(abs(r) - numpy.eye(r.shape[0])).max()
            if delta > imaginary_threshold:
                raise RuntimeError(
                    "K-points connected by time reversal {:d} and {:d} are not complex conjugate: "
                    "the difference {:.3e} is larger than the threshold {:.3e}"
                    .format(
                        k1,
                        k2,
                        delta,
                        imaginary_threshold,
                    ))
            p = numpy.angle(numpy.diag(r))
            if k1 == k2:
                phases[k1] = numpy.exp(-.5j * p)[numpy.newaxis, :]
            else:
                phases[k1] = numpy.exp(-1.j * p)[numpy.newaxis, :]

    nk = len(model.kpts)
    t_vecs = cartesian_prod(tuple(numpy.arange(i) for i in grid_spec))
    kpts_frac = model.cell.get_scaled_kpts(model.kpts)

    result = mf_constructor(super_cell(model.cell, grid_spec))
    result_ovlp = result.get_ovlp()[0]

    moe = numpy.concatenate(model.mo_energy)
    moo = numpy.concatenate(model.mo_occ)

    # Complex-valued wf in a supercell
    moc = []
    for mo_coeff, k in zip(model.mo_coeff, kpts_frac):
        psi = (
            mo_coeff[numpy.newaxis, ...] *
            numpy.exp(2.j * numpy.pi * t_vecs.dot(k))[:, numpy.newaxis,
                                                      numpy.newaxis]).reshape(
                                                          -1,
                                                          mo_coeff.shape[1])
        norms = einsum("ai,ab,bi->i", psi.conj(), result_ovlp, psi)**.5
        psi /= norms[numpy.newaxis, :]
        moc.append(psi)
    moc = numpy.concatenate(moc, axis=1)

    rotation_matrix = sparse.dok_matrix(moc.shape, dtype=moc.dtype)
    inv_rotation_matrix = sparse.dok_matrix(moc.shape, dtype=moc.dtype)
    nvecs = (0, ) + tuple(i.shape[1] for i in model.mo_coeff)
    nvecs = numpy.cumsum(nvecs)
    k_spaces = tuple(numpy.arange(i, j) for i, j in zip(nvecs[:-1], nvecs[1:]))

    for k in range(nk):

        i = k_spaces[k]
        j = k_spaces[mk[k]]

        if k == mk[k]:
            rotation_matrix[i, i] = phases[k]
            inv_rotation_matrix[i, i] = phases[k].conj()

        elif k < mk[k]:
            rotation_matrix[i, i] = .5**.5 * phases[k]
            rotation_matrix[j, i] = .5**.5
            rotation_matrix[i, j] = -1.j * .5**.5 * phases[k]
            rotation_matrix[j, j] = 1.j * .5**.5

            inv_rotation_matrix[i, i] = .5**.5 * phases[k].conj()
            inv_rotation_matrix[j, i] = 1.j * .5**.5 * phases[k].conj()
            inv_rotation_matrix[i, j] = .5**.5
            inv_rotation_matrix[j, j] = -1.j * .5**.5

        else:
            pass

    rotation_matrix = rotation_matrix.tocsc()
    inv_rotation_matrix = inv_rotation_matrix.tocsc()

    moc = sparse_transform(moc, 1, rotation_matrix)
    max_imag = abs(moc.imag).max()
    if max_imag > imaginary_threshold:
        raise RuntimeError(
            "Failed to compose real-valued orbitals: imaginary part is {:.3e}".
            format(max_imag))
    moc = moc.real

    mok = numpy.concatenate(
        tuple([i] * len(j) for i, j in enumerate(model.mo_energy)))
    moi = numpy.concatenate(
        tuple(numpy.arange(len(j)) for j in model.mo_energy))

    order = numpy.argsort(moe)

    moe = moe[order]
    moc = moc[:, order]
    moo = moo[order]
    mok = mok[order]
    moi = moi[order]
    rotation_matrix = rotation_matrix[:, order]
    inv_rotation_matrix = inv_rotation_matrix[order, :]

    result.mo_occ = moo,
    result.mo_energy = moe,
    result.mo_coeff = moc,
    result.supercell_rotation = rotation_matrix
    result.supercell_inv_rotation = inv_rotation_matrix
    result.supercell_orig_k = mok
    result.supercell_orig_i = moi

    assert_scf_converged(result, model.conv_tol**.5)

    p1 = abs(
        result.supercell_rotation.dot(result.supercell_inv_rotation) -
        numpy.eye(rotation_matrix.shape[0])).max()
    p2 = abs(
        result.supercell_inv_rotation.dot(result.supercell_rotation) -
        numpy.eye(rotation_matrix.shape[0])).max()
    if p1 > 1e-14 or p2 > 1e-14:
        raise RuntimeError("Rotation matrix error: {:.3e}, {:.3e}".format(
            p1, p2))

    return result
Beispiel #48
0
def make_intermediates(mycc, t1, t2, eris):
    t1a, t1b = t1
    t2aa, t2ab, t2bb = t2
    nocca, nvira = t1a.shape
    noccb, nvirb = t1b.shape

    fooa = eris.focka[:nocca,:nocca]
    fova = eris.focka[:nocca,nocca:]
    fvoa = eris.focka[nocca:,:nocca]
    fvva = eris.focka[nocca:,nocca:]
    foob = eris.fockb[:noccb,:noccb]
    fovb = eris.fockb[:noccb,noccb:]
    fvob = eris.fockb[noccb:,:noccb]
    fvvb = eris.fockb[noccb:,noccb:]

    tauaa, tauab, taubb = uccsd.make_tau(t2, t1, t1)

    ovov = numpy.asarray(eris.ovov)
    ovov = ovov - ovov.transpose(0,3,2,1)
    OVOV = numpy.asarray(eris.OVOV)
    OVOV = OVOV - OVOV.transpose(0,3,2,1)
    ovOV = numpy.asarray(eris.ovOV)

    v1a  = fvva - einsum('ja,jb->ba', fova, t1a)
    v1b  = fvvb - einsum('ja,jb->ba', fovb, t1b)
    v1a += einsum('jcka,jkbc->ba', ovov, tauaa) * .5
    v1a -= einsum('jaKC,jKbC->ba', ovOV, tauab) * .5
    v1a -= einsum('kaJC,kJbC->ba', ovOV, tauab) * .5
    v1b += einsum('jcka,jkbc->ba', OVOV, taubb) * .5
    v1b -= einsum('kcJA,kJcB->BA', ovOV, tauab) * .5
    v1b -= einsum('jcKA,jKcB->BA', ovOV, tauab) * .5

    v2a  = fooa + einsum('ib,jb->ij', fova, t1a)
    v2b  = foob + einsum('ib,jb->ij', fovb, t1b)
    v2a += einsum('ibkc,jkbc->ij', ovov, tauaa) * .5
    v2a += einsum('ibKC,jKbC->ij', ovOV, tauab)
    v2b += einsum('ibkc,jkbc->ij', OVOV, taubb) * .5
    v2b += einsum('kcIB,kJcB->IJ', ovOV, tauab)

    ovoo = numpy.asarray(eris.ovoo)
    ovoo = ovoo - ovoo.transpose(2,1,0,3)
    OVOO = numpy.asarray(eris.OVOO)
    OVOO = OVOO - OVOO.transpose(2,1,0,3)
    OVoo = numpy.asarray(eris.OVoo)
    ovOO = numpy.asarray(eris.ovOO)
    v2a -= numpy.einsum('ibkj,kb->ij', ovoo, t1a)
    v2a += numpy.einsum('KBij,KB->ij', OVoo, t1b)
    v2b -= numpy.einsum('ibkj,kb->ij', OVOO, t1b)
    v2b += numpy.einsum('kbIJ,kb->IJ', ovOO, t1a)

    v5a  = fvoa + numpy.einsum('kc,jkbc->bj', fova, t2aa)
    v5a += numpy.einsum('KC,jKbC->bj', fovb, t2ab)
    v5b  = fvob + numpy.einsum('kc,jkbc->bj', fovb, t2bb)
    v5b += numpy.einsum('kc,kJcB->BJ', fova, t2ab)
    tmp  = fova - numpy.einsum('kdlc,ld->kc', ovov, t1a)
    tmp += numpy.einsum('kcLD,LD->kc', ovOV, t1b)
    v5a += einsum('kc,kb,jc->bj', tmp, t1a, t1a)
    tmp  = fovb - numpy.einsum('kdlc,ld->kc', OVOV, t1b)
    tmp += numpy.einsum('ldKC,ld->KC', ovOV, t1a)
    v5b += einsum('kc,kb,jc->bj', tmp, t1b, t1b)
    v5a -= einsum('lckj,klbc->bj', ovoo, t2aa) * .5
    v5a -= einsum('LCkj,kLbC->bj', OVoo, t2ab)
    v5b -= einsum('LCKJ,KLBC->BJ', OVOO, t2bb) * .5
    v5b -= einsum('lcKJ,lKcB->BJ', ovOO, t2ab)

    oooo = numpy.asarray(eris.oooo)
    OOOO = numpy.asarray(eris.OOOO)
    ooOO = numpy.asarray(eris.ooOO)
    woooo  = einsum('icjl,kc->ikjl', ovoo, t1a)
    wOOOO  = einsum('icjl,kc->ikjl', OVOO, t1b)
    wooOO  = einsum('icJL,kc->ikJL', ovOO, t1a)
    wooOO += einsum('JCil,KC->ilJK', OVoo, t1b)
    woooo += (oooo - oooo.transpose(0,3,2,1)) * .5
    wOOOO += (OOOO - OOOO.transpose(0,3,2,1)) * .5
    wooOO += ooOO.copy()
    woooo += einsum('icjd,klcd->ikjl', ovov, tauaa) * .25
    wOOOO += einsum('icjd,klcd->ikjl', OVOV, taubb) * .25
    wooOO += einsum('icJD,kLcD->ikJL', ovOV, tauab)

    v4ovvo  = einsum('jbld,klcd->jbck', ovov, t2aa)
    v4ovvo += einsum('jbLD,kLcD->jbck', ovOV, t2ab)
    v4ovvo += numpy.asarray(eris.ovvo)
    v4ovvo -= numpy.asarray(eris.oovv).transpose(0,3,2,1)
    v4OVVO  = einsum('jbld,klcd->jbck', OVOV, t2bb)
    v4OVVO += einsum('ldJB,lKdC->JBCK', ovOV, t2ab)
    v4OVVO += numpy.asarray(eris.OVVO)
    v4OVVO -= numpy.asarray(eris.OOVV).transpose(0,3,2,1)
    v4OVvo  = einsum('ldJB,klcd->JBck', ovOV, t2aa)
    v4OVvo += einsum('JBLD,kLcD->JBck', OVOV, t2ab)
    v4OVvo += numpy.asarray(eris.OVvo)
    v4ovVO  = einsum('jbLD,KLCD->jbCK', ovOV, t2bb)
    v4ovVO += einsum('jbld,lKdC->jbCK', ovov, t2ab)
    v4ovVO += numpy.asarray(eris.ovVO)
    v4oVVo  = einsum('jdLB,kLdC->jBCk', ovOV, t2ab)
    v4oVVo -= numpy.asarray(eris.ooVV).transpose(0,3,2,1)
    v4OvvO  = einsum('lbJD,lKcD->JbcK', ovOV, t2ab)
    v4OvvO -= numpy.asarray(eris.OOvv).transpose(0,3,2,1)

    woovo  = einsum('ibck,jb->ijck', v4ovvo, t1a)
    wOOVO  = einsum('ibck,jb->ijck', v4OVVO, t1b)
    wOOvo  = einsum('IBck,JB->IJck', v4OVvo, t1b)
    wOOvo -= einsum('IbcK,jb->IKcj', v4OvvO, t1a)
    wooVO  = einsum('ibCK,jb->ijCK', v4ovVO, t1a)
    wooVO -= einsum('iBCk,JB->ikCJ', v4oVVo, t1b)
    woovo += ovoo.conj().transpose(3,2,1,0) * .5
    wOOVO += OVOO.conj().transpose(3,2,1,0) * .5
    wooVO += OVoo.conj().transpose(3,2,1,0)
    wOOvo += ovOO.conj().transpose(3,2,1,0)
    woovo -= einsum('iclk,jlbc->ikbj', ovoo, t2aa)
    woovo += einsum('LCik,jLbC->ikbj', OVoo, t2ab)
    wOOVO -= einsum('iclk,jlbc->ikbj', OVOO, t2bb)
    wOOVO += einsum('lcIK,lJcB->IKBJ', ovOO, t2ab)
    wooVO -= einsum('iclk,lJcB->ikBJ', ovoo, t2ab)
    wooVO += einsum('LCik,JLBC->ikBJ', OVoo, t2bb)
    wooVO -= einsum('icLK,jLcB->ijBK', ovOO, t2ab)
    wOOvo -= einsum('ICLK,jLbC->IKbj', OVOO, t2ab)
    wOOvo += einsum('lcIK,jlbc->IKbj', ovOO, t2aa)
    wOOvo -= einsum('IClk,lJbC->IJbk', OVoo, t2ab)

    wvvvo  = einsum('jack,jb->back', v4ovvo, t1a)
    wVVVO  = einsum('jack,jb->back', v4OVVO, t1b)
    wVVvo  = einsum('JAck,JB->BAck', v4OVvo, t1b)
    wVVvo -= einsum('jACk,jb->CAbk', v4oVVo, t1a)
    wvvVO  = einsum('jaCK,jb->baCK', v4ovVO, t1a)
    wvvVO -= einsum('JacK,JB->caBK', v4OvvO, t1b)
    wvvvo += einsum('lajk,jlbc->back', .25*ovoo, tauaa)
    wVVVO += einsum('lajk,jlbc->back', .25*OVOO, taubb)
    wVVvo -= einsum('LAjk,jLcB->BAck', OVoo, tauab)
    wvvVO -= einsum('laJK,lJbC->baCK', ovOO, tauab)

    w3a  = numpy.einsum('jbck,jb->ck', v4ovvo, t1a)
    w3a += numpy.einsum('JBck,JB->ck', v4OVvo, t1b)
    w3b  = numpy.einsum('jbck,jb->ck', v4OVVO, t1b)
    w3b += numpy.einsum('jbCK,jb->CK', v4ovVO, t1a)

    wovvo  = v4ovvo
    wOVVO  = v4OVVO
    wovVO  = v4ovVO
    wOVvo  = v4OVvo
    woVVo  = v4oVVo
    wOvvO  = v4OvvO
    wovvo += lib.einsum('jbld,kd,lc->jbck', ovov, t1a, -t1a)
    wOVVO += lib.einsum('jbld,kd,lc->jbck', OVOV, t1b, -t1b)
    wovVO += lib.einsum('jbLD,KD,LC->jbCK', ovOV, t1b, -t1b)
    wOVvo += lib.einsum('ldJB,kd,lc->JBck', ovOV, t1a, -t1a)
    woVVo += lib.einsum('jdLB,kd,LC->jBCk', ovOV, t1a,  t1b)
    wOvvO += lib.einsum('lbJD,KD,lc->JbcK', ovOV, t1b,  t1a)
    wovvo -= einsum('jblk,lc->jbck', ovoo, t1a)
    wOVVO -= einsum('jblk,lc->jbck', OVOO, t1b)
    wovVO -= einsum('jbLK,LC->jbCK', ovOO, t1b)
    wOVvo -= einsum('JBlk,lc->JBck', OVoo, t1a)
    woVVo += einsum('LBjk,LC->jBCk', OVoo, t1b)
    wOvvO += einsum('lbJK,lc->JbcK', ovOO, t1a)

    if nvira > 0 and nocca > 0:
        ovvv = numpy.asarray(eris.get_ovvv())
        ovvv = ovvv - ovvv.transpose(0,3,2,1)
        v1a -= numpy.einsum('jabc,jc->ba', ovvv, t1a)
        v5a += einsum('kdbc,jkcd->bj', ovvv, t2aa) * .5
        woovo += einsum('idcb,kjbd->ijck', ovvv, tauaa) * .25
        wovvo += einsum('jbcd,kd->jbck', ovvv, t1a)
        wvvvo -= ovvv.conj().transpose(3,2,1,0) * .5
        wvvvo += einsum('jacd,kjbd->cabk', ovvv, t2aa)
        wvvVO += einsum('jacd,jKdB->caBK', ovvv, t2ab)
        ovvv = tmp = None

    if nvirb > 0 and noccb > 0:
        OVVV = numpy.asarray(eris.get_OVVV())
        OVVV = OVVV - OVVV.transpose(0,3,2,1)
        v1b -= numpy.einsum('jabc,jc->ba', OVVV, t1b)
        v5b += einsum('KDBC,JKCD->BJ', OVVV, t2bb) * .5
        wOOVO += einsum('idcb,kjbd->ijck', OVVV, taubb) * .25
        wOVVO += einsum('jbcd,kd->jbck', OVVV, t1b)
        wVVVO -= OVVV.conj().transpose(3,2,1,0) * .5
        wVVVO += einsum('jacd,kjbd->cabk', OVVV, t2bb)
        wVVvo += einsum('JACD,kJbD->CAbk', OVVV, t2ab)
        OVVV = tmp = None

    if nvirb > 0 and nocca > 0:
        OVvv = numpy.asarray(eris.get_OVvv())
        v1a += numpy.einsum('JCba,JC->ba', OVvv, t1b)
        v5a += einsum('KDbc,jKcD->bj', OVvv, t2ab)
        wOOvo += einsum('IDcb,kJbD->IJck', OVvv, tauab)
        wOVvo += einsum('JBcd,kd->JBck', OVvv, t1a)
        wOvvO -= einsum('JDcb,KD->JbcK', OVvv, t1b)
        wvvVO -= OVvv.conj().transpose(3,2,1,0)
        wvvvo -= einsum('KDca,jKbD->cabj', OVvv, t2ab)
        wvvVO -= einsum('KDca,JKBD->caBJ', OVvv, t2bb)
        wVVvo += einsum('KAcd,jKdB->BAcj', OVvv, t2ab)
        OVvv = tmp = None

    if nvira > 0 and noccb > 0:
        ovVV = numpy.asarray(eris.get_ovVV())
        v1b += numpy.einsum('jcBA,jc->BA', ovVV, t1a)
        v5b += einsum('kdBC,kJdC->BJ', ovVV, t2ab)
        wooVO += einsum('idCB,jKdB->ijCK', ovVV, tauab)
        wovVO += einsum('jbCD,KD->jbCK', ovVV, t1b)
        woVVo -= einsum('jdCB,kd->jBCk', ovVV, t1a)
        wVVvo -= ovVV.conj().transpose(3,2,1,0)
        wVVVO -= einsum('kdCA,kJdB->CABJ', ovVV, t2ab)
        wVVvo -= einsum('kdCA,jkbd->CAbj', ovVV, t2aa)
        wvvVO += einsum('kaCD,kJbD->baCJ', ovVV, t2ab)
        ovVV = tmp = None

    w3a += v5a
    w3b += v5b
    w3a += lib.einsum('cb,jb->cj', v1a, t1a)
    w3b += lib.einsum('cb,jb->cj', v1b, t1b)
    w3a -= lib.einsum('jk,jb->bk', v2a, t1a)
    w3b -= lib.einsum('jk,jb->bk', v2b, t1b)

    class _IMDS: pass
    imds = _IMDS()
    imds.ftmp = lib.H5TmpFile()
    dtype = numpy.result_type(t2ab, eris.vvvv).char
    imds.woooo = imds.ftmp.create_dataset('woooo', (nocca,nocca,nocca,nocca), dtype)
    imds.wooOO = imds.ftmp.create_dataset('wooOO', (nocca,nocca,noccb,noccb), dtype)
    imds.wOOOO = imds.ftmp.create_dataset('wOOOO', (noccb,noccb,noccb,noccb), dtype)
    imds.wovvo = imds.ftmp.create_dataset('wovvo', (nocca,nvira,nvira,nocca), dtype)
    imds.wOVVO = imds.ftmp.create_dataset('wOVVO', (noccb,nvirb,nvirb,noccb), dtype)
    imds.wovVO = imds.ftmp.create_dataset('wovVO', (nocca,nvira,nvirb,noccb), dtype)
    imds.wOVvo = imds.ftmp.create_dataset('wOVvo', (noccb,nvirb,nvira,nocca), dtype)
    imds.woVVo = imds.ftmp.create_dataset('woVVo', (nocca,nvirb,nvirb,nocca), dtype)
    imds.wOvvO = imds.ftmp.create_dataset('wOvvO', (noccb,nvira,nvira,noccb), dtype)
    imds.woovo = imds.ftmp.create_dataset('woovo', (nocca,nocca,nvira,nocca), dtype)
    imds.wOOVO = imds.ftmp.create_dataset('wOOVO', (noccb,noccb,nvirb,noccb), dtype)
    imds.wOOvo = imds.ftmp.create_dataset('wOOvo', (noccb,noccb,nvira,nocca), dtype)
    imds.wooVO = imds.ftmp.create_dataset('wooVO', (nocca,nocca,nvirb,noccb), dtype)
    imds.wvvvo = imds.ftmp.create_dataset('wvvvo', (nvira,nvira,nvira,nocca), dtype)
    imds.wVVVO = imds.ftmp.create_dataset('wVVVO', (nvirb,nvirb,nvirb,noccb), dtype)
    imds.wVVvo = imds.ftmp.create_dataset('wVVvo', (nvirb,nvirb,nvira,nocca), dtype)
    imds.wvvVO = imds.ftmp.create_dataset('wvvVO', (nvira,nvira,nvirb,noccb), dtype)

    imds.woooo[:] = woooo
    imds.wOOOO[:] = wOOOO
    imds.wooOO[:] = wooOO
    imds.wovvo[:] = wovvo
    imds.wOVVO[:] = wOVVO
    imds.wovVO[:] = wovVO
    imds.wOVvo[:] = wOVvo
    imds.woVVo[:] = woVVo
    imds.wOvvO[:] = wOvvO
    imds.woovo[:] = woovo
    imds.wOOVO[:] = wOOVO
    imds.wOOvo[:] = wOOvo
    imds.wooVO[:] = wooVO
    imds.wvvvo[:] = wvvvo
    imds.wVVVO[:] = wVVVO
    imds.wVVvo[:] = wVVvo
    imds.wvvVO[:] = wvvVO
    imds.v1a = v1a
    imds.v1b = v1b
    imds.v2a = v2a
    imds.v2b = v2b
    imds.w3a = w3a
    imds.w3b = w3b
    imds.ftmp.flush()
    return imds
Beispiel #49
0
def get_ab(mf, mo_energy=None, mo_coeff=None, mo_occ=None):
    r'''A and B matrices for TDDFT response function.

    A[i,a,j,b] = \delta_{ab}\delta_{ij}(E_a - E_i) + (ia||bj)
    B[i,a,j,b] = (ia||jb)

    Spin symmetry is considered in the returned A, B lists.  List A has three
    items: (A_aaaa, A_aabb, A_bbbb). A_bbaa = A_aabb.transpose(2,3,0,1).
    B has three items: (B_aaaa, B_aabb, B_bbbb).
    B_bbaa = B_aabb.transpose(2,3,0,1).
    '''
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_coeff is None: mo_coeff = mf.mo_coeff
    if mo_occ is None: mo_occ = mf.mo_occ

    mol = mf.mol
    nao = mol.nao_nr()
    occidx_a = numpy.where(mo_occ[0] == 1)[0]
    viridx_a = numpy.where(mo_occ[0] == 0)[0]
    occidx_b = numpy.where(mo_occ[1] == 1)[0]
    viridx_b = numpy.where(mo_occ[1] == 0)[0]
    orbo_a = mo_coeff[0][:, occidx_a]
    orbv_a = mo_coeff[0][:, viridx_a]
    orbo_b = mo_coeff[1][:, occidx_b]
    orbv_b = mo_coeff[1][:, viridx_b]
    nocc_a = orbo_a.shape[1]
    nvir_a = orbv_a.shape[1]
    nocc_b = orbo_b.shape[1]
    nvir_b = orbv_b.shape[1]
    mo_a = numpy.hstack((orbo_a, orbv_a))
    mo_b = numpy.hstack((orbo_b, orbv_b))
    nmo_a = nocc_a + nvir_a
    nmo_b = nocc_b + nvir_b

    e_ia_a = (mo_energy[0][viridx_a, None] - mo_energy[0][occidx_a]).T
    e_ia_b = (mo_energy[1][viridx_b, None] - mo_energy[1][occidx_b]).T
    a_aa = numpy.diag(e_ia_a.ravel()).reshape(nocc_a, nvir_a, nocc_a, nvir_a)
    a_bb = numpy.diag(e_ia_b.ravel()).reshape(nocc_b, nvir_b, nocc_b, nvir_b)
    a_ab = numpy.zeros((nocc_a, nvir_a, nocc_b, nvir_b))
    b_aa = numpy.zeros_like(a_aa)
    b_ab = numpy.zeros_like(a_ab)
    b_bb = numpy.zeros_like(a_bb)
    a = (a_aa, a_ab, a_bb)
    b = (b_aa, b_ab, b_bb)

    def add_hf_(a, b, hyb=1):
        eri_aa = ao2mo.general(mol, [orbo_a, mo_a, mo_a, mo_a], compact=False)
        eri_ab = ao2mo.general(mol, [orbo_a, mo_a, mo_b, mo_b], compact=False)
        eri_bb = ao2mo.general(mol, [orbo_b, mo_b, mo_b, mo_b], compact=False)
        eri_aa = eri_aa.reshape(nocc_a, nmo_a, nmo_a, nmo_a)
        eri_ab = eri_ab.reshape(nocc_a, nmo_a, nmo_b, nmo_b)
        eri_bb = eri_bb.reshape(nocc_b, nmo_b, nmo_b, nmo_b)
        a_aa, a_ab, a_bb = a
        b_aa, b_ab, b_bb = b

        a_aa += numpy.einsum('iabj->iajb', eri_aa[:nocc_a, nocc_a:,
                                                  nocc_a:, :nocc_a])
        a_aa -= numpy.einsum('ijba->iajb', eri_aa[:nocc_a, :nocc_a, nocc_a:,
                                                  nocc_a:]) * hyb
        b_aa += numpy.einsum('iajb->iajb', eri_aa[:nocc_a, nocc_a:, :nocc_a,
                                                  nocc_a:])
        b_aa -= numpy.einsum('jaib->iajb', eri_aa[:nocc_a, nocc_a:, :nocc_a,
                                                  nocc_a:]) * hyb

        a_bb += numpy.einsum('iabj->iajb', eri_bb[:nocc_b, nocc_b:,
                                                  nocc_b:, :nocc_b])
        a_bb -= numpy.einsum('ijba->iajb', eri_bb[:nocc_b, :nocc_b, nocc_b:,
                                                  nocc_b:]) * hyb
        b_bb += numpy.einsum('iajb->iajb', eri_bb[:nocc_b, nocc_b:, :nocc_b,
                                                  nocc_b:])
        b_bb -= numpy.einsum('jaib->iajb', eri_bb[:nocc_b, nocc_b:, :nocc_b,
                                                  nocc_b:]) * hyb

        a_ab += numpy.einsum('iabj->iajb', eri_ab[:nocc_a, nocc_a:,
                                                  nocc_b:, :nocc_b])
        b_ab += numpy.einsum('iajb->iajb', eri_ab[:nocc_a, nocc_a:, :nocc_b,
                                                  nocc_b:])

    if getattr(mf, 'xc', None) and getattr(mf, '_numint', None):
        from pyscf.dft import rks
        from pyscf.dft import numint
        ni = mf._numint
        ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True)
        if getattr(mf, 'nlc', '') != '':
            logger.warn(
                mf, 'NLC functional found in DFT object.  Its second '
                'deriviative is not available. Its contribution is '
                'not included in the response function.')
        omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)

        add_hf_(a, b, hyb)

        xctype = ni._xc_type(mf.xc)
        dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        make_rho = ni._gen_rho_evaluator(mol, dm0, hermi=1)[0]
        mem_now = lib.current_memory()[0]
        max_memory = max(2000, mf.max_memory * .8 - mem_now)

        if xctype == 'LDA':
            ao_deriv = 0
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, mf.grids, nao, ao_deriv, max_memory):
                rho0a = make_rho(0, ao, mask, 'LDA')
                rho0b = make_rho(1, ao, mask, 'LDA')
                fxc = ni.eval_xc(mf.xc, (rho0a, rho0b), 1, deriv=2)[2]
                u_u, u_d, d_d = fxc[0].T

                rho_o_a = lib.einsum('rp,pi->ri', ao, orbo_a)
                rho_v_a = lib.einsum('rp,pi->ri', ao, orbv_a)
                rho_o_b = lib.einsum('rp,pi->ri', ao, orbo_b)
                rho_v_b = lib.einsum('rp,pi->ri', ao, orbv_b)
                rho_ov_a = numpy.einsum('ri,ra->ria', rho_o_a, rho_v_a)
                rho_ov_b = numpy.einsum('ri,ra->ria', rho_o_b, rho_v_b)

                w_ov = numpy.einsum('ria,r->ria', rho_ov_a, weight * u_u)
                iajb = lib.einsum('ria,rjb->iajb', rho_ov_a, w_ov)
                a_aa += iajb
                b_aa += iajb

                w_ov = numpy.einsum('ria,r->ria', rho_ov_b, weight * u_d)
                iajb = lib.einsum('ria,rjb->iajb', rho_ov_a, w_ov)
                a_ab += iajb
                b_ab += iajb

                w_ov = numpy.einsum('ria,r->ria', rho_ov_b, weight * d_d)
                iajb = lib.einsum('ria,rjb->iajb', rho_ov_b, w_ov)
                a_bb += iajb
                b_bb += iajb

        elif xctype == 'GGA':
            ao_deriv = 1
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, mf.grids, nao, ao_deriv, max_memory):
                rho0a = make_rho(0, ao, mask, 'GGA')
                rho0b = make_rho(1, ao, mask, 'GGA')
                vxc, fxc = ni.eval_xc(mf.xc, (rho0a, rho0b), 1, deriv=2)[1:3]
                uu, ud, dd = vxc[1].T
                u_u, u_d, d_d = fxc[0].T
                u_uu, u_ud, u_dd, d_uu, d_ud, d_dd = fxc[1].T
                uu_uu, uu_ud, uu_dd, ud_ud, ud_dd, dd_dd = fxc[2].T

                rho_o_a = lib.einsum('xrp,pi->xri', ao, orbo_a)
                rho_v_a = lib.einsum('xrp,pi->xri', ao, orbv_a)
                rho_o_b = lib.einsum('xrp,pi->xri', ao, orbo_b)
                rho_v_b = lib.einsum('xrp,pi->xri', ao, orbv_b)
                rho_ov_a = numpy.einsum('xri,ra->xria', rho_o_a, rho_v_a[0])
                rho_ov_b = numpy.einsum('xri,ra->xria', rho_o_b, rho_v_b[0])
                rho_ov_a[1:4] += numpy.einsum('ri,xra->xria', rho_o_a[0],
                                              rho_v_a[1:4])
                rho_ov_b[1:4] += numpy.einsum('ri,xra->xria', rho_o_b[0],
                                              rho_v_b[1:4])
                # sigma1 ~ \nabla(\rho_\alpha+\rho_\beta) dot \nabla(|b><j|) z_{bj}
                a0a1 = numpy.einsum('xr,xria->ria', rho0a[1:4], rho_ov_a[1:4])
                a0b1 = numpy.einsum('xr,xria->ria', rho0a[1:4], rho_ov_b[1:4])
                b0a1 = numpy.einsum('xr,xria->ria', rho0b[1:4], rho_ov_a[1:4])
                b0b1 = numpy.einsum('xr,xria->ria', rho0b[1:4], rho_ov_b[1:4])

                w_ov = numpy.empty_like(rho_ov_a)
                w_ov[0] = numpy.einsum('r,ria->ria', u_u, rho_ov_a[0])
                w_ov[0] += numpy.einsum('r,ria->ria', 2 * u_uu, a0a1)
                w_ov[0] += numpy.einsum('r,ria->ria', u_ud, b0a1)
                f_ov_a = numpy.einsum('r,ria->ria', 4 * uu_uu, a0a1)
                f_ov_b = numpy.einsum('r,ria->ria', 2 * uu_ud, a0a1)
                f_ov_a += numpy.einsum('r,ria->ria', 2 * uu_ud, b0a1)
                f_ov_b += numpy.einsum('r,ria->ria', ud_ud, b0a1)
                f_ov_a += numpy.einsum('r,ria->ria', 2 * u_uu, rho_ov_a[0])
                f_ov_b += numpy.einsum('r,ria->ria', u_ud, rho_ov_a[0])
                w_ov[1:] = numpy.einsum('ria,xr->xria', f_ov_a, rho0a[1:4])
                w_ov[1:] += numpy.einsum('ria,xr->xria', f_ov_b, rho0b[1:4])
                w_ov[1:] += numpy.einsum('r,xria->xria', 2 * uu, rho_ov_a[1:4])
                w_ov *= weight[:, None, None]
                iajb = lib.einsum('xria,xrjb->iajb', rho_ov_a, w_ov)
                a_aa += iajb
                b_aa += iajb

                w_ov = numpy.empty_like(rho_ov_b)
                w_ov[0] = numpy.einsum('r,ria->ria', d_d, rho_ov_b[0])
                w_ov[0] += numpy.einsum('r,ria->ria', 2 * d_dd, b0b1)
                w_ov[0] += numpy.einsum('r,ria->ria', d_ud, a0b1)
                f_ov_b = numpy.einsum('r,ria->ria', 4 * dd_dd, b0b1)
                f_ov_a = numpy.einsum('r,ria->ria', 2 * ud_dd, b0b1)
                f_ov_b += numpy.einsum('r,ria->ria', 2 * ud_dd, a0b1)
                f_ov_a += numpy.einsum('r,ria->ria', ud_ud, a0b1)
                f_ov_b += numpy.einsum('r,ria->ria', 2 * d_dd, rho_ov_b[0])
                f_ov_a += numpy.einsum('r,ria->ria', d_ud, rho_ov_b[0])
                w_ov[1:] = numpy.einsum('ria,xr->xria', f_ov_a, rho0a[1:4])
                w_ov[1:] += numpy.einsum('ria,xr->xria', f_ov_b, rho0b[1:4])
                w_ov[1:] += numpy.einsum('r,xria->xria', 2 * dd, rho_ov_b[1:4])
                w_ov *= weight[:, None, None]
                iajb = lib.einsum('xria,xrjb->iajb', rho_ov_b, w_ov)
                a_bb += iajb
                b_bb += iajb

                w_ov = numpy.empty_like(rho_ov_b)
                w_ov[0] = numpy.einsum('r,ria->ria', u_d, rho_ov_b[0])
                w_ov[0] += numpy.einsum('r,ria->ria', 2 * u_dd, b0b1)
                w_ov[0] += numpy.einsum('r,ria->ria', u_ud, a0b1)
                f_ov_a = numpy.einsum('r,ria->ria', 4 * uu_dd, b0b1)
                f_ov_b = numpy.einsum('r,ria->ria', 2 * ud_dd, b0b1)
                f_ov_a += numpy.einsum('r,ria->ria', 2 * uu_ud, a0b1)
                f_ov_b += numpy.einsum('r,ria->ria', ud_ud, a0b1)
                f_ov_a += numpy.einsum('r,ria->ria', 2 * d_uu, rho_ov_b[0])
                f_ov_b += numpy.einsum('r,ria->ria', d_ud, rho_ov_b[0])
                w_ov[1:] = numpy.einsum('ria,xr->xria', f_ov_a, rho0a[1:4])
                w_ov[1:] += numpy.einsum('ria,xr->xria', f_ov_b, rho0b[1:4])
                w_ov[1:] += numpy.einsum('r,xria->xria', ud, rho_ov_b[1:4])
                w_ov *= weight[:, None, None]
                iajb = lib.einsum('xria,xrjb->iajb', rho_ov_a, w_ov)
                a_ab += iajb
                b_ab += iajb

        elif xctype == 'NLC':
            raise NotImplementedError('NLC')
        elif xctype == 'MGGA':
            raise NotImplementedError('meta-GGA')

    else:
        add_hf_(a, b)

    return a, b
Beispiel #50
0
def update_lambda(mycc, t1, t2, l1, l2, eris, imds):
    time0 = time.clock(), time.time()
    log = logger.Logger(mycc.stdout, mycc.verbose)

    t1a, t1b = t1
    t2aa, t2ab, t2bb = t2
    l1a, l1b = l1
    l2aa, l2ab, l2bb = l2
    nocca, nvira = t1a.shape
    noccb, nvirb = t1b.shape
    u1a = numpy.zeros_like(l1a)
    u1b = numpy.zeros_like(l1b)
    u2aa = numpy.zeros_like(l2aa)
    u2ab = numpy.zeros_like(l2ab)
    u2bb = numpy.zeros_like(l2bb)
    mo_ea_o = eris.mo_energy[0][:nocca]
    mo_ea_v = eris.mo_energy[0][nocca:] + mycc.level_shift
    mo_eb_o = eris.mo_energy[1][:noccb]
    mo_eb_v = eris.mo_energy[1][noccb:] + mycc.level_shift

    fova = eris.focka[:nocca,nocca:]
    fovb = eris.fockb[:noccb,noccb:]
    v1a = imds.v1a - numpy.diag(mo_ea_v)
    v1b = imds.v1b - numpy.diag(mo_eb_v)
    v2a = imds.v2a - numpy.diag(mo_ea_o)
    v2b = imds.v2b - numpy.diag(mo_eb_o)

    mvv = einsum('klca,klcb->ba', l2aa, t2aa) * .5
    mvv+= einsum('lKaC,lKbC->ba', l2ab, t2ab)
    mVV = einsum('klca,klcb->ba', l2bb, t2bb) * .5
    mVV+= einsum('kLcA,kLcB->BA', l2ab, t2ab)
    moo = einsum('kicd,kjcd->ij', l2aa, t2aa) * .5
    moo+= einsum('iKdC,jKdC->ij', l2ab, t2ab)
    mOO = einsum('kicd,kjcd->ij', l2bb, t2bb) * .5
    mOO+= einsum('kIcD,kJcD->IJ', l2ab, t2ab)

    #m3 = lib.einsum('ijcd,cdab->ijab', l2, eris.vvvv) * .5
    m3aa, m3ab, m3bb = mycc._add_vvvv(None, (l2aa.conj(),l2ab.conj(),l2bb.conj()), eris)
    m3aa = m3aa.conj()
    m3ab = m3ab.conj()
    m3bb = m3bb.conj()
    m3aa += lib.einsum('klab,ikjl->ijab', l2aa, numpy.asarray(imds.woooo))
    m3bb += lib.einsum('klab,ikjl->ijab', l2bb, numpy.asarray(imds.wOOOO))
    m3ab += lib.einsum('kLaB,ikJL->iJaB', l2ab, numpy.asarray(imds.wooOO))

    ovov = numpy.asarray(eris.ovov)
    ovov = ovov - ovov.transpose(0,3,2,1)
    OVOV = numpy.asarray(eris.OVOV)
    OVOV = OVOV - OVOV.transpose(0,3,2,1)
    ovOV = numpy.asarray(eris.ovOV)
    mvv1 = einsum('jc,jb->bc', l1a, t1a) + mvv
    mVV1 = einsum('jc,jb->bc', l1b, t1b) + mVV
    moo1 = einsum('ic,kc->ik', l1a, t1a) + moo
    mOO1 = einsum('ic,kc->ik', l1b, t1b) + mOO
    if nvira > 0 and nocca > 0:
        ovvv = numpy.asarray(eris.get_ovvv())
        ovvv = ovvv - ovvv.transpose(0,3,2,1)
        tmp = lib.einsum('ijcd,kd->ijck', l2aa, t1a)
        m3aa -= lib.einsum('kbca,ijck->ijab', ovvv, tmp)

        tmp = einsum('ic,jbca->jiba', l1a, ovvv)
        tmp+= einsum('kiab,jk->ijab', l2aa, v2a)
        tmp-= einsum('ik,kajb->ijab', moo1, ovov)
        u2aa += tmp - tmp.transpose(1,0,2,3)
        u1a += numpy.einsum('iacb,bc->ia', ovvv, mvv1)
        ovvv = tmp = None

    if nvirb > 0 and noccb > 0:
        OVVV = numpy.asarray(eris.get_OVVV())
        OVVV = OVVV - OVVV.transpose(0,3,2,1)
        tmp = lib.einsum('ijcd,kd->ijck', l2bb, t1b)
        m3bb -= lib.einsum('kbca,ijck->ijab', OVVV, tmp)

        tmp = einsum('ic,jbca->jiba', l1b, OVVV)
        tmp+= einsum('kiab,jk->ijab', l2bb, v2b)
        tmp-= einsum('ik,kajb->ijab', mOO1, OVOV)
        u2bb += tmp - tmp.transpose(1,0,2,3)
        u1b += numpy.einsum('iaCB,BC->ia', OVVV, mVV1)
        OVVV = tmp = None

    if nvirb > 0 and nocca > 0:
        OVvv = numpy.asarray(eris.get_OVvv())
        tmp = lib.einsum('iJcD,KD->iJcK', l2ab, t1b)
        m3ab -= lib.einsum('KBca,iJcK->iJaB', OVvv, tmp)

        tmp = einsum('ic,JAcb->JibA', l1a, OVvv)
        tmp-= einsum('kIaB,jk->IjaB', l2ab, v2a)
        tmp-= einsum('IK,jaKB->IjaB', mOO1, ovOV)
        u2ab += tmp.transpose(1,0,2,3)
        u1b += numpy.einsum('iacb,bc->ia', OVvv, mvv1)
        OVvv = tmp = None

    if nvira > 0 and noccb > 0:
        ovVV = numpy.asarray(eris.get_ovVV())
        tmp = lib.einsum('iJdC,kd->iJCk', l2ab, t1a)
        m3ab -= lib.einsum('kaCB,iJCk->iJaB', ovVV, tmp)

        tmp = einsum('IC,jbCA->jIbA', l1b, ovVV)
        tmp-= einsum('iKaB,JK->iJaB', l2ab, v2b)
        tmp-= einsum('ik,kaJB->iJaB', moo1, ovOV)
        u2ab += tmp
        u1a += numpy.einsum('iaCB,BC->ia', ovVV, mVV1)
        ovVV = tmp = None

    tauaa, tauab, taubb = uccsd.make_tau(t2, t1, t1)
    tmp = lib.einsum('ijcd,klcd->ijkl', l2aa, tauaa)
    ovov = numpy.asarray(eris.ovov)
    ovov = ovov - ovov.transpose(0,3,2,1)
    m3aa += lib.einsum('kalb,ijkl->ijab', ovov, tmp) * .25

    tmp = lib.einsum('ijcd,klcd->ijkl', l2bb, taubb)
    OVOV = numpy.asarray(eris.OVOV)
    OVOV = OVOV - OVOV.transpose(0,3,2,1)
    m3bb += lib.einsum('kalb,ijkl->ijab', OVOV, tmp) * .25

    tmp = lib.einsum('iJcD,kLcD->iJkL', l2ab, tauab)
    ovOV = numpy.asarray(eris.ovOV)
    m3ab += lib.einsum('kaLB,iJkL->iJaB', ovOV, tmp) * .5
    tmp = lib.einsum('iJdC,lKdC->iJKl', l2ab, tauab)
    m3ab += lib.einsum('laKB,iJKl->iJaB', ovOV, tmp) * .5

    u1a += numpy.einsum('ijab,jb->ia', m3aa, t1a)
    u1a += numpy.einsum('iJaB,JB->ia', m3ab, t1b)
    u1b += numpy.einsum('IJAB,JB->IA', m3bb, t1b)
    u1b += numpy.einsum('jIbA,jb->IA', m3ab, t1a)

    u2aa += m3aa
    u2bb += m3bb
    u2ab += m3ab
    u2aa += ovov.transpose(0,2,1,3)
    u2bb += OVOV.transpose(0,2,1,3)
    u2ab += ovOV.transpose(0,2,1,3)

    fov1 = fova + numpy.einsum('kcjb,kc->jb', ovov, t1a)
    fov1+= numpy.einsum('jbKC,KC->jb', ovOV, t1b)
    tmp = numpy.einsum('ia,jb->ijab', l1a, fov1)
    tmp+= einsum('kica,jbck->ijab', l2aa, imds.wovvo)
    tmp+= einsum('iKaC,jbCK->ijab', l2ab, imds.wovVO)
    tmp = tmp - tmp.transpose(1,0,2,3)
    u2aa += tmp - tmp.transpose(0,1,3,2)

    fov1 = fovb + numpy.einsum('kcjb,kc->jb', OVOV, t1b)
    fov1+= numpy.einsum('kcJB,kc->JB', ovOV, t1a)
    tmp = numpy.einsum('ia,jb->ijab', l1b, fov1)
    tmp+= einsum('kica,jbck->ijab', l2bb, imds.wOVVO)
    tmp+= einsum('kIcA,JBck->IJAB', l2ab, imds.wOVvo)
    tmp = tmp - tmp.transpose(1,0,2,3)
    u2bb += tmp - tmp.transpose(0,1,3,2)

    fov1 = fovb + numpy.einsum('kcjb,kc->jb', OVOV, t1b)
    fov1+= numpy.einsum('kcJB,kc->JB', ovOV, t1a)
    u2ab += numpy.einsum('ia,JB->iJaB', l1a, fov1)
    u2ab += einsum('iKaC,JBCK->iJaB', l2ab, imds.wOVVO)
    u2ab += einsum('kica,JBck->iJaB', l2aa, imds.wOVvo)
    u2ab += einsum('kIaC,jBCk->jIaB', l2ab, imds.woVVo)
    u2ab += einsum('iKcA,JbcK->iJbA', l2ab, imds.wOvvO)
    fov1 = fova + numpy.einsum('kcjb,kc->jb', ovov, t1a)
    fov1+= numpy.einsum('jbKC,KC->jb', ovOV, t1b)
    u2ab += numpy.einsum('ia,jb->jiba', l1b, fov1)
    u2ab += einsum('kIcA,jbck->jIbA', l2ab, imds.wovvo)
    u2ab += einsum('KICA,jbCK->jIbA', l2bb, imds.wovVO)

    ovoo = numpy.asarray(eris.ovoo)
    ovoo = ovoo - ovoo.transpose(2,1,0,3)
    OVOO = numpy.asarray(eris.OVOO)
    OVOO = OVOO - OVOO.transpose(2,1,0,3)
    OVoo = numpy.asarray(eris.OVoo)
    ovOO = numpy.asarray(eris.ovOO)
    tmp = einsum('ka,jbik->ijab', l1a, ovoo)
    tmp+= einsum('ijca,cb->ijab', l2aa, v1a)
    tmp+= einsum('ca,icjb->ijab', mvv1, ovov)
    u2aa -= tmp - tmp.transpose(0,1,3,2)
    tmp = einsum('ka,jbik->ijab', l1b, OVOO)
    tmp+= einsum('ijca,cb->ijab', l2bb, v1b)
    tmp+= einsum('ca,icjb->ijab', mVV1, OVOV)
    u2bb -= tmp - tmp.transpose(0,1,3,2)
    u2ab -= einsum('ka,JBik->iJaB', l1a, OVoo)
    u2ab += einsum('iJaC,CB->iJaB', l2ab, v1b)
    u2ab -= einsum('ca,icJB->iJaB', mvv1, ovOV)
    u2ab -= einsum('KA,ibJK->iJbA', l1b, ovOO)
    u2ab += einsum('iJcA,cb->iJbA', l2ab, v1a)
    u2ab -= einsum('CA,ibJC->iJbA', mVV1, ovOV)

    u1a += fova
    u1b += fovb
    u1a += einsum('ib,ba->ia', l1a, v1a)
    u1a -= einsum('ja,ij->ia', l1a, v2a)
    u1b += einsum('ib,ba->ia', l1b, v1b)
    u1b -= einsum('ja,ij->ia', l1b, v2b)

    u1a += numpy.einsum('jb,iabj->ia', l1a, eris.ovvo)
    u1a -= numpy.einsum('jb,ijba->ia', l1a, eris.oovv)
    u1a += numpy.einsum('JB,iaBJ->ia', l1b, eris.ovVO)
    u1b += numpy.einsum('jb,iabj->ia', l1b, eris.OVVO)
    u1b -= numpy.einsum('jb,ijba->ia', l1b, eris.OOVV)
    u1b += numpy.einsum('jb,iabj->ia', l1a, eris.OVvo)

    u1a -= einsum('kjca,ijck->ia', l2aa, imds.woovo)
    u1a -= einsum('jKaC,ijCK->ia', l2ab, imds.wooVO)
    u1b -= einsum('kjca,ijck->ia', l2bb, imds.wOOVO)
    u1b -= einsum('kJcA,IJck->IA', l2ab, imds.wOOvo)

    u1a -= einsum('ikbc,back->ia', l2aa, imds.wvvvo)
    u1a -= einsum('iKbC,baCK->ia', l2ab, imds.wvvVO)
    u1b -= einsum('IKBC,BACK->IA', l2bb, imds.wVVVO)
    u1b -= einsum('kIcB,BAck->IA', l2ab, imds.wVVvo)

    u1a += numpy.einsum('jiba,bj->ia', l2aa, imds.w3a)
    u1a += numpy.einsum('iJaB,BJ->ia', l2ab, imds.w3b)
    u1b += numpy.einsum('JIBA,BJ->IA', l2bb, imds.w3b)
    u1b += numpy.einsum('jIbA,bj->IA', l2ab, imds.w3a)

    tmpa  = t1a + numpy.einsum('kc,kjcb->jb', l1a, t2aa)
    tmpa += numpy.einsum('KC,jKbC->jb', l1b, t2ab)
    tmpa -= einsum('bd,jd->jb', mvv1, t1a)
    tmpa -= einsum('lj,lb->jb', moo, t1a)
    tmpb  = t1b + numpy.einsum('kc,kjcb->jb', l1b, t2bb)
    tmpb += numpy.einsum('kc,kJcB->JB', l1a, t2ab)
    tmpb -= einsum('bd,jd->jb', mVV1, t1b)
    tmpb -= einsum('lj,lb->jb', mOO, t1b)
    u1a += numpy.einsum('jbia,jb->ia', ovov, tmpa)
    u1a += numpy.einsum('iaJB,JB->ia', ovOV, tmpb)
    u1b += numpy.einsum('jbia,jb->ia', OVOV, tmpb)
    u1b += numpy.einsum('jbIA,jb->IA', ovOV, tmpa)

    u1a -= numpy.einsum('iajk,kj->ia', ovoo, moo1)
    u1a -= numpy.einsum('iaJK,KJ->ia', ovOO, mOO1)
    u1b -= numpy.einsum('iajk,kj->ia', OVOO, mOO1)
    u1b -= numpy.einsum('IAjk,kj->IA', OVoo, moo1)

    tmp  = fova - numpy.einsum('kbja,jb->ka', ovov, t1a)
    tmp += numpy.einsum('kaJB,JB->ka', ovOV, t1b)
    u1a -= lib.einsum('ik,ka->ia', moo, tmp)
    u1a -= lib.einsum('ca,ic->ia', mvv, tmp)
    tmp  = fovb - numpy.einsum('kbja,jb->ka', OVOV, t1b)
    tmp += numpy.einsum('jbKA,jb->KA', ovOV, t1a)
    u1b -= lib.einsum('ik,ka->ia', mOO, tmp)
    u1b -= lib.einsum('ca,ic->ia', mVV, tmp)

    eia = lib.direct_sum('i-j->ij', mo_ea_o, mo_ea_v)
    eIA = lib.direct_sum('i-j->ij', mo_eb_o, mo_eb_v)
    u1a /= eia
    u1b /= eIA

    u2aa /= lib.direct_sum('ia+jb->ijab', eia, eia)
    u2ab /= lib.direct_sum('ia+jb->ijab', eia, eIA)
    u2bb /= lib.direct_sum('ia+jb->ijab', eIA, eIA)

    time0 = log.timer_debug1('update l1 l2', *time0)
    return (u1a,u1b), (u2aa,u2ab,u2bb)
Beispiel #51
0
    mf = x2c.RHF(mol).density_fit()
    dm = mf.get_init_guess() + 0.0j
    mf.with_df.auxbasis = 'def2-svp-jkfit'
    mf.kernel(dm)

    ncore = 2

    pt = MP2(mf)
    pt.frozen = ncore
    pt.kernel()
    rdm1 = pt.make_rdm1()
    rdm2 = pt.make_rdm2()

    n2c = mol.nao_2c()
    dferi = mf.with_df._cderi.reshape(-1,n2c,n2c)
    eri_mo = lib.einsum('rj,Qrs->Qjs', mf.mo_coeff.conj(), dferi)
    eri_mo = lib.einsum('sb,Qjs->Qjb', mf.mo_coeff, eri_mo)
    eri_mo = lib.einsum('Qia,Qjb->iajb', eri_mo, eri_mo)
    hcore = mf.get_hcore()
    h1 = reduce(numpy.dot, (mf.mo_coeff.T.conj(), hcore, mf.mo_coeff))
    e = numpy.einsum('ij,ji', h1, rdm1)
    e += numpy.einsum('ijkl,ijkl', eri_mo, rdm2)*0.5
    e += mol.energy_nuc()
    print("!*** E(X2CMP2) with RDM: %s" % e)

    mo_coeff, mo_energy, mo_occ = pt.fno()

    pt = MP2(mf, mo_coeff=mo_coeff, mo_occ=mo_occ)
    pt.frozen = ncore
    pt.kernel(mo_energy=mo_energy)
Beispiel #52
0
    mol = gto.Mole()
    mol.verbose = 0
    mol.atom = [
        [8 , (0. , 0.     , 0.)],
        [1 , (0. , -0.757 , 0.587)],
        [1 , (0. , 0.757  , 0.587)]]
    mol.basis = '631g'
    mol.build()
    mf = scf.RHF(mol)
    mf.conv_tol = 1e-16
    mf.scf()
    mo_coeff = mf.mo_coeff + np.sin(mf.mo_coeff) * .01j
    nao = mo_coeff.shape[0]
    eri = ao2mo.restore(1, mf._eri, nao)
    eri0 = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', eri, mo_coeff.conj(), mo_coeff,
                      mo_coeff.conj(), mo_coeff)

    nocc, nvir = 5, nao-5
    eris = _ChemistsERIs(mol)
    eris.oooo = eri0[:nocc,:nocc,:nocc,:nocc].copy()
    eris.ovoo = eri0[:nocc,nocc:,:nocc,:nocc].copy()
    eris.oovv = eri0[:nocc,:nocc,nocc:,nocc:].copy()
    eris.ovvo = eri0[:nocc,nocc:,nocc:,:nocc].copy()
    eris.ovov = eri0[:nocc,nocc:,:nocc,nocc:].copy()
    eris.ovvv = eri0[:nocc,nocc:,nocc:,nocc:].copy()
    eris.vvvv = eri0[nocc:,nocc:,nocc:,nocc:].copy()
    eris.fock = np.diag(mf.mo_energy)
    eris.mo_energy = mf.mo_energy

    np.random.seed(1)
    t1 = np.random.random((nocc,nvir)) + np.random.random((nocc,nvir))*.1j - .5
Beispiel #53
0
def contract(myci, civec, eris):
    time0 = time.clock(), time.time()
    log = logger.Logger(myci.stdout, myci.verbose)
    nocc = myci.nocc
    nmo = myci.nmo
    nvir = nmo - nocc
    nov = nocc * nvir
    noo = nocc**2
    c0, c1, c2 = myci.cisdvec_to_amplitudes(civec, nmo, nocc)

    t2 = myci._add_vvvv(c2, eris, t2sym='jiba')
    t2 *= .5  # due to t2+t2.transpose(1,0,3,2) in the end
    time1 = log.timer_debug1('vvvv', *time0)

    foo = eris.fock[:nocc, :nocc].copy()
    fov = eris.fock[:nocc, nocc:].copy()
    fvv = eris.fock[nocc:, nocc:].copy()

    t1 = fov * c0
    t1 += numpy.einsum('ib,ab->ia', c1, fvv)
    t1 -= numpy.einsum('ja,ji->ia', c1, foo)

    t2 += lib.einsum('kilj,klab->ijab', _cp(eris.oooo) * .5, c2)
    t2 += lib.einsum('ijac,bc->ijab', c2, fvv)
    t2 -= lib.einsum('kj,kiba->jiba', foo, c2)
    t2 += numpy.einsum('ia,jb->ijab', c1, fov)

    unit = nocc * nvir**2 + nocc**2 * nvir * 3 + 1
    max_memory = max(0, myci.max_memory - lib.current_memory()[0])
    blksize = min(nvir, max(BLKMIN, int(max_memory * .9e6 / 8 / unit)))
    log.debug1('max_memory %d MB,  nocc,nvir = %d,%d  blksize = %d',
               max_memory, nocc, nvir, blksize)
    nvir_pair = nvir * (nvir + 1) // 2
    for p0, p1 in lib.prange(0, nvir, blksize):
        eris_oVoV = _cp(_cp(eris.oovv[:, :, p0:p1]).transpose(0, 2, 1, 3))
        tmp = lib.einsum('kbjc,ikca->jiba', eris_oVoV, c2)
        t2[:, :, p0:p1] -= tmp * .5
        t2[:, :, p0:p1] -= tmp.transpose(1, 0, 2, 3)
        tmp = None

        eris_ovvo = _cp(eris.ovvo[:, p0:p1])
        t2[:, :, p0:p1] += eris_ovvo.transpose(0, 3, 1, 2) * (c0 * .5)
        t1 += numpy.einsum('ia,iabj->jb', c1[:, p0:p1], eris_ovvo) * 2
        t1[:, p0:p1] -= numpy.einsum('ib,iajb->ja', c1, eris_oVoV)

        ovov = -.5 * eris_oVoV
        ovov += eris_ovvo.transpose(3, 1, 0, 2)
        eris_oVoV = eris_oovv = None
        theta = c2[:, :, p0:p1].transpose(2, 0, 1, 3) * 2
        theta -= c2[:, :, p0:p1].transpose(2, 1, 0, 3)
        for j in range(nocc):
            t2[:, j] += lib.einsum('ckb,ckia->iab', ovov[j], theta)
        tmp = ovov = None

        t1 += numpy.einsum('aijb,ia->jb', theta, fov[:, p0:p1])

        eris_ovoo = _cp(eris.ovoo[:, p0:p1])
        t1 -= lib.einsum('bjka,jbki->ia', theta, eris_ovoo)
        t2[:, :, p0:p1] -= lib.einsum('jbik,ka->jiba', eris_ovoo.conj(), c1)
        eris_vooo = None

        eris_ovvv = eris.get_ovvv(slice(None), slice(p0, p1)).conj()
        t1 += lib.einsum('cjib,jcba->ia', theta, eris_ovvv)
        t2[:, :, p0:p1] += lib.einsum('iacb,jc->ijab', eris_ovvv, c1)
        tmp = eris_ovvv = None

    #:t2 + t2.transpose(1,0,3,2)
    for i in range(nocc):
        if i > 0:
            t2[i, :i] += t2[:i, i].transpose(0, 2, 1)
            t2[:i, i] = t2[i, :i].transpose(0, 2, 1)
        t2[i, i] = t2[i, i] + t2[i, i].T

    t0 = numpy.einsum('ia,ia->', fov, c1) * 2
    t0 += numpy.einsum('iabj,ijab->', eris.ovvo, c2) * 2
    t0 -= numpy.einsum('iabj,jiab->', eris.ovvo, c2)
    cinew = numpy.hstack((t0, t1.ravel(), t2.ravel()))
    return cinew
Beispiel #54
0
def update_amps(cc, t1, t2, eris):
    # Ref: Hirata et al., J. Chem. Phys. 120, 2581 (2004) Eqs.(35)-(36)
    assert(isinstance(eris, ccsd._ChemistsERIs))
    nocc, nvir = t1.shape
    fock = eris.fock
    mo_e_o = eris.mo_energy[:nocc]
    mo_e_v = eris.mo_energy[nocc:] + cc.level_shift

    fov = fock[:nocc,nocc:].copy()
    foo = fock[:nocc,:nocc].copy()
    fvv = fock[nocc:,nocc:].copy()

    Foo = imd.cc_Foo(t1,t2,eris)
    Fvv = imd.cc_Fvv(t1,t2,eris)
    Fov = imd.cc_Fov(t1,t2,eris)

    # Move energy terms to the other side
    Foo[np.diag_indices(nocc)] -= mo_e_o
    Fvv[np.diag_indices(nvir)] -= mo_e_v

    # T1 equation
    t1new  =-2*np.einsum('kc,ka,ic->ia', fov, t1, t1)
    t1new +=   np.einsum('ac,ic->ia', Fvv, t1)
    t1new +=  -np.einsum('ki,ka->ia', Foo, t1)
    t1new += 2*np.einsum('kc,kica->ia', Fov, t2)
    t1new +=  -np.einsum('kc,ikca->ia', Fov, t2)
    t1new +=   np.einsum('kc,ic,ka->ia', Fov, t1, t1)
    t1new += fov.conj()
    t1new += 2*np.einsum('kcai,kc->ia', eris.ovvo, t1)
    t1new +=  -np.einsum('kiac,kc->ia', eris.oovv, t1)
    eris_ovvv = np.asarray(eris.get_ovvv())
    t1new += 2*lib.einsum('kdac,ikcd->ia', eris_ovvv, t2)
    t1new +=  -lib.einsum('kcad,ikcd->ia', eris_ovvv, t2)
    t1new += 2*lib.einsum('kdac,kd,ic->ia', eris_ovvv, t1, t1)
    t1new +=  -lib.einsum('kcad,kd,ic->ia', eris_ovvv, t1, t1)
    eris_ovoo = np.asarray(eris.ovoo, order='C')
    t1new +=-2*lib.einsum('lcki,klac->ia', eris_ovoo, t2)
    t1new +=   lib.einsum('kcli,klac->ia', eris_ovoo, t2)
    t1new +=-2*lib.einsum('lcki,lc,ka->ia', eris_ovoo, t1, t1)
    t1new +=   lib.einsum('kcli,lc,ka->ia', eris_ovoo, t1, t1)

    # T2 equation
    tmp2  = lib.einsum('kibc,ka->abic', eris.oovv, -t1)
    tmp2 += np.asarray(eris_ovvv).conj().transpose(1,3,0,2)
    tmp = lib.einsum('abic,jc->ijab', tmp2, t1)
    t2new = tmp + tmp.transpose(1,0,3,2)
    tmp2  = lib.einsum('kcai,jc->akij', eris.ovvo, t1)
    tmp2 += eris_ovoo.transpose(1,3,0,2).conj()
    tmp = lib.einsum('akij,kb->ijab', tmp2, t1)
    t2new -= tmp + tmp.transpose(1,0,3,2)
    t2new += np.asarray(eris.ovov).conj().transpose(0,2,1,3)
    if cc.cc2:
        Woooo2 = np.asarray(eris.oooo).transpose(0,2,1,3).copy()
        Woooo2 += lib.einsum('lcki,jc->klij', eris_ovoo, t1)
        Woooo2 += lib.einsum('kclj,ic->klij', eris_ovoo, t1)
        Woooo2 += lib.einsum('kcld,ic,jd->klij', eris.ovov, t1, t1)
        t2new += lib.einsum('klij,ka,lb->ijab', Woooo2, t1, t1)
        Wvvvv = lib.einsum('kcbd,ka->abcd', eris_ovvv, -t1)
        Wvvvv = Wvvvv + Wvvvv.transpose(1,0,3,2)
        Wvvvv += np.asarray(eris.vvvv).transpose(0,2,1,3)
        t2new += lib.einsum('abcd,ic,jd->ijab', Wvvvv, t1, t1)
        Lvv2 = fvv - np.einsum('kc,ka->ac', fov, t1)
        Lvv2 -= np.diag(np.diag(fvv))
        tmp = lib.einsum('ac,ijcb->ijab', Lvv2, t2)
        t2new += (tmp + tmp.transpose(1,0,3,2))
        Loo2 = foo + np.einsum('kc,ic->ki', fov, t1)
        Loo2 -= np.diag(np.diag(foo))
        tmp = lib.einsum('ki,kjab->ijab', Loo2, t2)
        t2new -= (tmp + tmp.transpose(1,0,3,2))
    else:
        Loo = imd.Loo(t1, t2, eris)
        Lvv = imd.Lvv(t1, t2, eris)
        Loo[np.diag_indices(nocc)] -= mo_e_o
        Lvv[np.diag_indices(nvir)] -= mo_e_v

        Woooo = imd.cc_Woooo(t1, t2, eris)
        Wvoov = imd.cc_Wvoov(t1, t2, eris)
        Wvovo = imd.cc_Wvovo(t1, t2, eris)
        Wvvvv = imd.cc_Wvvvv(t1, t2, eris)

        tau = t2 + np.einsum('ia,jb->ijab', t1, t1)
        t2new += lib.einsum('klij,klab->ijab', Woooo, tau)
        t2new += lib.einsum('abcd,ijcd->ijab', Wvvvv, tau)
        tmp = lib.einsum('ac,ijcb->ijab', Lvv, t2)
        t2new += (tmp + tmp.transpose(1,0,3,2))
        tmp = lib.einsum('ki,kjab->ijab', Loo, t2)
        t2new -= (tmp + tmp.transpose(1,0,3,2))
        tmp  = 2*lib.einsum('akic,kjcb->ijab', Wvoov, t2)
        tmp -=   lib.einsum('akci,kjcb->ijab', Wvovo, t2)
        t2new += (tmp + tmp.transpose(1,0,3,2))
        tmp = lib.einsum('akic,kjbc->ijab', Wvoov, t2)
        t2new -= (tmp + tmp.transpose(1,0,3,2))
        tmp = lib.einsum('bkci,kjac->ijab', Wvovo, t2)
        t2new -= (tmp + tmp.transpose(1,0,3,2))

    eia = mo_e_o[:,None] - mo_e_v
    eijab = lib.direct_sum('ia,jb->ijab',eia,eia)
    t1new /= eia
    t2new /= eijab

    return t1new, t2new
Beispiel #55
0
def _gamma2_outcore(myci, civec, nmo, nocc, h5fobj, compress_vvvv=False):
    log = logger.Logger(myci.stdout, myci.verbose)
    nocc = myci.nocc
    nmo = myci.nmo
    nvir = nmo - nocc
    nvir_pair = nvir * (nvir + 1) // 2
    c0, c1, c2 = myci.cisdvec_to_amplitudes(civec, nmo, nocc)

    h5fobj['dovov'] = (2 * c0 * c2.conj().transpose(0, 2, 1, 3) -
                       c0 * c2.conj().transpose(1, 2, 0, 3))

    doooo = lib.einsum('ijab,klab->ijkl', c2.conj(), c2)
    h5fobj['doooo'] = doooo.transpose(0, 2, 1,
                                      3) - doooo.transpose(1, 2, 0, 3) * .5
    doooo = None

    dooov = -lib.einsum('ia,klac->klic', c1 * 2, c2.conj())
    h5fobj['dooov'] = dooov.transpose(0, 2, 1, 3) * 2 - dooov.transpose(
        1, 2, 0, 3)
    dooov = None

    #:dvovv = numpy.einsum('ia,ikcd->akcd', c1, c2) * 2
    #:dvvvv = lib.einsum('ijab,ijcd->abcd', c2, c2)
    max_memory = max(0, myci.max_memory - lib.current_memory()[0])
    unit = max(nocc**2 * nvir * 2 + nocc * nvir**2 * 3 + 1,
               nvir**3 * 2 + nocc * nvir**2 + 1)
    blksize = min(nvir, max(BLKMIN, int(max_memory * .9e6 / 8 / unit)))
    iobuflen = int(256e6 / 8 / blksize)
    log.debug1('rdm intermediates: block size = %d, nvir = %d in %d blocks',
               blksize, nocc, int((nvir + blksize - 1) / blksize))
    dtype = numpy.result_type(civec).char
    dovvv = h5fobj.create_dataset('dovvv', (nocc, nvir, nvir, nvir),
                                  dtype,
                                  chunks=(nocc, min(nocc, nvir), 1, nvir))
    if compress_vvvv:
        dvvvv = h5fobj.create_dataset('dvvvv', (nvir_pair, nvir_pair), dtype)
    else:
        dvvvv = h5fobj.create_dataset('dvvvv', (nvir, nvir, nvir, nvir), dtype)

    for istep, (p0, p1) in enumerate(lib.prange(0, nvir, blksize)):
        theta = c2[:, :, p0:p1] - c2[:, :, p0:p1].transpose(1, 0, 2, 3) * .5
        gvvvv = lib.einsum('ijab,ijcd->abcd', theta.conj(), c2)
        if compress_vvvv:
            # symmetrize dvvvv because it does not affect the results of cisd_grad
            # dvvvv = (dvvvv+dvvvv.transpose(0,1,3,2)) * .5
            # dvvvv = (dvvvv+dvvvv.transpose(1,0,2,3)) * .5
            # now dvvvv == dvvvv.transpose(0,1,3,2) == dvvvv.transpose(1,0,3,2)
            tmp = numpy.empty((nvir, nvir, nvir))
            tmpvvvv = numpy.empty((p1 - p0, nvir, nvir_pair))
            for i in range(p1 - p0):
                tmp[:] = gvvvv[i].conj().transpose(1, 0, 2)
                lib.pack_tril(tmp + tmp.transpose(0, 2, 1), out=tmpvvvv[i])
            # tril of (dvvvv[p0:p1,p0:p1]+dvvvv[p0:p1,p0:p1].T)
            for i in range(p0, p1):
                for j in range(p0, i):
                    tmpvvvv[i - p0, j] += tmpvvvv[j - p0, i]
                tmpvvvv[i - p0, i] *= 2
            for i in range(p1, nvir):
                off = i * (i + 1) // 2
                dvvvv[off + p0:off + p1] = tmpvvvv[:, i]
            for i in range(p0, p1):
                off = i * (i + 1) // 2
                if p0 > 0:
                    tmpvvvv[i - p0, :p0] += dvvvv[off:off + p0]
                dvvvv[off:off + i + 1] = tmpvvvv[i - p0, :i + 1] * .25
            tmp = tmpvvvv = None
        else:
            for i in range(p0, p1):
                dvvvv[i] = gvvvv[i - p0].conj().transpose(1, 0, 2)

        gvovv = numpy.einsum('ia,ikcd->akcd', c1[:, p0:p1].conj() * 2, c2)
        gvovv = gvovv.conj()
        dovvv[:, :, p0:p1] = gvovv.transpose(1, 3, 0, 2) * 2 - gvovv.transpose(
            1, 2, 0, 3)

    theta = c2 * 2 - c2.transpose(1, 0, 2, 3)
    doovv = numpy.einsum('ia,kc->ikca', c1.conj(), -c1)
    doovv -= lib.einsum('kjcb,kica->jiab', c2.conj(), theta)
    doovv -= lib.einsum('ikcb,jkca->ijab', c2.conj(), theta)
    h5fobj['doovv'] = doovv
    doovv = None

    dovvo = lib.einsum('ikac,jkbc->iabj', theta.conj(), theta)
    dovvo += numpy.einsum('ia,kc->iack', c1.conj(), c1) * 2
    h5fobj['dovvo'] = dovvo
    theta = dovvo = None

    dvvov = None
    return (h5fobj['dovov'], h5fobj['dvvvv'], h5fobj['doooo'], h5fobj['doovv'],
            h5fobj['dovvo'], dvvov, h5fobj['dovvv'], h5fobj['dooov'])
Beispiel #56
0
def update_lambda(mycc, t1, t2, l1, l2, eris=None, imds=None):
    if imds is None: imds = make_intermediates(mycc, t1, t2, eris)
    time0 = logger.process_clock(), logger.perf_counter()
    log = logger.Logger(mycc.stdout, mycc.verbose)
    nocc, nvir = t1.shape
    fov = eris.fock[:nocc, nocc:]
    mo_e_o = eris.mo_energy[:nocc]
    mo_e_v = eris.mo_energy[nocc:] + mycc.level_shift

    theta = t2 * 2 - t2.transpose(0, 1, 3, 2)
    mba = lib.einsum('klca,klcb->ba', l2, theta)
    mij = lib.einsum('ikcd,jkcd->ij', l2, theta)
    theta = None
    mba1 = numpy.einsum('jc,jb->bc', l1, t1) + mba
    mij1 = numpy.einsum('kb,jb->kj', l1, t1) + mij
    mia1 = t1 + numpy.einsum('kc,jkbc->jb', l1, t2) * 2
    mia1 -= numpy.einsum('kc,jkcb->jb', l1, t2)
    mia1 -= reduce(numpy.dot, (t1, l1.T, t1))
    mia1 -= numpy.einsum('bd,jd->jb', mba, t1)
    mia1 -= numpy.einsum('lj,lb->jb', mij, t1)

    l2new = mycc._add_vvvv(None, l2, eris, with_ovvv=False, t2sym='jiba')
    l1new = numpy.einsum('ijab,jb->ia', l2new, t1) * 2
    l1new -= numpy.einsum('jiab,jb->ia', l2new, t1)
    l2new *= .5  # *.5 because of l2+l2.transpose(1,0,3,2) in the end
    tmp = None

    w1 = imds.w1 - numpy.diag(mo_e_v)
    w2 = imds.w2 - numpy.diag(mo_e_o)

    l1new += fov
    l1new += numpy.einsum('ib,ba->ia', l1, w1)
    l1new -= numpy.einsum('ja,ij->ia', l1, w2)
    l1new -= numpy.einsum('ik,ka->ia', mij, imds.w4)
    l1new -= numpy.einsum('ca,ic->ia', mba, imds.w4)
    l1new += numpy.einsum('ijab,bj->ia', l2, imds.w3) * 2
    l1new -= numpy.einsum('ijba,bj->ia', l2, imds.w3)

    l2new += numpy.einsum('ia,jb->ijab', l1, imds.w4)
    l2new += lib.einsum('jibc,ca->jiba', l2, w1)
    l2new -= lib.einsum('jk,kiba->jiba', w2, l2)

    eris_ovoo = _cp(eris.ovoo)
    l1new -= numpy.einsum('iajk,kj->ia', eris_ovoo, mij1) * 2
    l1new += numpy.einsum('jaik,kj->ia', eris_ovoo, mij1)
    l2new -= lib.einsum('jbki,ka->jiba', eris_ovoo, l1)
    eris_ovoo = None

    tau = _ccsd.make_tau(t2, t1, t1)
    l2tau = lib.einsum('ijcd,klcd->ijkl', l2, tau)
    tau = None
    l2t1 = lib.einsum('jidc,kc->ijkd', l2, t1)

    max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
    unit = nocc * nvir**2 * 5
    blksize = min(nocc, max(ccsd.BLKMIN, int(max_memory * .95e6 / 8 / unit)))
    log.debug1('block size = %d, nocc = %d is divided into %d blocks', blksize,
               nocc, int((nocc + blksize - 1) / blksize))

    l1new -= numpy.einsum('jb,jiab->ia', l1, _cp(eris.oovv))
    for p0, p1 in lib.prange(0, nvir, blksize):
        eris_ovvv = eris.get_ovvv(slice(None), slice(p0, p1))
        l1new[:, p0:p1] += numpy.einsum('iabc,bc->ia', eris_ovvv, mba1) * 2
        l1new -= numpy.einsum('ibca,bc->ia', eris_ovvv, mba1[p0:p1])
        l2new[:, :, p0:p1] += lib.einsum('jbac,ic->jiba', eris_ovvv, l1)
        m4 = lib.einsum('ijkd,kadb->ijab', l2t1, eris_ovvv)
        l2new[:, :, p0:p1] -= m4
        l1new[:, p0:p1] -= numpy.einsum('ijab,jb->ia', m4, t1) * 2
        l1new -= numpy.einsum('ijab,ia->jb', m4, t1[:, p0:p1]) * 2
        l1new[:, p0:p1] += numpy.einsum('jiab,jb->ia', m4, t1)
        l1new += numpy.einsum('jiab,ia->jb', m4, t1[:, p0:p1])
        eris_ovvv = m4 = None

        eris_voov = _cp(eris.ovvo[:, p0:p1].transpose(1, 0, 3, 2))
        l1new[:, p0:p1] += numpy.einsum('jb,aijb->ia', l1, eris_voov) * 2
        l2new[:, :, p0:p1] += eris_voov.transpose(1, 2, 0, 3) * .5
        l2new[:, :, p0:p1] -= lib.einsum('bjic,ca->jiba', eris_voov, mba1)
        l2new[:, :, p0:p1] -= lib.einsum('bjka,ik->jiba', eris_voov, mij1)
        l1new[:, p0:p1] += numpy.einsum('aijb,jb->ia', eris_voov, mia1) * 2
        l1new -= numpy.einsum('bija,jb->ia', eris_voov, mia1[:, p0:p1])
        m4 = lib.einsum('ijkl,aklb->ijab', l2tau, eris_voov)
        l2new[:, :, p0:p1] += m4 * .5
        l1new[:, p0:p1] += numpy.einsum('ijab,jb->ia', m4, t1) * 2
        l1new -= numpy.einsum('ijba,jb->ia', m4, t1[:, p0:p1])

        saved_wvooo = _cp(imds.wvooo[p0:p1])
        l1new -= lib.einsum('ckij,jkca->ia', saved_wvooo, l2[:, :, p0:p1])
        saved_wvovv = _cp(imds.wvvov[p0:p1])
        # Watch out memory usage here, due to the l2 transpose
        l1new[:, p0:p1] += lib.einsum('abkc,kibc->ia', saved_wvovv, l2)
        saved_wvooo = saved_wvovv = None

        saved_wvOOv = _cp(imds.wvOOv[p0:p1])
        tmp_voov = _cp(imds.wVOov[p0:p1]) * 2
        tmp_voov += saved_wvOOv
        tmp = l2.transpose(0, 2, 1, 3) - l2.transpose(0, 3, 1, 2) * .5
        l2new[:, :, p0:p1] += lib.einsum('iakc,bjkc->jiba', tmp, tmp_voov)
        tmp = None

        tmp = lib.einsum('jkca,bikc->jiba', l2, saved_wvOOv)
        l2new[:, :, p0:p1] += tmp
        l2new[:, :, p0:p1] += tmp.transpose(1, 0, 2, 3) * .5
        saved_wvOOv = tmp = None

    saved_woooo = _cp(imds.woooo)
    m3 = lib.einsum('ijkl,klab->ijab', saved_woooo, l2)
    l2new += m3 * .5
    l1new += numpy.einsum('ijab,jb->ia', m3, t1) * 2
    l1new -= numpy.einsum('ijba,jb->ia', m3, t1)
    saved_woooo = m3 = None
    #time1 = log.timer_debug1('lambda pass [%d:%d]'%(p0, p1), *time1)

    eia = lib.direct_sum('i-a->ia', mo_e_o, mo_e_v)
    l1new /= eia

    #    l2new = l2new + l2new.transpose(1,0,3,2)
    #    l2new /= lib.direct_sum('ia+jb->ijab', eia, eia)
    #    l2new += l2
    for i in range(nocc):
        if i > 0:
            l2new[i, :i] += l2new[:i, i].transpose(0, 2, 1)
            l2new[i, :i] /= lib.direct_sum('a,jb->jab', eia[i], eia[:i])
            l2new[:i, i] = l2new[i, :i].transpose(0, 2, 1)
        l2new[i, i] = l2new[i, i] + l2new[i, i].T
        l2new[i, i] /= lib.direct_sum('a,b->ab', eia[i], eia[i])

    time0 = log.timer_debug1('update l1 l2', *time0)
    return l1new, l2new
Beispiel #57
0
def Lci_dot_dgci_dx(Lci,
                    weights,
                    mc,
                    mo_coeff=None,
                    ci=None,
                    atmlst=None,
                    mf_grad=None,
                    eris=None,
                    verbose=None):
    ''' Modification of pyscf.grad.casscf.kernel to compute instead the CI
    Lagrange term nuclear gradient (sum_IJ Lci_IJ d2_Ecas/d_lambda d_PIJ)
    This involves removing all core-core and nuclear-nuclear terms and making the substitution
    sum_I w_I<L_I|p'q|I> + c.c. -> <0|p'q|0>
    sum_I w_I<L_I|p'r'sq|I> + c.c. -> <0|p'r'sq|0>
    The active-core terms (sum_I w_I<L_I|x'iyi|I>, sum_I w_I <L_I|x'iiy|I>, c.c.) must be retained.'''
    if mo_coeff is None: mo_coeff = mc.mo_coeff
    if ci is None: ci = mc.ci
    if mf_grad is None: mf_grad = mc._scf.nuc_grad_method()
    if mc.frozen is not None:
        raise NotImplementedError

    t0 = (logger.process_clock(), logger.perf_counter())
    mol = mc.mol
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao + 1) // 2

    mo_occ = mo_coeff[:, :nocc]
    mo_core = mo_coeff[:, :ncore]
    mo_cas = mo_coeff[:, ncore:nocc]

    # MRH: TDMs + c.c. instead of RDMs; 06/30/2020: new interface in mcscf.addons makes this much more transparent
    casdm1, casdm2 = mc.fcisolver.trans_rdm12(Lci, ci, ncas, nelecas)
    casdm1 += casdm1.transpose(1, 0)
    casdm2 += casdm2.transpose(1, 0, 3, 2)

    # gfock = Generalized Fock, Adv. Chem. Phys., 69, 63
    dm_core = np.dot(mo_core, mo_core.T) * 2
    dm_cas = reduce(np.dot, (mo_cas, casdm1, mo_cas.T))
    aapa = np.zeros((ncas, ncas, nmo, ncas), dtype=dm_cas.dtype)
    for i in range(nmo):
        aapa[:, :, i, :] = eris.ppaa[i][ncore:nocc, :, :].transpose(1, 2, 0)
    vj, vk = mc._scf.get_jk(mol, (dm_core, dm_cas))
    h1 = mc.get_hcore()
    vhf_c = vj[0] - vk[0] * .5
    vhf_a = vj[1] - vk[1] * .5
    # MRH: delete h1 + vhf_c from the first line below (core and core-core stuff)
    # Also extend gfock to span the whole space
    gfock = np.zeros_like(dm_cas)
    gfock[:, :nocc] = reduce(np.dot, (mo_coeff.T, vhf_a, mo_occ)) * 2
    gfock[:, ncore:nocc] = reduce(np.dot,
                                  (mo_coeff.T, h1 + vhf_c, mo_cas, casdm1))
    gfock[:, ncore:nocc] += np.einsum('uvpw,vuwt->pt', aapa, casdm2)
    dme0 = reduce(np.dot, (mo_coeff, (gfock + gfock.T) * .5, mo_coeff.T))
    aapa = vj = vk = vhf_c = vhf_a = h1 = gfock = None

    vj, vk = mf_grad.get_jk(mol, (dm_core, dm_cas))
    vhf1c, vhf1a = vj - vk * 0.5
    #vhf1c, vhf1a = mf_grad.get_veff(mol, (dm_core, dm_cas))
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    diag_idx = np.arange(nao)
    diag_idx = diag_idx * (diag_idx + 1) // 2 + diag_idx
    casdm2_cc = casdm2 + casdm2.transpose(0, 1, 3, 2)
    dm2buf = ao2mo._ao2mo.nr_e2(casdm2_cc.reshape(ncas**2, ncas**2), mo_cas.T,
                                (0, nao, 0, nao)).reshape(ncas**2, nao, nao)
    dm2buf = lib.pack_tril(dm2buf)
    dm2buf[:, diag_idx] *= .5
    dm2buf = dm2buf.reshape(ncas, ncas, nao_pair)
    casdm2 = casdm2_cc = None

    if atmlst is None:
        atmlst = range(mol.natm)
    aoslices = mol.aoslice_by_atom()
    de_hcore = np.zeros((len(atmlst), 3))
    de_renorm = np.zeros((len(atmlst), 3))
    de_eri = np.zeros((len(atmlst), 3))
    de = np.zeros((len(atmlst), 3))

    max_memory = mc.max_memory - lib.current_memory()[0]
    blksize = int(max_memory * .9e6 / 8 /
                  (4 * (aoslices[:, 3] - aoslices[:, 2]).max() * nao_pair))
    # MRH: 3 components of eri array and 1 density matrix array: FOUR arrays of this size are required!
    blksize = min(nao, max(2, blksize))
    logger.info(
        mc,
        'SA-CASSCF Lci_dot_dgci memory remaining for eri manipulation: {} MB; using blocksize = {}'
        .format(max_memory, blksize))
    t0 = logger.timer(mc, 'SA-CASSCF Lci_dot_dgci 1-electron part', *t0)

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        h1ao = hcore_deriv(ia)
        # MRH: dm1 -> dm_cas in the line below
        de_hcore[k] += np.einsum('xij,ij->x', h1ao, dm_cas)
        de_renorm[k] -= np.einsum('xij,ij->x', s1[:, p0:p1], dme0[p0:p1]) * 2

        q1 = 0
        for b0, b1, nf in _shell_prange(mol, 0, mol.nbas, blksize):
            q0, q1 = q1, q1 + nf
            dm2_ao = lib.einsum('ijw,pi,qj->pqw', dm2buf, mo_cas[p0:p1],
                                mo_cas[q0:q1])
            shls_slice = (shl0, shl1, b0, b1, 0, mol.nbas, 0, mol.nbas)
            gc.collect()
            eri1 = mol.intor('int2e_ip1',
                             comp=3,
                             aosym='s2kl',
                             shls_slice=shls_slice).reshape(
                                 3, p1 - p0, nf, nao_pair)
            de_eri[k] -= np.einsum('xijw,ijw->x', eri1, dm2_ao) * 2
            eri1 = dm2_ao = None
            gc.collect()
            t0 = logger.timer(
                mc, 'SA-CASSCF Lci_dot_dgci atom {} ({},{}|{})'.format(
                    ia, p1 - p0, nf, nao_pair), *t0)
        # MRH: dm1 -> dm_cas in the line below. Also eliminate core-core terms
        de_eri[k] += np.einsum('xij,ij->x', vhf1c[:, p0:p1], dm_cas[p0:p1]) * 2
        de_eri[k] += np.einsum('xij,ij->x', vhf1a[:, p0:p1],
                               dm_core[p0:p1]) * 2

    logger.debug(mc, "CI lagrange hcore component:\n{}".format(de_hcore))
    logger.debug(mc, "CI lagrange renorm component:\n{}".format(de_renorm))
    logger.debug(mc, "CI lagrange eri component:\n{}".format(de_eri))
    de = de_hcore + de_renorm + de_eri
    return de
Beispiel #58
0
def make_intermediates(mycc, t1, t2, eris):
    log = logger.Logger(mycc.stdout, mycc.verbose)
    nocc, nvir = t1.shape
    foo = eris.fock[:nocc, :nocc]
    fov = eris.fock[:nocc, nocc:]
    #fvo = eris.fock[nocc:,:nocc]
    fvv = eris.fock[nocc:, nocc:]

    class _IMDS:
        pass

    imds = _IMDS()
    #TODO: mycc.incore_complete
    imds.ftmp = lib.H5TmpFile()
    imds.woooo = imds.ftmp.create_dataset('woooo', (nocc, nocc, nocc, nocc),
                                          'f8')
    imds.wvooo = imds.ftmp.create_dataset('wvooo', (nvir, nocc, nocc, nocc),
                                          'f8')
    imds.wVOov = imds.ftmp.create_dataset('wVOov', (nvir, nocc, nocc, nvir),
                                          'f8')
    imds.wvOOv = imds.ftmp.create_dataset('wvOOv', (nvir, nocc, nocc, nvir),
                                          'f8')
    imds.wvvov = imds.ftmp.create_dataset('wvvov', (nvir, nvir, nocc, nvir),
                                          'f8')

    w1 = fvv - numpy.einsum('ja,jb->ba', fov, t1)
    w2 = foo + numpy.einsum('ib,jb->ij', fov, t1)
    w3 = numpy.einsum('kc,jkbc->bj', fov, t2) * 2 + fov.T
    w3 -= numpy.einsum('kc,kjbc->bj', fov, t2)
    w3 += lib.einsum('kc,kb,jc->bj', fov, t1, t1)
    w4 = fov.copy()

    unit = nocc * nvir**2 * 6
    max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
    blksize = min(
        nvir,
        max(ccsd.BLKMIN,
            int((max_memory * .95e6 / 8 - nocc**4 - nvir * nocc**3) / unit)))
    log.debug1(
        'ccsd lambda make_intermediates: block size = %d, nvir = %d in %d blocks',
        blksize, nvir, int((nvir + blksize - 1) // blksize))

    fswap = lib.H5TmpFile()
    for istep, (p0, p1) in enumerate(lib.prange(0, nvir, blksize)):
        eris_ovvv = eris.get_ovvv(slice(None), slice(p0, p1))
        fswap['vvov/%d' % istep] = eris_ovvv.transpose(2, 3, 0, 1)

    woooo = 0
    wvooo = numpy.zeros((nvir, nocc, nocc, nocc))
    for p0, p1 in lib.prange(0, nvir, blksize):
        eris_ovvv = eris.get_ovvv(slice(None), slice(p0, p1))
        eris_vvov = numpy.empty(((p1 - p0), nvir, nocc, nvir))
        for istep, (q0, q1) in enumerate(lib.prange(0, nvir, blksize)):
            eris_vvov[:, :, :, q0:q1] = fswap['vvov/%d' % istep][p0:p1]

        w1 += numpy.einsum('jcba,jc->ba', eris_ovvv, t1[:, p0:p1] * 2)
        w1[:, p0:p1] -= numpy.einsum('jabc,jc->ba', eris_ovvv, t1)
        theta = t2[:, :, :, p0:p1] * 2 - t2[:, :, :, p0:p1].transpose(
            1, 0, 2, 3)
        w3 += lib.einsum('jkcd,kdcb->bj', theta, eris_ovvv)
        theta = None
        wVOov = lib.einsum('jbcd,kd->bjkc', eris_ovvv, t1)
        wvOOv = lib.einsum('cbjd,kd->cjkb', eris_vvov, -t1)
        g2vovv = eris_vvov.transpose(0, 2, 1, 3) * 2 - eris_vvov.transpose(
            0, 2, 3, 1)
        for i0, i1 in lib.prange(0, nocc, blksize):
            tau = t2[:, i0:i1] + numpy.einsum('ia,jb->ijab', t1, t1[i0:i1])
            wvooo[p0:p1, i0:i1] += lib.einsum('cibd,jkbd->ckij', g2vovv, tau)
        g2vovv = tau = None

        # Watch out memory usage here, due to the t2 transpose
        wvvov = lib.einsum('jabd,jkcd->abkc', eris_ovvv, t2) * -1.5
        wvvov += eris_vvov.transpose(0, 3, 2, 1) * 2
        wvvov -= eris_vvov

        g2vvov = eris_vvov * 2 - eris_ovvv.transpose(1, 2, 0, 3)
        for i0, i1 in lib.prange(0, nocc, blksize):
            theta = t2[i0:i1] * 2 - t2[i0:i1].transpose(0, 1, 3, 2)
            vackb = lib.einsum('acjd,kjbd->ackb', g2vvov, theta)
            wvvov[:, :, i0:i1] += vackb.transpose(0, 3, 2, 1)
            wvvov[:, :, i0:i1] -= vackb * .5
        g2vvov = eris_ovvv = eris_vvov = theta = None

        eris_ovoo = _cp(eris.ovoo[:, p0:p1])
        w2 += numpy.einsum('kbij,kb->ij', eris_ovoo, t1[:, p0:p1]) * 2
        w2 -= numpy.einsum('ibkj,kb->ij', eris_ovoo, t1[:, p0:p1])
        theta = t2[:, :, p0:p1].transpose(1, 0, 2, 3) * 2 - t2[:, :, p0:p1]
        w3 -= lib.einsum('lckj,klcb->bj', eris_ovoo, theta)

        tmp = lib.einsum('lc,jcik->ijkl', t1[:, p0:p1], eris_ovoo)
        woooo += tmp
        woooo += tmp.transpose(1, 0, 3, 2)
        theta = tmp = None

        wvOOv += lib.einsum('lbjk,lc->bjkc', eris_ovoo, t1)
        wVOov -= lib.einsum('jbkl,lc->bjkc', eris_ovoo, t1)
        wvooo[p0:p1] += eris_ovoo.transpose(1, 3, 2, 0) * 2
        wvooo[p0:p1] -= eris_ovoo.transpose(1, 0, 2, 3)
        wvooo -= lib.einsum('klbc,iblj->ckij', t2[:, :, p0:p1],
                            eris_ovoo * 1.5)

        g2ovoo = eris_ovoo * 2 - eris_ovoo.transpose(2, 1, 0, 3)
        theta = t2[:, :, :, p0:p1] * 2 - t2[:, :, :, p0:p1].transpose(
            1, 0, 2, 3)
        vcjik = lib.einsum('jlcb,lbki->cjki', theta, g2ovoo)
        wvooo += vcjik.transpose(0, 3, 2, 1)
        wvooo -= vcjik * .5
        theta = g2ovoo = None

        eris_voov = _cp(eris.ovvo[:, p0:p1]).transpose(1, 0, 3, 2)
        tau = t2[:, :, p0:p1] + numpy.einsum('ia,jb->ijab', t1[:, p0:p1], t1)
        woooo += lib.einsum('cijd,klcd->ijkl', eris_voov, tau)
        tau = None

        g2voov = eris_voov * 2 - eris_voov.transpose(0, 2, 1, 3)
        tmpw4 = numpy.einsum('ckld,ld->kc', g2voov, t1)
        w1 -= lib.einsum('ckja,kjcb->ba', g2voov, t2[:, :, p0:p1])
        w1[:, p0:p1] -= numpy.einsum('ja,jb->ba', tmpw4, t1)
        w2 += lib.einsum('jkbc,bikc->ij', t2[:, :, p0:p1], g2voov)
        w2 += numpy.einsum('ib,jb->ij', tmpw4, t1[:, p0:p1])
        w3 += reduce(numpy.dot, (t1.T, tmpw4, t1[:, p0:p1].T))
        w4[:, p0:p1] += tmpw4

        wvOOv += lib.einsum('bljd,kd,lc->bjkc', eris_voov, t1, t1)
        wVOov -= lib.einsum('bjld,kd,lc->bjkc', eris_voov, t1, t1)

        VOov = lib.einsum('bjld,klcd->bjkc', g2voov, t2)
        VOov -= lib.einsum('bjld,kldc->bjkc', eris_voov, t2)
        VOov += eris_voov
        vOOv = lib.einsum('bljd,kldc->bjkc', eris_voov, t2)
        vOOv -= _cp(eris.oovv[:, :, p0:p1]).transpose(2, 1, 0, 3)
        wVOov += VOov
        wvOOv += vOOv
        imds.wVOov[p0:p1] = wVOov
        imds.wvOOv[p0:p1] = wvOOv

        ov1 = vOOv * 2 + VOov
        ov2 = VOov * 2 + vOOv
        vOOv = VOov = None
        wvooo -= lib.einsum('jb,bikc->ckij', t1[:, p0:p1], ov1)
        wvooo += lib.einsum('kb,bijc->ckij', t1[:, p0:p1], ov2)
        w3 += numpy.einsum('ckjb,kc->bj', ov2, t1[:, p0:p1])

        wvvov += lib.einsum('ajkc,jb->abkc', ov1, t1)
        wvvov -= lib.einsum('ajkb,jc->abkc', ov2, t1)

        eris_ovoo = _cp(eris.ovoo[:, p0:p1])
        g2ovoo = eris_ovoo * 2 - eris_ovoo.transpose(2, 1, 0, 3)
        tau = t2 + numpy.einsum('ia,jb->ijab', t1, t1)
        wvvov += lib.einsum('laki,klbc->abic', g2ovoo, tau)
        imds.wvvov[p0:p1] = wvvov
        wvvov = ov1 = ov2 = g2ovoo = None

    woooo += _cp(eris.oooo).transpose(0, 2, 1, 3)
    imds.woooo[:] = woooo
    imds.wvooo[:] = wvooo
    woooo = wvooo = None

    w3 += numpy.einsum('bc,jc->bj', w1, t1)
    w3 -= numpy.einsum('kj,kb->bj', w2, t1)

    fswap = None

    imds.w1 = w1
    imds.w2 = w2
    imds.w3 = w3
    imds.w4 = w4
    imds.ftmp.flush()
    return imds
Beispiel #59
0
def grad_elec_auxresponse_dferi (mc_grad, mo_cas=None, ci=None, dfcasdm2=None, casdm2=None, atmlst=None, max_memory=None, dferi=None, incl_2c=True):
    ''' Evaluate the [(P'|ij) + (P'|Q) g_Qij] d_Pij contribution to the electronic gradient, where d_Pij is
    the DF-2RDM obtained by solve_df_rdm2 and g_Qij solves (P|Q) g_Qij = (P|ij). The caller must symmetrize
    if necessary (i.e., (P|Q) d_Qij = (P|kl) d_ijkl <-> (P|Q) d_Qkl = (P|ij) d_ijkl in order to get at Q').
    Args:
        mc_grad: MC-SCF gradients method object

    Kwargs:
        mc_cas: ndarray, list, or tuple containing active-space MO coefficients
            If a tuple of length 2, the same pair of MO sets are assumed to apply to
            the internally-contracted and externally-contracted indices of the DF-2rdm:
            (P|Q)d_Qij = (P|kl)d_ijkl -> (P|Q)d_Qij = (P|ij)d_ijij
            If a tuple of length 4, the 4 MO sets are applied to ijkl above in that order
            (first two external, last two internal).
        ci: ndarray, tuple, or list containing CI coefficients in mo_cas basis.
            Not used if dfcasdm2 is provided.
        dfcasdm2: ndarray, tuple, or list containing DF-2rdm in mo_cas basis.
            Computed by solve_df_rdm2 if omitted.
        casdm2: ndarray, tuple, or list containing rdm2 in mo_cas basis.
            Computed by mc_grad.fcisolver.make_rdm12 (ci,...) if omitted.
        atmlst: list of integers
            List of nonfrozen atoms, as in grad_elec functions.
            Defaults to list (range (mol.natm))
        max_memory: int
            Maximum memory usage in MB
        dferi: ndarray containing g_Pij for optional precalculation
        incl_2c: bool
            If False, omit the terms depending on (P'|Q)

    Returns:
        dE: list of ndarray of shape (len (atmlst), 3) '''

    if isinstance (mc_grad, GradientsBasics):
        mc = mc_grad.base
    else:
        mc = mc_grad
    mol = mc_grad.mol
    auxmol = mc.with_df.auxmol
    ncore, ncas, nao, naux, nbas = mc.ncore, mc.ncas, mol.nao, auxmol.nao, mol.nbas
    nocc = ncore + ncas
    npair = nao * (nao + 1) // 2
    if mo_cas is None: mo_cas = mc.mo_coeff[:,ncore:nocc]
    if max_memory is None: max_memory = mc.max_memory
    if isinstance (mo_cas, np.ndarray) and mo_cas.ndim == 2:
        mo_cas = (mo_cas,)*4
    elif len (mo_cas) == 2:
        mo_cas = (mo_cas[0], mo_cas[1], mo_cas[0], mo_cas[1])
    elif len (mo_cas) == 4:
        mo_cas = tuple (mo_cas)
    else:
        raise RuntimeError ('Invalid shape of np.asarray (mo_cas): {}'.format (mo_cas.shape))
    nmo = [mo.shape[1] for mo in mo_cas]
    if atmlst is None: atmlst = list (range (mol.natm))
    if ci is None: ci = mc.ci
    if dfcasdm2 is None: dfcasdm2 = solve_df_rdm2 (mc, mo_cas=mo_cas[2:], ci=ci, casdm2=casdm2) # d_Pij = (P|Q)^{-1} (Q|kl) d_ijkl
    nset = len (dfcasdm2)
    dE = np.zeros ((nset, naux, 3))
    dfcasdm2 = np.array (dfcasdm2)

    # Shape dfcasdm2
    mosym, nmo_pair, mo_conc, mo_slice = _conc_mos(mo_cas[0], mo_cas[1], compact=True)
    if 's2' in mosym:
        assert (nmo[0] == nmo[1]), 'How did I get {} with nmo[0] = {} and nmo[1] = {}'.format (mosym, nmo[0], nmo[1])
        dfcasdm2 = dfcasdm2.reshape (nset*naux, nmo[0], nmo[1])
        dfcasdm2 += dfcasdm2.transpose (0,2,1)
        diag_idx = np.arange(nmo[0])
        diag_idx = diag_idx * (diag_idx+1) // 2 + diag_idx
        dfcasdm2 = lib.pack_tril (np.ascontiguousarray (dfcasdm2))
        dfcasdm2[:,diag_idx] *= 0.5
    dfcasdm2 = dfcasdm2.reshape (nset, naux, nmo_pair)

    # Do 2c part. Assume memory is no object
    if incl_2c: 
        int2c = auxmol.intor('int2c2e_ip1')
        if (dferi is None): dferi = solve_df_eri (mc, mo_cas=mo_cas[:2]).reshape (naux, nmo_pair) # g_Pij = (P|Q)^{-1} (Q|ij)
        int3c = np.dot (int2c, dferi) # (P'|Q) g_Qij
        dE += lib.einsum ('npi,xpi->npx', dfcasdm2, int3c) # d_Pij (P'|Q) g_Qij
        int2c = int3c = dferi = None

    # Set up 3c part
    get_int3c = _int3c_wrapper(mol, auxmol, 'int3c2e_ip2', 's2ij')
    max_memory -= lib.current_memory()[0]  
    blklen = 6*npair
    blksize = int (min (max (max_memory * 1e6 / 8 / blklen, 20), 240))
    aux_loc = auxmol.ao_loc
    aux_ranges = balance_partition(aux_loc, blksize)

    # Iterate over auxbasis range and do 3c part
    for shl0, shl1, nL in aux_ranges:
        p0, p1 = aux_loc[shl0], aux_loc[shl1]
        int3c = get_int3c ((0, nbas, 0, nbas, shl0, shl1))  # (uv|P'); shape = (3,npair,p1-p0)
        int3c = np.ascontiguousarray (int3c.transpose (0,2,1).reshape (3*(p1-p0), npair))
        int3c = _ao2mo.nr_e2(int3c, mo_conc, mo_slice, aosym='s2', mosym=mosym)
        int3c = int3c.reshape (3,p1-p0,nmo_pair)
        int3c = np.ascontiguousarray (int3c)
        dE[:,p0:p1,:] -= lib.einsum ('npi,xpi->npx', dfcasdm2[:,p0:p1,:], int3c)

    # Ravel to atoms
    auxslices = auxmol.aoslice_by_atom ()
    dE = np.array ([dE[:,p0:p1].sum (axis=1) for p0, p1 in auxslices[:,2:]]).transpose (1,0,2)
    return np.ascontiguousarray (dE)
Beispiel #60
0
def Lorb_dot_dgorb_dx(Lorb,
                      mc,
                      mo_coeff=None,
                      ci=None,
                      atmlst=None,
                      mf_grad=None,
                      eris=None,
                      verbose=None):
    ''' Modification of pyscf.grad.casscf.kernel to compute instead the orbital
    Lagrange term nuclear gradient (sum_pq Lorb_pq d2_Ecas/d_lambda d_kpq)
    This involves removing nuclear-nuclear terms and making the substitution
    (D_[p]q + D_p[q]) -> D_pq
    (d_[p]qrs + d_pq[r]s + d_p[q]rs + d_pqr[s]) -> d_pqrs
    Where [] around an index implies contraction with Lorb from the left, so that the external index
    (regardless of whether the index on the rdm is bra or ket) is always the first index of Lorb. '''

    # dmo = smoT.dao.smo
    # dao = mo.dmo.moT
    t0 = (logger.process_clock(), logger.perf_counter())

    if mo_coeff is None: mo_coeff = mc.mo_coeff
    if ci is None: ci = mc.ci
    if mf_grad is None: mf_grad = mc._scf.nuc_grad_method()
    if mc.frozen is not None:
        raise NotImplementedError

    mol = mc.mol
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao + 1) // 2

    mo_core = mo_coeff[:, :ncore]
    mo_cas = mo_coeff[:, ncore:nocc]

    # MRH: new 'effective' MO coefficients including contraction from the Lagrange multipliers
    moL_coeff = np.dot(mo_coeff, Lorb)
    s0_inv = np.dot(mo_coeff, mo_coeff.T)
    moL_core = moL_coeff[:, :ncore]
    moL_cas = moL_coeff[:, ncore:nocc]

    # MRH: these SHOULD be state-averaged! Use the actual sacasscf object!
    casdm1, casdm2 = mc.fcisolver.make_rdm12(ci, ncas, nelecas)

    # gfock = Generalized Fock, Adv. Chem. Phys., 69, 63
    # MRH: each index exactly once!
    dm_core = np.dot(mo_core, mo_core.T) * 2
    dm_cas = reduce(np.dot, (mo_cas, casdm1, mo_cas.T))
    # MRH: new density matrix terms
    dmL_core = np.dot(moL_core, mo_core.T) * 2
    dmL_cas = reduce(np.dot, (moL_cas, casdm1, mo_cas.T))
    dmL_core += dmL_core.T
    dmL_cas += dmL_cas.T
    dm1 = dm_core + dm_cas
    dm1L = dmL_core + dmL_cas
    # MRH: end new density matrix terms
    # MRH: wrap the integral instead of the density matrix. I THINK the sign is the same!
    # mo sets 0 and 2 should be transposed, 1 and 3 should be not transposed; this will lead to correct sign
    # Except I can't do this for the external index, because the external index is contracted to ovlp matrix,
    # not the 2RDM
    aapa = np.zeros((ncas, ncas, nmo, ncas), dtype=dm_cas.dtype)
    aapaL = np.zeros((ncas, ncas, nmo, ncas), dtype=dm_cas.dtype)
    for i in range(nmo):
        jbuf = eris.ppaa[i]
        kbuf = eris.papa[i]
        aapa[:, :, i, :] = jbuf[ncore:nocc, :, :].transpose(1, 2, 0)
        aapaL[:, :, i, :] += np.tensordot(jbuf,
                                          Lorb[:, ncore:nocc],
                                          axes=((0), (0)))
        kbuf = np.tensordot(kbuf, Lorb[:, ncore:nocc],
                            axes=((1), (0))).transpose(1, 2, 0)
        aapaL[:, :, i, :] += kbuf + kbuf.transpose(1, 0, 2)
    # MRH: new vhf terms
    vj, vk = mc._scf.get_jk(mol, (dm_core, dm_cas))
    vjL, vkL = mc._scf.get_jk(mol, (dmL_core, dmL_cas))
    h1 = mc.get_hcore()
    vhf_c = vj[0] - vk[0] * .5
    vhf_a = vj[1] - vk[1] * .5
    vhfL_c = vjL[0] - vkL[0] * .5
    vhfL_a = vjL[1] - vkL[1] * .5
    # MRH: I rewrote this Feff calculation completely, double-check it
    gfock = np.dot(h1, dm1L)  # h1e
    gfock += np.dot((vhf_c + vhf_a),
                    dmL_core)  # core-core and active-core, 2nd 1RDM linked
    gfock += np.dot((vhfL_c + vhfL_a),
                    dm_core)  # core-core and active-core, 1st 1RDM linked
    gfock += np.dot(vhfL_c, dm_cas)  # core-active, 1st 1RDM linked
    gfock += np.dot(vhf_c, dmL_cas)  # core-active, 2nd 1RDM linked
    gfock = np.dot(
        s0_inv, gfock
    )  # Definition of quantity is in MO's; going (AO->MO->AO) incurs an inverse ovlp
    gfock += reduce(np.dot, (mo_coeff, np.einsum(
        'uviw,uvtw->it', aapaL, casdm2), mo_cas.T))  # active-active
    # MRH: I have to contract this external 2RDM index explicitly on the 2RDM but fortunately I can do so here
    gfock += reduce(
        np.dot,
        (mo_coeff, np.einsum('uviw,vuwt->it', aapa, casdm2), moL_cas.T))
    # MRH: As of 04/18/2019, the two-body part of this is including aapaL is definitely, unambiguously correct
    dme0 = (gfock +
            gfock.T) / 2  # This transpose is for the overlap matrix later on
    aapa = vj = vk = vhf_c = vhf_a = None

    vj, vk = mf_grad.get_jk(mol, (dm_core, dm_cas, dmL_core, dmL_cas))
    vhf1c, vhf1a, vhf1cL, vhf1aL = vj - vk * 0.5
    #vhf1c, vhf1a, vhf1cL, vhf1aL = mf_grad.get_veff(mol, (dm_core, dm_cas, dmL_core, dmL_cas))
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    diag_idx = np.arange(nao)
    diag_idx = diag_idx * (diag_idx + 1) // 2 + diag_idx
    casdm2_cc = casdm2 + casdm2.transpose(0, 1, 3, 2)
    dm2buf = ao2mo._ao2mo.nr_e2(casdm2_cc.reshape(ncas**2, ncas**2), mo_cas.T,
                                (0, nao, 0, nao)).reshape(ncas**2, nao, nao)
    # MRH: contract the final two indices of the active-active 2RDM with L as you change to AOs
    # note tensordot always puts indices in the order of the arguments.
    dm2Lbuf = np.zeros((ncas**2, nmo, nmo))
    # MRH: The second line below transposes the L; the third line transposes the derivative later on
    # Both the L and the derivative have to explore all indices
    dm2Lbuf[:, :, ncore:nocc] = np.tensordot(
        Lorb[:, ncore:nocc], casdm2,
        axes=(1, 2)).transpose(1, 2, 0, 3).reshape(ncas**2, nmo, ncas)
    dm2Lbuf[:, ncore:nocc, :] += np.tensordot(
        Lorb[:, ncore:nocc], casdm2,
        axes=(1, 3)).transpose(1, 2, 3, 0).reshape(ncas**2, ncas, nmo)
    dm2Lbuf += dm2Lbuf.transpose(0, 2, 1)
    dm2Lbuf = np.ascontiguousarray(dm2Lbuf)
    dm2Lbuf = ao2mo._ao2mo.nr_e2(dm2Lbuf.reshape(ncas**2, nmo**2), mo_coeff.T,
                                 (0, nao, 0, nao)).reshape(ncas**2, nao, nao)
    dm2buf = lib.pack_tril(dm2buf)
    dm2buf[:, diag_idx] *= .5
    dm2buf = dm2buf.reshape(ncas, ncas, nao_pair)
    dm2Lbuf = lib.pack_tril(dm2Lbuf)
    dm2Lbuf[:, diag_idx] *= .5
    dm2Lbuf = dm2Lbuf.reshape(ncas, ncas, nao_pair)

    if atmlst is None:
        atmlst = list(range(mol.natm))
    aoslices = mol.aoslice_by_atom()
    de_hcore = np.zeros((len(atmlst), 3))
    de_renorm = np.zeros((len(atmlst), 3))
    de_eri = np.zeros((len(atmlst), 3))
    de = np.zeros((len(atmlst), 3))

    max_memory = mc.max_memory - lib.current_memory()[0]
    blksize = int(max_memory * .9e6 / 8 /
                  (4 * (aoslices[:, 3] - aoslices[:, 2]).max() * nao_pair))
    # MRH: 3 components of eri array and 1 density matrix array: FOUR arrays of this size are required!
    blksize = min(nao, max(2, blksize))
    logger.info(
        mc,
        'SA-CASSCF Lorb_dot_dgorb memory remaining for eri manipulation: {} MB; using blocksize = {}'
        .format(max_memory, blksize))
    t0 = logger.timer(mc, 'SA-CASSCF Lorb_dot_dgorb 1-electron part', *t0)

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        h1ao = hcore_deriv(ia)
        # MRH: h1e and Feff terms
        de_hcore[k] += np.einsum('xij,ij->x', h1ao, dm1L)
        de_renorm[k] -= np.einsum('xij,ij->x', s1[:, p0:p1], dme0[p0:p1]) * 2

        q1 = 0
        for b0, b1, nf in _shell_prange(mol, 0, mol.nbas, blksize):
            q0, q1 = q1, q1 + nf
            dm2_ao = lib.einsum('ijw,pi,qj->pqw', dm2Lbuf, mo_cas[p0:p1],
                                mo_cas[q0:q1])
            # MRH: now contract the first two indices of the active-active 2RDM with L as you go from MOs to AOs
            dm2_ao += lib.einsum('ijw,pi,qj->pqw', dm2buf, moL_cas[p0:p1],
                                 mo_cas[q0:q1])
            dm2_ao += lib.einsum('ijw,pi,qj->pqw', dm2buf, mo_cas[p0:p1],
                                 moL_cas[q0:q1])
            shls_slice = (shl0, shl1, b0, b1, 0, mol.nbas, 0, mol.nbas)
            gc.collect()
            eri1 = mol.intor('int2e_ip1',
                             comp=3,
                             aosym='s2kl',
                             shls_slice=shls_slice).reshape(
                                 3, p1 - p0, nf, nao_pair)
            # MRH: I still don't understand why there is a minus here!
            de_eri[k] -= np.einsum('xijw,ijw->x', eri1, dm2_ao) * 2
            eri1 = dm2_ao = None
            gc.collect()
            t0 = logger.timer(
                mc, 'SA-CASSCF Lorb_dot_dgorb atom {} ({},{}|{})'.format(
                    ia, p1 - p0, nf, nao_pair), *t0)
        # MRH: core-core and core-active 2RDM terms
        de_eri[k] += np.einsum('xij,ij->x', vhf1c[:, p0:p1], dm1L[p0:p1]) * 2
        de_eri[k] += np.einsum('xij,ij->x', vhf1cL[:, p0:p1], dm1[p0:p1]) * 2
        # MRH: active-core 2RDM terms
        de_eri[k] += np.einsum('xij,ij->x', vhf1a[:, p0:p1],
                               dmL_core[p0:p1]) * 2
        de_eri[k] += np.einsum('xij,ij->x', vhf1aL[:, p0:p1],
                               dm_core[p0:p1]) * 2

    # MRH: deleted the nuclear-nuclear part to avoid double-counting
    # lesson learned from debugging - mol.intor computes -1 * the derivative and only
    # for one index
    # on the other hand, mf_grad.hcore_generator computes the actual derivative of
    # h1 for both indices and with the correct sign

    logger.debug(mc, "Orb lagrange hcore component:\n{}".format(de_hcore))
    logger.debug(mc, "Orb lagrange renorm component:\n{}".format(de_renorm))
    logger.debug(mc, "Orb lagrange eri component:\n{}".format(de_eri))
    de = de_hcore + de_renorm + de_eri

    return de