def test_rdm(self):
        mycc = rccsd.RCCSD(mf)
        mycc.frozen = 1
        mycc.kernel()
        dm1 = mycc.make_rdm1()
        dm2 = mycc.make_rdm2()
        h1 = reduce(numpy.dot, (mf.mo_coeff.T, mf.get_hcore(), mf.mo_coeff))
        nmo = mf.mo_coeff.shape[1]
        eri = ao2mo.restore(1, ao2mo.kernel(mf._eri, mf.mo_coeff), nmo)
        e1 = numpy.einsum('ij,ji', h1, dm1)
        e1 += numpy.einsum('ijkl,ijkl', eri, dm2) * .5
        e1 += mol.energy_nuc()
        self.assertAlmostEqual(e1, mycc.e_tot, 7)

        d1 = ccsd_rdm._gamma1_intermediates(mycc, mycc.t1, mycc.t2, mycc.l1,
                                            mycc.l2)
        mycc1 = copy.copy(mycc)
        mycc1.max_memory = 0
        d2 = ccsd_rdm._gamma2_intermediates(mycc1, mycc.t1, mycc.t2, mycc.l1,
                                            mycc.l2, True)
        dm2 = ccsd_rdm._make_rdm2(mycc,
                                  d1,
                                  d2,
                                  with_dm1=True,
                                  with_frozen=True)
        e1 = numpy.einsum('ij,ji', h1, dm1)
        e1 += numpy.einsum('ijkl,ijkl', eri, dm2) * .5
        e1 += mol.energy_nuc()
        self.assertAlmostEqual(e1, mycc.e_tot, 7)
Exemple #2
0
def _gamma1_intermediates(cc, t1, t2, l1, l2):
    d1 = ccsd_rdm._gamma1_intermediates(cc, t1, t2, l1, l2)
    if cc.frozen is None or cc.frozen is 0:
        return d1
    nocc = numpy.count_nonzero(cc.mo_occ > 0)
    nvir = cc.mo_occ.size - nocc
    OA, VA, OF, VF = index_frozen_active(cc)
    doo = numpy.zeros((nocc, nocc))
    dov = numpy.zeros((nocc, nvir))
    dvo = numpy.zeros((nvir, nocc))
    dvv = numpy.zeros((nvir, nvir))
    doo[OA[:, None], OA] = d1[0]
    dov[OA[:, None], VA] = d1[1]
    dvo[VA[:, None], OA] = d1[2]
    dvv[VA[:, None], VA] = d1[3]
    return doo, dov, dvo, dvv
Exemple #3
0
def _gamma1_intermediates(cc, t1, t2, l1, l2):
    d1 = ccsd_rdm._gamma1_intermediates(cc, t1, t2, l1, l2)
    if cc.frozen is None or cc.frozen is 0:
        return d1
    nocc = numpy.count_nonzero(cc.mo_occ>0)
    nvir = cc.mo_occ.size - nocc
    OA, VA, OF, VF = index_frozen_active(cc)
    doo = numpy.zeros((nocc,nocc))
    dov = numpy.zeros((nocc,nvir))
    dvo = numpy.zeros((nvir,nocc))
    dvv = numpy.zeros((nvir,nvir))
    doo[OA[:,None],OA] = d1[0]
    dov[OA[:,None],VA] = d1[1]
    dvo[VA[:,None],OA] = d1[2]
    dvv[VA[:,None],VA] = d1[3]
    return doo, dov, dvo, dvv
