Exemple #1
0
    def __init__(self,
                 cc,
                 mo_coeff=None,
                 method='incore',
                 ao2mofn=ao2mo.outcore.general_iofree):
        cput0 = (time.clock(), time.time())
        moidx = ccsd.get_moidx(cc)
        if mo_coeff is None:
            self.mo_coeff = mo_coeff = cc.mo_coeff[:, moidx]
        else:  # If mo_coeff is not canonical orbital
            self.mo_coeff = mo_coeff = mo_coeff[:, moidx]
        dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ)
        fockao = cc._scf.get_hcore() + cc._scf.get_veff(cc.mol, dm)
        self.fock = reduce(numpy.dot, (mo_coeff.T, fockao, mo_coeff))

        nocc = cc.nocc
        nmo = cc.nmo
        nvir = nmo - nocc
        mem_incore, mem_outcore, mem_basic = _mem_usage(nocc, nvir)
        mem_now = lib.current_memory()[0]

        log = logger.Logger(cc.stdout, cc.verbose)
        if (method == 'incore' and (mem_incore + mem_now < cc.max_memory)
                or cc.mol.incore_anyway):
            eri = ao2mofn(cc._scf.mol,
                          (mo_coeff, mo_coeff, mo_coeff, mo_coeff),
                          compact=0)
            if mo_coeff.dtype == np.float: eri = eri.real
            eri = eri.reshape((nmo, ) * 4)
            # <ij|kl> = (ik|jl)
            eri = eri.transpose(0, 2, 1, 3)

            self.dtype = eri.dtype
            self.oooo = eri[:nocc, :nocc, :nocc, :nocc].copy()
            self.ooov = eri[:nocc, :nocc, :nocc, nocc:].copy()
            self.oovv = eri[:nocc, :nocc, nocc:, nocc:].copy()
            self.ovov = eri[:nocc, nocc:, :nocc, nocc:].copy()
            self.voov = eri[nocc:, :nocc, :nocc, nocc:].copy()
            self.vovv = eri[nocc:, :nocc, nocc:, nocc:].copy()
            self.vvvv = eri[nocc:, nocc:, nocc:, nocc:].copy()
        else:
            _tmpfile1 = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR)
            self.feri1 = h5py.File(_tmpfile1.name)
            orbo = mo_coeff[:, :nocc]
            orbv = mo_coeff[:, nocc:]
            if mo_coeff.dtype == np.complex: ds_type = 'c16'
            else: ds_type = 'f8'
            self.oooo = self.feri1.create_dataset('oooo',
                                                  (nocc, nocc, nocc, nocc),
                                                  ds_type)
            self.ooov = self.feri1.create_dataset('ooov',
                                                  (nocc, nocc, nocc, nvir),
                                                  ds_type)
            self.oovv = self.feri1.create_dataset('oovv',
                                                  (nocc, nocc, nvir, nvir),
                                                  ds_type)
            self.ovov = self.feri1.create_dataset('ovov',
                                                  (nocc, nvir, nocc, nvir),
                                                  ds_type)
            self.voov = self.feri1.create_dataset('voov',
                                                  (nvir, nocc, nocc, nvir),
                                                  ds_type)
            self.vovv = self.feri1.create_dataset('vovv',
                                                  (nvir, nocc, nvir, nvir),
                                                  ds_type)
            self.vvvv = self.feri1.create_dataset('vvvv',
                                                  (nvir, nvir, nvir, nvir),
                                                  ds_type)

            cput1 = time.clock(), time.time()
            # <ij|pq>  = (ip|jq)
            buf = ao2mofn(cc._scf.mol, (orbo, mo_coeff, orbo, mo_coeff),
                          compact=0)
            if mo_coeff.dtype == np.float: buf = buf.real
            buf = buf.reshape((nocc, nmo, nocc, nmo)).transpose(0, 2, 1, 3)
            cput1 = log.timer_debug1('transforming oopq', *cput1)
            self.dtype = buf.dtype
            self.oooo[:, :, :, :] = buf[:, :, :nocc, :nocc]
            self.ooov[:, :, :, :] = buf[:, :, :nocc, nocc:]
            self.oovv[:, :, :, :] = buf[:, :, nocc:, nocc:]

            cput1 = time.clock(), time.time()
            # <ia|pq> = (ip|aq)
            buf = ao2mofn(cc._scf.mol, (orbo, mo_coeff, orbv, mo_coeff),
                          compact=0)
            if mo_coeff.dtype == np.float: buf = buf.real
            buf = buf.reshape((nocc, nmo, nvir, nmo)).transpose(0, 2, 1, 3)
            cput1 = log.timer_debug1('transforming ovpq', *cput1)
            self.ovov[:, :, :, :] = buf[:, :, :nocc, nocc:]
            self.vovv[:, :, :, :] = buf[:, :, nocc:,
                                        nocc:].transpose(1, 0, 3, 2)
            self.voov[:, :, :, :] = buf[:, :,
                                        nocc:, :nocc].transpose(1, 0, 3, 2)

            _tmpfile2 = tempfile.NamedTemporaryFile()
            self.feri2 = h5py.File(_tmpfile2.name, 'w')
            ao2mo.full(cc.mol,
                       orbv,
                       self.feri2,
                       max_memory=cc.max_memory,
                       verbose=log,
                       compact=False)
            vvvv_buf = self.feri2['eri_mo']
            for a in range(nvir):
                abrange = a * nvir + np.arange(nvir)
                self.vvvv[a, :, :, :] = np.array(vvvv_buf[abrange, :]).reshape(
                    (nvir, nvir, nvir)).transpose(1, 0, 2)

            cput1 = log.timer_debug1('transforming vvvv', *cput1)

        log.timer('CCSD integral transformation', *cput0)