Exemple #4
0
def _gamma1_intermediates(mycc, t1, t2, l1, l2, eris=None, for_grad=False):
    doo, dov, dvo, dvv = ccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2)

    if eris is None: eris = mycc.ao2mo()
    nocc, nvir = t1.shape
    eris_ovvv = numpy.asarray(eris.get_ovvv())
    eris_ovoo = numpy.asarray(eris.ovoo)
    eris_ovov = numpy.asarray(eris.ovov)

    mo_e = eris.fock.diagonal()
    eia = lib.direct_sum('i-a->ia', mo_e[:nocc], mo_e[nocc:])
    d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia)

    w = (numpy.einsum('iafb,kjcf->ijkabc', eris_ovvv.conj(), t2) -
         numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo.conj(), t2)) / d3
    v = (numpy.einsum('iajb,kc->ijkabc', eris_ovov.conj(), t1) +
         numpy.einsum('ck,ijab->ijkabc', eris.fock[nocc:, :nocc], t2)) / d3
    w = p6(w)
    v = p6(v)
    wv = w + v * .5
    rw = r6(w)
    goo = numpy.einsum('iklabc,jklabc->ij', wv.conj(), rw)
    gvv = numpy.einsum('ijkacd,ijkbcd->ab', wv, rw.conj())

    if not for_grad:
        # t3 amplitudes in CCSD(T) is computed non-iteratively. The off-diagonal
        # blocks of fock matrix does not contribute to CCSD(T) energy. To make Tr(H,D)
        # consistent to the CCSD(T) total energy, the density matrix off-diagonal
        # parts are excluded.
        doo[numpy.diag_indices(nocc)] -= goo.diagonal() * .5
        dvv[numpy.diag_indices(nvir)] += gvv.diagonal() * .5

    else:
        # The off-diagonal blocks of fock matrix have small contributions to analytical
        # nuclear gradients.
        doo -= goo * .5
        dvv += gvv * .5

    dvo += numpy.einsum('ijab,ijkabc->ck', t2.conj(), rw) * .5
    return doo, dov, dvo, dvv
Exemple #5
0
def _gamma1_intermediates(mycc, t1, t2, l1, l2, eris=None, for_grad=False):
    doo, dov, dvo, dvv = ccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2)

    if eris is None: eris = mycc.ao2mo()
    nocc, nvir = t1.shape
    eris_ovvv = numpy.asarray(eris.get_ovvv())
    eris_ovoo = numpy.asarray(eris.ovoo)
    eris_ovov = numpy.asarray(eris.ovov)

    mo_e = eris.mo_energy
    eia = lib.direct_sum('i-a->ia', mo_e[:nocc], mo_e[nocc:])
    d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia)

    w =(numpy.einsum('iafb,kjcf->ijkabc', eris_ovvv.conj(), t2)
      - numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo.conj(), t2)) / d3
    v =(numpy.einsum('iajb,kc->ijkabc', eris_ovov.conj(), t1)
      + numpy.einsum('ck,ijab->ijkabc', eris.fock[nocc:,:nocc], t2)) / d3
    w = p6(w)
    v = p6(v)
    wv = w + v * .5
    rw = r6(w)
    goo = numpy.einsum('iklabc,jklabc->ij', wv.conj(), rw)
    gvv = numpy.einsum('ijkacd,ijkbcd->ab', wv, rw.conj())

    if not for_grad:
# t3 amplitudes in CCSD(T) is computed non-iteratively. The off-diagonal
# blocks of fock matrix does not contribute to CCSD(T) energy. To make Tr(H,D)
# consistent to the CCSD(T) total energy, the density matrix off-diagonal
# parts are excluded.
        doo[numpy.diag_indices(nocc)] -= goo.diagonal() * .5
        dvv[numpy.diag_indices(nvir)] += gvv.diagonal() * .5

    else:
# The off-diagonal blocks of fock matrix have small contributions to analytical
# nuclear gradients.
        doo -= goo * .5
        dvv += gvv * .5

    dvo += numpy.einsum('ijab,ijkabc->ck', t2.conj(), rw) * .5
    return doo, dov, dvo, dvv
Exemple #6
0
    def test_rdm(self):
        mycc = rccsd.RCCSD(mf)
        mycc.frozen = 1
        mycc.kernel()
        dm1 = mycc.make_rdm1()
        dm2 = mycc.make_rdm2()
        h1 = reduce(numpy.dot, (mf.mo_coeff.T, mf.get_hcore(), mf.mo_coeff))
        nmo = mf.mo_coeff.shape[1]
        eri = ao2mo.restore(1, ao2mo.kernel(mf._eri, mf.mo_coeff), nmo)
        e1 = numpy.einsum('ij,ji', h1, dm1)
        e1+= numpy.einsum('ijkl,ijkl', eri, dm2) * .5
        e1+= mol.energy_nuc()
        self.assertAlmostEqual(e1, mycc.e_tot, 7)

        d1 = ccsd_rdm._gamma1_intermediates(mycc, mycc.t1, mycc.t2, mycc.l1, mycc.l2)
        mycc1 = copy.copy(mycc)
        mycc1.max_memory = 0
        d2 = ccsd_rdm._gamma2_intermediates(mycc1, mycc.t1, mycc.t2, mycc.l1, mycc.l2, True)
        dm2 = ccsd_rdm._make_rdm2(mycc, d1, d2, with_dm1=True, with_frozen=True)
        e1 = numpy.einsum('ij,ji', h1, dm1)
        e1+= numpy.einsum('ijkl,ijkl', eri, dm2) * .5
        e1+= mol.energy_nuc()
        self.assertAlmostEqual(e1, mycc.e_tot, 7)