Exemple #2
0
def kernel(mycc,
           t1=None,
           t2=None,
           l1=None,
           l2=None,
           eris=None,
           atmlst=None,
           mf_grad=None,
           verbose=logger.INFO):
    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 eris is None: eris = ccsd._ERIS(mycc)
    if mf_grad is None:
        mf_grad = rhf_grad.Gradients(mycc._scf)

    log = logger.Logger(mycc.stdout, mycc.verbose)
    time0 = time.clock(), time.time()
    mol = mycc.mol
    if mycc.frozen is not 0:
        raise NotImplementedError('frozen orbital ccsd_grad')
    moidx = ccsd.get_moidx(mycc)
    mo_coeff = mycc.mo_coeff[:,
                             moidx]  #FIXME: ensure mycc.mo_coeff is canonical orbital
    mo_energy = eris.fock.diagonal()
    nocc, nvir = t1.shape
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao + 1) // 2

    log.debug('Build ccsd rdm1 intermediates')
    d1 = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2)
    doo, dov, dvo, dvv = d1
    time1 = log.timer('rdm1 intermediates', *time0)

    log.debug('Build ccsd rdm2 intermediates')
    d2 = ccsd_rdm.gamma2_incore(mycc, t1, t2, l1, l2)
    time1 = log.timer('rdm2 intermediates', *time1)
    log.debug('Build ccsd response_rdm1')
    Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris, d1, d2)
    time1 = log.timer('response_rdm1 intermediates', *time1)

    dm1mo = response_dm1(mycc, t1, t2, l1, l2, eris, (Ioo, Ivv, Ivo, Xvo))
    dm1mo[:nocc, :nocc] = doo * 2
    dm1mo[nocc:, nocc:] = dvv * 2
    dm1ao = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T))
    im1 = numpy.zeros_like(dm1mo)
    im1[:nocc, :nocc] = Ioo
    im1[nocc:, nocc:] = Ivv
    im1[nocc:, :nocc] = Ivo
    im1[:nocc, nocc:] = Ivo.T
    im1 = reduce(numpy.dot, (mo_coeff, im1, mo_coeff.T))
    time1 = log.timer('response_rdm1', *time1)

    log.debug('symmetrized rdm2 and MO->AO transformation')
    dm1_with_hf = dm1mo.copy()
    for i in range(nocc):
        dm1_with_hf[i, i] += 1
    dm2ao = _rdm2_mo2ao(mycc, d2, dm1_with_hf, mo_coeff)
    time1 = log.timer('MO->AO transformation', *time1)

    log.debug('h1 and JK1')
    h1 = mf_grad.get_hcore(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))
    p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T)
    vhf4sij = reduce(numpy.dot,
                     (p1, mycc._scf.get_veff(mol, dm1ao + dm1ao.T), p1))
    time1 = log.timer('h1 and JK1', *time1)

    # Hartree-Fock part contribution
    hf_dm1 = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ)
    dm1ao += hf_dm1
    zeta += mf_grad.make_rdm1e(mycc.mo_energy, mycc.mo_coeff, mycc.mo_occ)

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    de = numpy.zeros((len(atmlst), 3))
    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]) +
                 numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1]))
        # h[1] \dot DM, *2 for +c.c.,  contribute to f1
        h1ao = mf_grad._grad_rinv(mol, ia)
        h1ao[:, p0:p1] += h1[:, p0:p1]
        de[k] += (numpy.einsum('xij,ij->x', h1ao, dm1ao) +
                  numpy.einsum('xji,ij->x', h1ao, dm1ao))
        # -s[1]*e \dot DM,  contribute to f1
        de[k] -= (numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) +
                  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], vhf4sij[p0:p1]) * 2

        # 2e AO integrals dot 2pdm
        eri1 = mol.intor('int2e_ip1',
                         comp=3,
                         aosym='s2kl',
                         shls_slice=(shl0, shl1, 0, mol.nbas, 0, mol.nbas, 0,
                                     mol.nbas))
        eri1 = eri1.reshape(3, p1 - p0, nao, -1)
        dm2buf = _load_block_tril(dm2ao, p0, p1)
        de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2

        eri1 = dm2buf = None
        log.debug('grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k])
        time1 = log.timer('grad of atom %d' % ia, *time1)

    de += rhf_grad.grad_nuc(mol)
    log.note('CCSD gradinets')
    log.note('==============')
    log.note('           x                y                z')
    for k, ia in enumerate(atmlst):
        log.note('%d %s  %15.9f  %15.9f  %15.9f', ia, mol.atom_symbol(ia),
                 *de[k])
    log.timer('CCSD gradients', *time0)
    return de
Exemple #3
0
def kernel(mycc,
           t1=None,
           t2=None,
           l1=None,
           l2=None,
           eris=None,
           atmlst=None,
           mf_grad=None,
           verbose=logger.INFO):
    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 eris is None: eris = ccsd._ERIS(mycc)
    if mf_grad is None:
        mf_grad = rhf_grad.Gradients(mycc._scf)

    log = logger.new_logger(mycc, verbose)
    time0 = time.clock(), time.time()
    mol = mycc.mol
    if mycc.frozen is not 0:
        raise NotImplementedError('frozen orbital ccsd_grad')
    moidx = ccsd.get_moidx(mycc)
    mo_coeff = mycc.mo_coeff[:,
                             moidx]  #FIXME: ensure mycc.mo_coeff is canonical orbital
    mo_energy = eris.fock.diagonal()
    nocc, nvir = t1.shape
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao + 1) // 2

    log.debug('Build ccsd rdm1 intermediates')
    d1 = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2)
    doo, dov, dvo, dvv = d1
    time1 = log.timer('rdm1 intermediates', *time0)

    log.debug('Build ccsd rdm2 intermediates')
    fd2intermediate = lib.H5TmpFile()
    d2 = ccsd_rdm.gamma2_outcore(mycc, t1, t2, l1, l2, fd2intermediate)
    time1 = log.timer('rdm2 intermediates', *time1)
    log.debug('Build ccsd response_rdm1')
    Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris, d1, d2)
    time1 = log.timer('response_rdm1 intermediates', *time1)

    dm1mo = response_dm1(mycc, t1, t2, l1, l2, eris, (Ioo, Ivv, Ivo, Xvo))
    dm1mo[:nocc, :nocc] = doo + doo.T
    dm1mo[nocc:, nocc:] = dvv + dvv.T
    dm1ao = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T))
    im1 = numpy.zeros_like(dm1mo)
    im1[:nocc, :nocc] = Ioo
    im1[nocc:, nocc:] = Ivv
    im1[nocc:, :nocc] = Ivo
    im1[:nocc, nocc:] = Ivo.T
    im1 = reduce(numpy.dot, (mo_coeff, im1, mo_coeff.T))
    time1 = log.timer('response_rdm1', *time1)

    log.debug('symmetrized rdm2 and MO->AO transformation')
    # Basically, 4 times of dm2 is computed. *2 in _rdm2_mo2ao, *2 in _load_block_tril
    fdm2 = lib.H5TmpFile()
    dm1_with_hf = dm1mo.copy()
    for i in range(
            nocc
    ):  # HF 2pdm ~ 4(ij)(kl)-2(il)(jk), diagonal+1 because of 4*dm2
        dm1_with_hf[i, i] += 1
    _rdm2_mo2ao(mycc, d2, dm1_with_hf, mo_coeff, fdm2)
    time1 = log.timer('MO->AO transformation', *time1)
    fd2intermediate = None

    #TODO: pass hf_grad object to compute h1 and s1
    log.debug('h1 and JK1')
    h1 = mf_grad.get_hcore(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))
    p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T)
    vhf4sij = reduce(numpy.dot,
                     (p1, mycc._scf.get_veff(mol, dm1ao + dm1ao.T), p1))
    time1 = log.timer('h1 and JK1', *time1)

    # Hartree-Fock part contribution
    hf_dm1 = mycc._scf.make_rdm1(mycc._scf.mo_coeff, mycc._scf.mo_occ)
    dm1ao += hf_dm1
    zeta += mf_grad.make_rdm1e(mycc._scf.mo_energy, mycc._scf.mo_coeff,
                               mycc._scf.mo_occ)

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    max_memory = mycc.max_memory - lib.current_memory()[0]
    blksize = max(1, int(max_memory * 1e6 / 8 / (nao**3 * 2.5)))
    ioblksize = fdm2['dm2/0'].shape[-1]
    de = numpy.zeros((len(atmlst), 3))
    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]) +
                 numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1]))
        # h[1] \dot DM, *2 for +c.c.,  contribute to f1
        h1ao = mf_grad._grad_rinv(mol, ia)
        h1ao[:, p0:p1] += h1[:, p0:p1]
        de[k] += (numpy.einsum('xij,ij->x', h1ao, dm1ao) +
                  numpy.einsum('xji,ij->x', h1ao, dm1ao))
        # -s[1]*e \dot DM,  contribute to f1
        de[k] -= (numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) +
                  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], vhf4sij[p0:p1]) * 2

        # 2e AO integrals dot 2pdm
        ip0 = p0
        for b0, b1, nf in shell_prange(mol, shl0, shl1, blksize):
            eri1 = mol.intor('int2e_ip1',
                             comp=3,
                             aosym='s2kl',
                             shls_slice=(b0, b1, 0, mol.nbas, 0, mol.nbas, 0,
                                         mol.nbas))
            eri1 = eri1.reshape(3, nf, nao, -1)
            dm2buf = numpy.empty((nf, nao, nao_pair))
            for ic, (i0, i1) in enumerate(prange(0, nao_pair, ioblksize)):
                _load_block_tril(fdm2['dm2/%d' % ic], ip0, ip0 + nf,
                                 dm2buf[:, :, i0:i1])
            de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2
            eri1 = dm2buf = None
            ip0 += nf
        log.debug('grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k])
        time1 = log.timer('grad of atom %d' % ia, *time1)

    de += rhf_grad.grad_nuc(mol)
    log.note('--------------- CCSD gradients ---------------')
    log.note('           x                y                z')
    for k, ia in enumerate(atmlst):
        log.note('%d %s  %15.9f  %15.9f  %15.9f', ia, mol.atom_symbol(ia),
                 *de[k])
    log.note('----------------------------------------------')
    log.timer('CCSD gradients', *time0)
    fdm2 = None
    return de