Exemple #7
0
def kernel(mycc,
           t1=None,
           t2=None,
           l1=None,
           l2=None,
           eris=None,
           atmlst=None,
           mf_grad=None,
           d1=None,
           d2=None,
           verbose=logger.INFO):
    if eris is not None:
        if abs(eris.fock - numpy.diag(eris.fock.diagonal())).max() > 1e-3:
            raise RuntimeError(
                'CCSD 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
    if mf_grad is None: mf_grad = mycc._scf.nuc_grad_method()

    log = logger.new_logger(mycc, verbose)
    time0 = time.clock(), time.time()

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

    mol = mycc.mol
    mo_coeff = mycc.mo_coeff
    mo_energy = mycc._scf.mo_energy
    nao, nmo = mo_coeff.shape
    nocc = numpy.count_nonzero(mycc.mo_occ > 0)
    with_frozen = not (mycc.frozen is None or mycc.frozen is 0)
    OA, VA, OF, VF = _index_frozen_active(mycc.get_frozen_mask(), mycc.mo_occ)

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

    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))
    Imat = numpy.zeros((nao, nao))
    vhf1 = fdm2.create_dataset('vhf1', (len(atmlst), 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((3, nao, nao))
        for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize):
            ip0, ip1 = ip1, ip1 + nf
            dm2buf = _load_block_tril(fdm2['dm2'], ip0, ip1, nao)
            dm2buf[:, :, 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)
            Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf, nao, -1),
                               dm2buf)
            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, dm2buf) * 2
            dm2buf = 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[i] -= numpy.einsum('ijkl,il->kj', eri1tmp,
                                       hf_dm1[ip0:ip1]) * .5
                vhf[i, ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1)
                vhf[i, ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp,
                                                hf_dm1) * .5
            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)

    Imat = reduce(numpy.dot,
                  (mo_coeff.T, Imat, mycc._scf.get_ovlp(), mo_coeff)) * -1

    dm1mo = numpy.zeros((nmo, nmo))
    if with_frozen:
        dco = Imat[OF[:, None], OA] / (mo_energy[OF, None] - mo_energy[OA])
        dfv = Imat[VF[:, None], VA] / (mo_energy[VF, None] - mo_energy[VA])
        dm1mo[OA[:, None], OA] = doo + doo.T
        dm1mo[OF[:, None], OA] = dco
        dm1mo[OA[:, None], OF] = dco.T
        dm1mo[VA[:, None], VA] = dvv + dvv.T
        dm1mo[VF[:, None], VA] = dfv
        dm1mo[VA[:, None], VF] = dfv.T
    else:
        dm1mo[:nocc, :nocc] = doo + doo.T
        dm1mo[nocc:, nocc:] = dvv + dvv.T

    dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T))
    vhf = mycc._scf.get_veff(mycc.mol, dm1) * 2
    Xvo = reduce(numpy.dot, (mo_coeff[:, nocc:].T, vhf, mo_coeff[:, :nocc]))
    Xvo += Imat[:nocc, nocc:].T - Imat[nocc:, :nocc]

    dm1mo += _response_dm1(mycc, Xvo, eris)
    time1 = log.timer_debug1('response_rdm1 intermediates', *time1)

    Imat[nocc:, :nocc] = Imat[:nocc, nocc:].T
    im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T))
    time1 = log.timer_debug1('response_rdm1', *time1)

    log.debug('h1 and JK1')
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)
    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:, :nocc] = mo_energy[:nocc]
    zeta[:nocc, nocc:] = mo_energy[:nocc].reshape(-1, 1)
    zeta = reduce(numpy.dot, (mo_coeff, zeta * dm1mo, mo_coeff.T))

    dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T))
    p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T)
    vhf_s1occ = reduce(numpy.dot,
                       (p1, mycc._scf.get_veff(mol, dm1 + dm1.T), p1))
    time1 = log.timer_debug1('h1 and JK1', *time1)

    # Hartree-Fock part contribution
    dm1p = hf_dm1 + dm1 * 2
    dm1 += hf_dm1
    zeta += mf_grad.make_rdm1e(mo_energy, mo_coeff, mycc.mo_occ)

    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], dm1p)

    de += mf_grad.grad_nuc(mol, atmlst)
    log.timer('%s gradients' % mycc.__class__.__name__, *time0)
    return de
    def test_rdm_trace(self):
        mycc = rccsd.RCCSD(mf)
        numpy.random.seed(2)
        nocc = 5
        nmo = 12
        nvir = nmo - nocc
        eri0 = numpy.random.random((nmo, nmo, nmo, nmo))
        eri0 = ao2mo.restore(1, ao2mo.restore(8, eri0, nmo), nmo)
        fock0 = numpy.random.random((nmo, nmo))
        fock0 = fock0 + fock0.T + numpy.diag(range(nmo)) * 2
        t1 = numpy.random.random((nocc, nvir))
        t2 = numpy.random.random((nocc, nocc, nvir, nvir))
        t2 = t2 + t2.transpose(1, 0, 3, 2)
        l1 = numpy.random.random((nocc, nvir))
        l2 = numpy.random.random((nocc, nocc, nvir, nvir))
        l2 = l2 + l2.transpose(1, 0, 3, 2)
        h1 = fock0 - (numpy.einsum('kkpq->pq', eri0[:nocc, :nocc]) * 2 -
                      numpy.einsum('pkkq->pq', eri0[:, :nocc, :nocc]))

        eris = lambda: None
        eris.oooo = eri0[:nocc, :nocc, :nocc, :nocc].copy()
        eris.ooov = eri0[:nocc, :nocc, :nocc, nocc:].copy()
        eris.ovoo = eri0[:nocc, nocc:, :nocc, :nocc].copy()
        eris.oovv = eri0[:nocc, :nocc, nocc:, nocc:].copy()
        eris.ovov = eri0[:nocc, nocc:, :nocc, nocc:].copy()
        eris.ovvo = eri0[:nocc, nocc:, nocc:, :nocc].copy()
        eris.ovvv = eri0[:nocc, nocc:, nocc:, nocc:].copy()
        eris.vvvv = eri0[nocc:, nocc:, nocc:, nocc:].copy()
        eris.fock = fock0

        doo, dov, dvo, dvv = ccsd_rdm._gamma1_intermediates(
            mycc, t1, t2, l1, l2)
        self.assertAlmostEqual(
            (numpy.einsum('ij,ij', doo, fock0[:nocc, :nocc])) * 2,
            -20166.329861034799, 8)
        self.assertAlmostEqual(
            (numpy.einsum('ab,ab', dvv, fock0[nocc:, nocc:])) * 2,
            58078.964019246778, 8)
        self.assertAlmostEqual(
            (numpy.einsum('ai,ia', dvo, fock0[:nocc, nocc:])) * 2,
            -74994.356886784764, 8)
        self.assertAlmostEqual(
            (numpy.einsum('ia,ai', dov, fock0[nocc:, :nocc])) * 2,
            34.010188025702391, 9)

        fdm2 = lib.H5TmpFile()
        dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \
                ccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True)
        self.assertAlmostEqual(lib.finger(numpy.array(dovov)),
                               -14384.907042073517, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dvvvv)),
                               -25.374007033024839, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doooo)),
                               60.114594698129963, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doovv)),
                               -79.176348067958401, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvo)),
                               9.864134457251815, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvv)),
                               -421.90333700061342, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dooov)),
                               -592.66863759586136, 9)
        fdm2 = None

        dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \
                ccsd_rdm._gamma2_intermediates(mycc, t1, t2, l1, l2)
        self.assertAlmostEqual(lib.finger(numpy.array(dovov)),
                               -14384.907042073517, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dvvvv)),
                               45.872344902116758, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doooo)),
                               60.114594698129963, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doovv)),
                               -79.176348067958401, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvo)),
                               9.864134457251815, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvv)),
                               -421.90333700061342, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dooov)),
                               -592.66863759586136, 9)

        self.assertAlmostEqual(
            numpy.einsum('kilj,kilj', doooo, eris.oooo) * 2, 15939.9007625418,
            7)
        self.assertAlmostEqual(
            numpy.einsum('acbd,acbd', dvvvv, eris.vvvv) * 2, 37581.823919588,
            7)
        self.assertAlmostEqual(
            numpy.einsum('jkia,jkia', dooov, eris.ooov) * 2, 128470.009687716,
            7)
        self.assertAlmostEqual(
            numpy.einsum('icba,icba', dovvv, eris.ovvv) * 2, -166794.225195056,
            7)
        self.assertAlmostEqual(
            numpy.einsum('iajb,iajb', dovov, eris.ovov) * 2, -719279.812916893,
            7)
        self.assertAlmostEqual(
            numpy.einsum('jbai,jbia', dovvo, eris.ovov) * 2 +
            numpy.einsum('jiab,jiba', doovv, eris.oovv) * 2, -53634.0012286654,
            7)

        dm1 = ccsd_rdm.make_rdm1(mycc, t1, t2, l1, l2)
        dm2 = ccsd_rdm.make_rdm2(mycc, t1, t2, l1, l2)
        e2 = (
            numpy.einsum('ijkl,ijkl', doooo, eris.oooo) * 2 +
            numpy.einsum('acbd,acbd', dvvvv, eris.vvvv) * 2 +
            numpy.einsum('jkia,jkia', dooov, eris.ooov) * 2 +
            numpy.einsum('icba,icba', dovvv, eris.ovvv) * 2 +
            numpy.einsum('iajb,iajb', dovov, eris.ovov) * 2 +
            numpy.einsum('jbai,jbia', dovvo, eris.ovov) * 2 +
            numpy.einsum('ijab,ijab', doovv, eris.oovv) * 2 +
            numpy.einsum('ij,ij', doo, fock0[:nocc, :nocc]) * 2 +
            numpy.einsum('ai,ia', dvo, fock0[:nocc, nocc:]) * 2 +
            numpy.einsum('ia,ai', dov, fock0[nocc:, :nocc]) * 2 +
            numpy.einsum('ab,ab', dvv, fock0[nocc:, nocc:]) * 2 +
            fock0[:nocc].trace() * 2 - numpy.einsum(
                'kkpq->pq', eri0[:nocc, :nocc, :nocc, :nocc]).trace() * 2 +
            numpy.einsum('pkkq->pq', eri0[:nocc, :nocc, :nocc, :nocc]).trace())
        self.assertAlmostEqual(e2, -794721.197459942, 8)
        self.assertAlmostEqual(
            numpy.einsum('pqrs,pqrs', dm2, eri0) * .5 +
            numpy.einsum('pq,qp', dm1, h1), e2, 9)

        self.assertAlmostEqual(
            abs(dm2 - dm2.transpose(1, 0, 3, 2)).max(), 0, 9)
        self.assertAlmostEqual(
            abs(dm2 - dm2.transpose(2, 3, 0, 1)).max(), 0, 9)

        d1 = numpy.einsum('kkpq->qp', dm2) / 9
        self.assertAlmostEqual(abs(d1 - dm1).max(), 0, 9)
Exemple #9
0
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None,
           mf_grad=None, d1=None, d2=None, verbose=logger.INFO):
    if eris is not None:
        if abs(eris.fock - numpy.diag(eris.fock.diagonal())).max() > 1e-3:
            raise RuntimeError('CCSD 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
    if mf_grad is None: mf_grad = mycc._scf.nuc_grad_method()

    log = logger.new_logger(mycc, verbose)
    time0 = time.clock(), time.time()

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

    mol = mycc.mol
    mo_coeff = mycc.mo_coeff
    mo_energy = mycc._scf.mo_energy
    nao, nmo = mo_coeff.shape
    nocc = numpy.count_nonzero(mycc.mo_occ > 0)
    with_frozen = not (mycc.frozen is None or mycc.frozen is 0)
    OA, VA, OF, VF = _index_frozen_active(mycc.get_frozen_mask(), mycc.mo_occ)

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

    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))
    Imat = numpy.zeros((nao,nao))
    vhf1 = fdm2.create_dataset('vhf1', (len(atmlst),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((3,nao,nao))
        for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize):
            ip0, ip1 = ip1, ip1 + nf
            dm2buf = _load_block_tril(fdm2['dm2'], ip0, ip1, nao)
            dm2buf[:,:,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)
            Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf,nao,-1), dm2buf)
            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, dm2buf) * 2
            dm2buf = 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[i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1[ip0:ip1]) * .5
                vhf[i,ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1)
                vhf[i,ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1) * .5
            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)

    Imat = reduce(numpy.dot, (mo_coeff.T, Imat, mycc._scf.get_ovlp(), mo_coeff)) * -1

    dm1mo = numpy.zeros((nmo,nmo))
    if with_frozen:
        dco = Imat[OF[:,None],OA] / (mo_energy[OF,None] - mo_energy[OA])
        dfv = Imat[VF[:,None],VA] / (mo_energy[VF,None] - mo_energy[VA])
        dm1mo[OA[:,None],OA] = doo + doo.T
        dm1mo[OF[:,None],OA] = dco
        dm1mo[OA[:,None],OF] = dco.T
        dm1mo[VA[:,None],VA] = dvv + dvv.T
        dm1mo[VF[:,None],VA] = dfv
        dm1mo[VA[:,None],VF] = dfv.T
    else:
        dm1mo[:nocc,:nocc] = doo + doo.T
        dm1mo[nocc:,nocc:] = dvv + dvv.T

    dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T))
    vhf = mycc._scf.get_veff(mycc.mol, dm1) * 2
    Xvo = reduce(numpy.dot, (mo_coeff[:,nocc:].T, vhf, mo_coeff[:,:nocc]))
    Xvo+= Imat[:nocc,nocc:].T - Imat[nocc:,:nocc]

    dm1mo += _response_dm1(mycc, Xvo, eris)
    time1 = log.timer_debug1('response_rdm1 intermediates', *time1)

    Imat[nocc:,:nocc] = Imat[:nocc,nocc:].T
    im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T))
    time1 = log.timer_debug1('response_rdm1', *time1)

    log.debug('h1 and JK1')
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)
    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:,:nocc] = mo_energy[:nocc]
    zeta[:nocc,nocc:] = mo_energy[:nocc].reshape(-1,1)
    zeta = reduce(numpy.dot, (mo_coeff, zeta*dm1mo, mo_coeff.T))

    dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T))
    p1 = numpy.dot(mo_coeff[:,:nocc], mo_coeff[:,:nocc].T)
    vhf_s1occ = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1+dm1.T), p1))
    time1 = log.timer_debug1('h1 and JK1', *time1)

    # Hartree-Fock part contribution
    dm1p = hf_dm1 + dm1*2
    dm1 += hf_dm1
    zeta += mf_grad.make_rdm1e(mo_energy, mo_coeff, mycc.mo_occ)

    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], dm1p)

    de += mf_grad.grad_nuc(mol, atmlst)
    log.timer('%s gradients' % mycc.__class__.__name__, *time0)
    return de
Exemple #10
0
    def test_rdm_trace(self):
        mycc = rccsd.RCCSD(mf)
        numpy.random.seed(2)
        nocc = 5
        nmo = 12
        nvir = nmo - nocc
        eri0 = numpy.random.random((nmo,nmo,nmo,nmo))
        eri0 = ao2mo.restore(1, ao2mo.restore(8, eri0, nmo), nmo)
        fock0 = numpy.random.random((nmo,nmo))
        fock0 = fock0 + fock0.T + numpy.diag(range(nmo))*2
        t1 = numpy.random.random((nocc,nvir))
        t2 = numpy.random.random((nocc,nocc,nvir,nvir))
        t2 = t2 + t2.transpose(1,0,3,2)
        l1 = numpy.random.random((nocc,nvir))
        l2 = numpy.random.random((nocc,nocc,nvir,nvir))
        l2 = l2 + l2.transpose(1,0,3,2)
        h1 = fock0 - (numpy.einsum('kkpq->pq', eri0[:nocc,:nocc])*2
                    - numpy.einsum('pkkq->pq', eri0[:,:nocc,:nocc]))

        eris = lambda:None
        eris.oooo = eri0[:nocc,:nocc,:nocc,:nocc].copy()
        eris.ooov = eri0[:nocc,:nocc,:nocc,nocc:].copy()
        eris.ovoo = eri0[:nocc,nocc:,:nocc,:nocc].copy()
        eris.oovv = eri0[:nocc,:nocc,nocc:,nocc:].copy()
        eris.ovov = eri0[:nocc,nocc:,:nocc,nocc:].copy()
        eris.ovvo = eri0[:nocc,nocc:,nocc:,:nocc].copy()
        eris.ovvv = eri0[:nocc,nocc:,nocc:,nocc:].copy()
        eris.vvvv = eri0[nocc:,nocc:,nocc:,nocc:].copy()
        eris.fock = fock0

        doo, dov, dvo, dvv = ccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2)
        self.assertAlmostEqual((numpy.einsum('ij,ij', doo, fock0[:nocc,:nocc]))*2, -20166.329861034799, 8)
        self.assertAlmostEqual((numpy.einsum('ab,ab', dvv, fock0[nocc:,nocc:]))*2,  58078.964019246778, 8)
        self.assertAlmostEqual((numpy.einsum('ai,ia', dvo, fock0[:nocc,nocc:]))*2, -74994.356886784764, 8)
        self.assertAlmostEqual((numpy.einsum('ia,ai', dov, fock0[nocc:,:nocc]))*2,  34.010188025702391, 9)

        fdm2 = lib.H5TmpFile()
        dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \
                ccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True)
        self.assertAlmostEqual(lib.finger(numpy.array(dovov)), -14384.907042073517, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dvvvv)), -25.374007033024839, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doooo)),  60.114594698129963, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doovv)), -79.176348067958401, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvo)),   9.864134457251815, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvv)), -421.90333700061342, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dooov)), -592.66863759586136, 9)
        fdm2 = None

        dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \
                ccsd_rdm._gamma2_intermediates(mycc, t1, t2, l1, l2)
        self.assertAlmostEqual(lib.finger(numpy.array(dovov)), -14384.907042073517, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dvvvv)),  45.872344902116758, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doooo)),  60.114594698129963, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(doovv)), -79.176348067958401, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvo)),   9.864134457251815, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dovvv)), -421.90333700061342, 9)
        self.assertAlmostEqual(lib.finger(numpy.array(dooov)), -592.66863759586136, 9)

        self.assertAlmostEqual(numpy.einsum('kilj,kilj', doooo, eris.oooo)*2, 15939.9007625418, 7)
        self.assertAlmostEqual(numpy.einsum('acbd,acbd', dvvvv, eris.vvvv)*2, 37581.823919588 , 7)
        self.assertAlmostEqual(numpy.einsum('jkia,jkia', dooov, eris.ooov)*2, 128470.009687716, 7)
        self.assertAlmostEqual(numpy.einsum('icba,icba', dovvv, eris.ovvv)*2,-166794.225195056, 7)
        self.assertAlmostEqual(numpy.einsum('iajb,iajb', dovov, eris.ovov)*2,-719279.812916893, 7)
        self.assertAlmostEqual(numpy.einsum('jbai,jbia', dovvo, eris.ovov)*2+
                               numpy.einsum('jiab,jiba', doovv, eris.oovv)*2,-53634.0012286654, 7)

        dm1 = ccsd_rdm.make_rdm1(mycc, t1, t2, l1, l2)
        dm2 = ccsd_rdm.make_rdm2(mycc, t1, t2, l1, l2)
        e2 =(numpy.einsum('ijkl,ijkl', doooo, eris.oooo)*2
            +numpy.einsum('acbd,acbd', dvvvv, eris.vvvv)*2
            +numpy.einsum('jkia,jkia', dooov, eris.ooov)*2
            +numpy.einsum('icba,icba', dovvv, eris.ovvv)*2
            +numpy.einsum('iajb,iajb', dovov, eris.ovov)*2
            +numpy.einsum('jbai,jbia', dovvo, eris.ovov)*2
            +numpy.einsum('ijab,ijab', doovv, eris.oovv)*2
            +numpy.einsum('ij,ij', doo, fock0[:nocc,:nocc])*2
            +numpy.einsum('ai,ia', dvo, fock0[:nocc,nocc:])*2
            +numpy.einsum('ia,ai', dov, fock0[nocc:,:nocc])*2
            +numpy.einsum('ab,ab', dvv, fock0[nocc:,nocc:])*2
            +fock0[:nocc].trace()*2
            -numpy.einsum('kkpq->pq', eri0[:nocc,:nocc,:nocc,:nocc]).trace()*2
            +numpy.einsum('pkkq->pq', eri0[:nocc,:nocc,:nocc,:nocc]).trace())
        self.assertAlmostEqual(e2, -794721.197459942, 8)
        self.assertAlmostEqual(numpy.einsum('pqrs,pqrs', dm2, eri0)*.5 +
                               numpy.einsum('pq,qp', dm1, h1), e2, 9)

        self.assertAlmostEqual(abs(dm2-dm2.transpose(1,0,3,2)).max(), 0, 9)
        self.assertAlmostEqual(abs(dm2-dm2.transpose(2,3,0,1)).max(), 0, 9)

        d1 = numpy.einsum('kkpq->qp', dm2) / 9
        self.assertAlmostEqual(abs(d1-dm1).max(), 0, 9)