Beispiel #1
0
def build_Lpq_pbc(mydf, auxcell, kptij_lst):
    """Fitting coefficients for auxiliary functions"""
    kpts_ji = kptij_lst[:, 1] - kptij_lst[:, 0]
    uniq_kpts, uniq_index, uniq_inverse = unique(kpts_ji)
    max_memory = max(2000, (mydf.max_memory - lib.current_memory()[0]))
    if mydf.metric.upper() == "S":
        outcore.aux_e2(
            mydf.cell, auxcell, mydf._cderi, "cint3c1e_sph", kptij_lst=kptij_lst, dataname="Lpq", max_memory=max_memory
        )
        s_aux = auxcell.pbc_intor("cint1e_ovlp_sph", hermi=1, kpts=uniq_kpts)
    else:  # mydf.metric.upper() == 'T'
        outcore.aux_e2(
            mydf.cell,
            auxcell,
            mydf._cderi,
            "cint3c1e_p2_sph",
            kptij_lst=kptij_lst,
            dataname="Lpq",
            max_memory=max_memory,
        )
        s_aux = [x * 2 for x in auxcell.pbc_intor("cint1e_kin_sph", hermi=1, kpts=uniq_kpts)]

    s_aux = [scipy.linalg.cho_factor(x) for x in s_aux]

    max_memory = mydf.max_memory - lib.current_memory()[0]
    naux = auxcell.nao_nr()
    blksize = max(int(max_memory * 0.5 * 1e6 / 16 / naux / mydf.blockdim), 1) * mydf.blockdim
    with h5py.File(mydf._cderi) as feri:
        for k, where in enumerate(uniq_inverse):
            s_k = s_aux[where]
            key = "Lpq/%d" % k
            Lpq = feri[key]
            nao_pair = Lpq.shape[1]
            for p0, p1 in lib.prange(0, nao_pair, blksize):
                Lpq[:, p0:p1] = scipy.linalg.cho_solve(s_k, Lpq[:, p0:p1])
Beispiel #2
0
def gamma1_intermediates(mycc, t1, t2, l1, l2):
    nocc, nvir = t1.shape
    doo =-numpy.einsum('ja,ia->ij', l1, t1)
    dvv = numpy.einsum('ia,ib->ab', l1, t1)
    dvo = l1.T
    xtv = numpy.einsum('ie,me->im', t1, l1)
    dov = t1 - numpy.einsum('im,ma->ia', xtv, t1)
    #:doo -= numpy.einsum('jkab,ikab->ij', l2, theta)
    #:dvv += numpy.einsum('jica,jicb->ab', l2, theta)
    #:xt1  = numpy.einsum('mnef,inef->mi', l2, make_theta(t2))
    #:xt2  = numpy.einsum('mnaf,mnef->ea', l2, make_theta(t2))
    #:dov += numpy.einsum('imae,me->ia', make_theta(t2), l1)
    #:dov -= numpy.einsum('ma,ie,me->ia', t1, t1, l1)
    #:dov -= numpy.einsum('mi,ma->ia', xt1, t1)
    #:dov -= numpy.einsum('ie,ae->ia', t1, xt2)
    max_memory = mycc.max_memory - lib.current_memory()[0]
    unit = nocc*nvir**2
    blksize = max(ccsd.BLKMIN, int(max_memory*.95e6/8/unit))
    for p0, p1 in prange(0, nocc, blksize):
        theta = make_theta(t2[p0:p1])
        doo[p0:p1] -= lib.dot(theta.reshape(p1-p0,-1), l2.reshape(nocc,-1).T)
        dov[p0:p1] += numpy.einsum('imae,me->ia', theta, l1)
        xt1 = lib.dot(l2.reshape(nocc,-1), theta.reshape(p1-p0,-1).T)
        dov[p0:p1] -= numpy.einsum('mi,ma->ia', xt1, t1)
        xt2 = lib.dot(theta.reshape(-1,nvir).T, l2[p0:p1].reshape(-1,nvir))
        dov -= numpy.einsum('ie,ae->ia', t1, xt2)
        dvv += lib.dot(l2[p0:p1].reshape(-1,nvir).T, theta.reshape(-1,nvir))
    return doo, dov, dvo, dvv
Beispiel #3
0
def gen_hop(hobj, mo_energy=None, mo_coeff=None, mo_occ=None, verbose=None):
    log = logger.new_logger(hobj, verbose)
    mol = hobj.mol
    mf = hobj.base

    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None:    mo_occ = mf.mo_occ
    if mo_coeff is None:  mo_coeff = mf.mo_coeff

    natm = mol.natm
    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    nocc = mocc.shape[1]

    atmlst = range(natm)
    max_memory = max(2000, hobj.max_memory - lib.current_memory()[0])
    de2 = hobj.partial_hess_elec(mo_energy, mo_coeff, mo_occ, atmlst,
                                 max_memory, log)
    de2 += hobj.hess_nuc()

    # Compute H1 integrals and store in hobj.chkfile
    hobj.make_h1(mo_coeff, mo_occ, hobj.chkfile, atmlst, log)

    aoslices = mol.aoslice_by_atom()
    s1a = -mol.intor('int1e_ipovlp', comp=3)

    fvind = gen_vind(mf, mo_coeff, mo_occ)
    def h_op(x):
        x = x.reshape(natm,3)
        hx = numpy.einsum('abxy,ax->by', de2, x)
        h1ao = 0
        s1ao = 0
        for ia in range(natm):
            shl0, shl1, p0, p1 = aoslices[ia]
            h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/%d' % ia)
            h1ao += numpy.einsum('x,xij->ij', x[ia], h1ao_i)
            s1ao_i = numpy.zeros((3,nao,nao))
            s1ao_i[:,p0:p1] += s1a[:,p0:p1]
            s1ao_i[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
            s1ao += numpy.einsum('x,xij->ij', x[ia], s1ao_i)

        s1vo = reduce(numpy.dot, (mo_coeff.T, s1ao, mocc))
        h1vo = reduce(numpy.dot, (mo_coeff.T, h1ao, mocc))
        mo1, mo_e1 = cphf.solve(fvind, mo_energy, mo_occ, h1vo, s1vo)
        mo1 = numpy.dot(mo_coeff, mo1)
        mo_e1 = mo_e1.reshape(nocc,nocc)
        dm1 = numpy.einsum('pi,qi->pq', mo1, mocc)
        dme1 = numpy.einsum('pi,qi,i->pq', mo1, mocc, mo_energy[mo_occ>0])
        dme1 = dme1 + dme1.T + reduce(numpy.dot, (mocc, mo_e1.T, mocc.T))

        for ja in range(natm):
            q0, q1 = aoslices[ja][2:]
            h1ao = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/%s'%ja)
            hx[ja] += numpy.einsum('xpq,pq->x', h1ao, dm1) * 4
            hx[ja] -= numpy.einsum('xpq,pq->x', s1a[:,q0:q1], dme1[q0:q1]) * 2
            hx[ja] -= numpy.einsum('xpq,qp->x', s1a[:,q0:q1], dme1[:,q0:q1]) * 2
        return hx.ravel()

    hdiag = numpy.einsum('aaxx->ax', de2).ravel()
    return h_op, hdiag
Beispiel #4
0
    def get_vind(self, zs):
        mol = self.mol
        mo_coeff = self._scf.mo_coeff
        mo_energy = self._scf.mo_energy
        nao, nmo = mo_coeff.shape
        nocc = (self._scf.mo_occ>0).sum()
        nvir = nmo - nocc
        orbv = mo_coeff[:,nocc:]
        orbo = mo_coeff[:,:nocc]
        eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])
        dai = numpy.sqrt(eai).ravel()

        nz = len(zs)
        dmvo = numpy.empty((nz,nao,nao))
        for i, z in enumerate(zs):
            dm = reduce(numpy.dot, (orbv, (dai*z).reshape(nvir,nocc), orbo.T))
            dmvo[i] = dm + dm.T # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B

        mem_now = lib.current_memory()[0]
        max_memory = max(2000, self.max_memory*.9-mem_now)
        v1ao = _contract_xc_kernel(self, self._scf.xc, dmvo,
                                   singlet=self.singlet, max_memory=max_memory)

        if self.singlet:
            vj = self._scf.get_j(mol, dmvo, hermi=1)
            v1ao += vj * 2

        v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc,nmo,0,nocc)).reshape(-1,nvir*nocc)
        edai = eai.ravel() * dai
        for i, z in enumerate(zs):
            # numpy.sqrt(eai) * (eai*dai*z + v1vo)
            v1vo[i] += edai*z
            v1vo[i] *= dai
        return v1vo.reshape(nz,-1)
Beispiel #5
0
def get_j_kpts(mydf, dm_kpts, hermi=1, kpts=numpy.zeros((1,3)), kpts_band=None):
    if kpts_band is not None:
        return get_j_for_bands(mydf, dm_kpts, hermi, kpts, kpts_band)

    dm_kpts = lib.asarray(dm_kpts, order='C')
    dms = _format_dms(dm_kpts, kpts)
    nset, nkpts, nao = dms.shape[:3]
    vj_kpts = numpy.zeros((nset,nkpts,nao,nao), dtype=numpy.complex128)
    kpt_allow = numpy.zeros(3)
    mesh = mydf.mesh
    coulG = mydf.weighted_coulG(kpt_allow, False, mesh)
    max_memory = (mydf.max_memory - lib.current_memory()[0]) * .8
    weight = 1./len(kpts)
    dmsC = dms.conj()
    for aoaoks, p0, p1 in mydf.ft_loop(mesh, kpt_allow, kpts, max_memory=max_memory):
        vG = [0] * nset
        #:rho = numpy.einsum('lkL,lk->L', pqk.conj(), dm)
        for k, aoao in enumerate(aoaoks):
            for i in range(nset):
                rho = numpy.einsum('ij,Lij->L', dmsC[i,k],
                                   aoao.reshape(-1,nao,nao)).conj()
                vG[i] += rho * coulG[p0:p1]
        for i in range(nset):
            vG[i] *= weight
        for k, aoao in enumerate(aoaoks):
            for i in range(nset):
                vj_kpts[i,k] += numpy.einsum('L,Lij->ij', vG[i],
                                             aoao.reshape(-1,nao,nao))
    aoao = aoaoks = p0 = p1 = None

    if gamma_point(kpts):
        vj_kpts = vj_kpts.real.copy()
    return _format_jks(vj_kpts, dm_kpts, kpts_band, kpts)
Beispiel #6
0
def _ERIS(mc, mo, method='incore'):
    nmo = mo.shape[1]
    ncore = mc.ncore
    ncas = mc.ncas

    mem_incore, mem_outcore, mem_basic = mc_ao2mo._mem_usage(ncore, ncas, nmo)
    mem_now = lib.current_memory()[0]
    if (method == 'incore' and mc._scf._eri is not None and
        (mem_incore+mem_now < mc.max_memory*.9) or
        mc.mol.incore_anyway):
        ppaa, papa, pacv, cvcv = trans_e1_incore(mc, mo)
    else:
        max_memory = max(2000, mc.max_memory-mem_now)
        ppaa, papa, pacv, cvcv = \
                trans_e1_outcore(mc, mo, max_memory=max_memory,
                                 verbose=mc.verbose)

    dmcore = numpy.dot(mo[:,:ncore], mo[:,:ncore].T)
    vj, vk = mc._scf.get_jk(mc.mol, dmcore)
    vhfcore = reduce(numpy.dot, (mo.T, vj*2-vk, mo))

    eris = {}
    eris['vhf_c'] = vhfcore
    eris['ppaa'] = ppaa
    eris['papa'] = papa
    eris['pacv'] = pacv
    eris['cvcv'] = cvcv
    eris['h1eff'] = reduce(numpy.dot, (mo.T, mc.get_hcore(), mo)) + vhfcore
    return eris
Beispiel #7
0
def kernel(casci, mo_coeff=None, ci0=None, verbose=logger.NOTE):
    '''UHF-CASCI solver
    '''
    if mo_coeff is None: mo_coeff = casci.mo_coeff
    log = logger.new_logger(casci, verbose)
    t0 = (time.clock(), time.time())
    log.debug('Start uhf-based CASCI')

    ncas = casci.ncas
    nelecas = casci.nelecas
    ncore = casci.ncore
    mo_core, mo_cas, mo_vir = extract_orbs(mo_coeff, ncas, nelecas, ncore)

    # 1e
    h1eff, energy_core = casci.h1e_for_cas(mo_coeff)
    log.debug('core energy = %.15g', energy_core)
    t1 = log.timer('effective h1e in CAS space', *t0)

    # 2e
    eri_cas = casci.get_h2eff(mo_cas)
    t1 = log.timer('integral transformation to CAS space', *t1)

    # FCI
    max_memory = max(400, casci.max_memory-lib.current_memory()[0])
    e_tot, fcivec = casci.fcisolver.kernel(h1eff, eri_cas, ncas, nelecas,
                                           ci0=ci0, verbose=log,
                                           max_memory=max_memory,
                                           ecore=energy_core)

    t1 = log.timer('FCI solver', *t1)
    e_cas = e_tot - energy_core
    return e_tot, e_cas, fcivec
Beispiel #8
0
    def build(self):
        t0 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        mol = self.mol
        auxmol = self.auxmol = incore.format_aux_basis(self.mol, self.auxbasis)
        nao = mol.nao_nr()
        naux = auxmol.nao_nr()
        nao_pair = nao*(nao+1)//2

        max_memory = (self.max_memory - lib.current_memory()[0]) * .8
        if nao_pair*naux*3*8/1e6 < max_memory:
            self._cderi = incore.cholesky_eri(mol, auxmol=auxmol, verbose=log)
        else:
            if not isinstance(self._cderi, str):
                if isinstance(self._cderi_file, str):
                    self._cderi = self._cderi_file
                else:
                    self._cderi = self._cderi_file.name
            outcore.cholesky_eri(mol, self._cderi, auxmol=auxmol, verbose=log)
            if nao_pair*nao*8/1e6 < max_memory:
                with addons.load(self._cderi) as feri:
                    cderi = numpy.asarray(feri)
                self._cderi = cderi
            log.timer_debug1('Generate density fitting integrals', *t0)

        return self
Beispiel #9
0
 def dump_flags(self):
     log = logger.Logger(self.stdout, self.verbose)
     log.info('\n')
     self._scf.dump_flags()
     log.info('******** %s Newton solver flags ********', self._scf.__class__)
     log.info('SCF tol = %g', self.conv_tol)
     log.info('conv_tol_grad = %s',    self.conv_tol_grad)
     log.info('max. SCF cycles = %d', self.max_cycle)
     log.info('direct_scf = %s', self._scf.direct_scf)
     if self._scf.direct_scf:
         log.info('direct_scf_tol = %g', self._scf.direct_scf_tol)
     if self.chkfile:
         log.info('chkfile to save SCF result = %s', self.chkfile)
     log.info('max_cycle_inner = %d',  self.max_cycle_inner)
     log.info('max_stepsize = %g', self.max_stepsize)
     log.info('ah_start_tol = %g',     self.ah_start_tol)
     log.info('ah_level_shift = %g',   self.ah_level_shift)
     log.info('ah_conv_tol = %g',      self.ah_conv_tol)
     log.info('ah_lindep = %g',        self.ah_lindep)
     log.info('ah_start_cycle = %d',   self.ah_start_cycle)
     log.info('ah_max_cycle = %d',     self.ah_max_cycle)
     log.info('ah_grad_trust_region = %g', self.ah_grad_trust_region)
     log.info('kf_interval = %d', self.kf_interval)
     log.info('kf_trust_region = %d', self.kf_trust_region)
     log.info('augmented hessian decay rate = %g', self.ah_decay_rate)
     log.info('max_memory %d MB (current use %d MB)',
              self.max_memory, lib.current_memory()[0])
Beispiel #10
0
        def get_hcore(self, mol=None):
            if mol is None: mol = self.mol
            if getattr(scf_method, 'get_hcore', None):
                h1e = method_class.get_hcore(self, mol)
            else:  # DO NOT modify post-HF objects to avoid the MM charges applied twice
                raise RuntimeError('mm_charge function cannot be applied on post-HF methods')

            if pyscf.DEBUG:
                v = 0
                for i,q in enumerate(charges):
                    mol.set_rinv_origin(coords[i])
                    v += mol.intor('int1e_rinv') * -q
            else:
                if mol.cart:
                    intor = 'int3c2e_cart'
                else:
                    intor = 'int3c2e_sph'
                nao = mol.nao
                max_memory = self.max_memory - lib.current_memory()[0]
                blksize = int(min(max_memory*1e6/8/nao**2, 200))
                v = 0
                for i0, i1 in lib.prange(0, charges.size, blksize):
                    fakemol = gto.fakemol_for_charges(coords[i0:i1])
                    j3c = df.incore.aux_e2(mol, fakemol, intor=intor, aosym='s2ij')
                    v += numpy.einsum('xk,k->x', j3c, -charges[i0:i1])
                v = lib.unpack_tril(v)
            return h1e + v
Beispiel #11
0
def get_pp_loc_part1(mydf, cell, kpts):
    log = logger.Logger(mydf.stdout, mydf.verbose)
    t1 = t0 = (time.clock(), time.time())
    nkpts = len(kpts)

    gs = mydf.gs
    nao = cell.nao_nr()
    Gv = cell.get_Gv(gs)
    SI = cell.get_SI(Gv)
    vpplocG = pseudo.pp_int.get_gth_vlocG_part1(cell, Gv)
    vpplocG = -1./cell.vol * numpy.einsum('ij,ij->j', SI, vpplocG)
    kpt_allow = numpy.zeros(3)
    real = gamma_point(kpts)

    if real:
        vloc = numpy.zeros((nkpts,nao**2))
    else:
        vloc = numpy.zeros((nkpts,nao**2), dtype=numpy.complex128)
    max_memory = mydf.max_memory - lib.current_memory()[0]
    for k, pqkR, pqkI, p0, p1 \
            in mydf.ft_loop(cell, mydf.gs, kpt_allow, kpts, max_memory=max_memory):
        vG = vpplocG[p0:p1]
        if not real:
            vloc[k] += numpy.einsum('k,xk->x', vG.real, pqkI) * 1j
            vloc[k] += numpy.einsum('k,xk->x', vG.imag, pqkR) *-1j
        vloc[k] += numpy.einsum('k,xk->x', vG.real, pqkR)
        vloc[k] += numpy.einsum('k,xk->x', vG.imag, pqkI)
        pqkR = pqkI = None
    t1 = log.timer_debug1('contracting vloc part1', *t1)
    return vloc.reshape(-1,nao,nao)
Beispiel #12
0
def energy(mycc, t1=None, t2=None, eris=None):
    '''CCSD correlation energy'''
    if t1 is None: t1 = mycc.t1
    if t2 is None: t2 = mycc.t2
    eris = getattr(mycc, '_eris', None)
    if eris is None:
        mycc.ao2mo()
        eris = mycc._eris

    nocc, nvir = t1.shape
    t2T = t2.transpose(2,3,0,1)
    fock = eris.fock
    loc0, loc1 = _task_location(nvir)
    e = numpy.einsum('ia,ia', fock[:nocc,nocc:], t1) * 2
    max_memory = mycc.max_memory - lib.current_memory()[0]
    blksize = int(min(nvir, max(BLKMIN, max_memory*.3e6/8/(nocc**2*nvir+1))))
    for p0, p1 in lib.prange(0, loc1-loc0, blksize):
        eris_ovov = eris.ovov[:,p0:p1]
        tau = t2T[p0:p1] + numpy.einsum('ia,jb->abij', t1[:,p0+loc0:p1+loc0], t1)
        e += 2 * numpy.einsum('abij,iajb', tau, eris_ovov)
        e -=     numpy.einsum('abji,iajb', tau, eris_ovov)
    e = comm.allreduce(e)

    if rank == 0 and abs(e.imag) > 1e-4:
        logger.warn(mycc, 'Non-zero imaginary part found in CCSD energy %s', e)
    return e.real
Beispiel #13
0
def init_amps(mycc, eris=None):
    eris = getattr(mycc, '_eris', None)
    if eris is None:
        mycc.ao2mo()
        eris = mycc._eris

    time0 = time.clock(), time.time()
    mo_e = eris.mo_energy
    nocc = mycc.nocc
    nvir = mo_e.size - nocc
    eia = mo_e[:nocc,None] - mo_e[None,nocc:]
    t1T = eris.fock[nocc:,:nocc] / eia.T
    loc0, loc1 = _task_location(nvir)

    t2T = numpy.empty((loc1-loc0,nvir,nocc,nocc))
    max_memory = mycc.max_memory - lib.current_memory()[0]
    blksize = int(min(nvir, max(BLKMIN, max_memory*.3e6/8/(nocc**2*nvir+1))))
    emp2 = 0
    for p0, p1 in lib.prange(0, loc1-loc0, blksize):
        eris_ovov = eris.ovov[:,p0:p1]
        t2T[p0:p1] = (eris_ovov.transpose(1,3,0,2) /
                      lib.direct_sum('ia,jb->abij', eia[:,p0+loc0:p1+loc0], eia))
        emp2 += 2 * numpy.einsum('abij,iajb', t2T[p0:p1], eris_ovov)
        emp2 -=     numpy.einsum('abji,iajb', t2T[p0:p1], eris_ovov)

    mycc.emp2 = comm.allreduce(emp2)
    logger.info(mycc, 'Init t2, MP2 energy = %.15g', mycc.emp2)
    logger.timer(mycc, 'init mp2', *time0)
    return mycc.emp2, t1T.T, t2T.transpose(2,3,0,1)
Beispiel #14
0
Datei: hf.py Projekt: sunqm/pyscf
 def _is_mem_enough(self):
     nao = self.cell.nao_nr()
     if abs(self.kpt).sum() < 1e-9:
         mem_need = nao**4*8/4/1e6
     else:
         mem_need = nao**4*16/1e6
     return mem_need + lib.current_memory()[0] < self.max_memory*.95
Beispiel #15
0
def kernel(casci, mo_coeff=None, ci0=None, verbose=logger.NOTE):
    '''CASCI solver
    '''
    if mo_coeff is None: mo_coeff = casci.mo_coeff
    log = logger.new_logger(casci, verbose)
    t0 = (time.clock(), time.time())
    log.debug('Start CASCI')

    ncas = casci.ncas
    nelecas = casci.nelecas

    # 2e
    eri_cas = casci.get_h2eff(mo_coeff)
    t1 = log.timer('integral transformation to CAS space', *t0)

    # 1e
    h1eff, energy_core = casci.get_h1eff(mo_coeff)
    log.debug('core energy = %.15g', energy_core)
    t1 = log.timer('effective h1e in CAS space', *t1)

    if h1eff.shape[0] != ncas:
        raise RuntimeError('Active space size error. nmo=%d ncore=%d ncas=%d' %
                           (mo_coeff.shape[1], casci.ncore, ncas))

    # FCI
    max_memory = max(400, casci.max_memory-lib.current_memory()[0])
    e_tot, fcivec = casci.fcisolver.kernel(h1eff, eri_cas, ncas, nelecas,
                                           ci0=ci0, verbose=log,
                                           max_memory=max_memory,
                                           ecore=energy_core)

    t1 = log.timer('FCI solver', *t1)
    e_cas = e_tot - energy_core
    return e_tot, e_cas, fcivec
Beispiel #16
0
def kernel(casci, mo_coeff=None, ci0=None, verbose=logger.NOTE):
    '''CASCI solver
    '''
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(casci.stdout, verbose)
    if mo_coeff is None: mo_coeff = casci.mo_coeff
    t0 = (time.clock(), time.time())
    log.debug('Start CASCI')

    ncas = casci.ncas
    nelecas = casci.nelecas

    # 2e
    eri_cas = casci.get_h2eff(mo_coeff)
    t1 = log.timer('integral transformation to CAS space', *t0)

    # 1e
    h1eff, energy_core = casci.get_h1eff(mo_coeff)
    log.debug('core energy = %.15g', energy_core)
    t1 = log.timer('effective h1e in CAS space', *t1)

    # FCI
    max_memory = max(400, casci.max_memory-lib.current_memory()[0])
    e_tot, fcivec = casci.fcisolver.kernel(h1eff, eri_cas, ncas, nelecas,
                                           ci0=ci0, verbose=log,
                                           max_memory=max_memory,
                                           ecore=energy_core)

    t1 = log.timer('FCI solver', *t1)
    e_cas = e_tot - energy_core
    return e_tot, e_cas, fcivec
Beispiel #17
0
    def __init__(self, mycc):
        self._cc = mycc
        self.daemon = None

        nocc, nvir = mycc.t1.shape
        nmo = nocc + nvir
        nvir_seg = (nvir + mpi.pool.size - 1) // mpi.pool.size
        max_memory = mycc.max_memory - lib.current_memory()[0]
        max_memory = max(0, max_memory - nocc**3*13*lib.num_threads()*8/1e6)
        blksize = max(BLKMIN, (max_memory*.5e6/8/(6*nmo*nocc))**.5 - nocc/4)
        blksize = int(min(comm.allgather(min(nvir/6+2, nvir_seg/2+1, blksize))))
        logger.debug1(mycc, 'GlobalDataHandler blksize %s', blksize)

        self.vranges = []
        self.data_partition = []
        self.segment_location = {}
        for task in range(mpi.pool.size):
            p0 = nvir_seg * task
            p1 = min(nvir, p0 + nvir_seg)
            self.vranges.append((p0, p1))

            for j0, j1 in lib.prange(p0, p1, blksize):
                self.data_partition.append((j0, j1))
                self.segment_location[j0] = task
        logger.debug1(mycc, 'data_partition %s', self.data_partition)
        logger.debug1(mycc, 'segment_location %s', self.segment_location)
Beispiel #18
0
def get_nuc_less_accurate(mydf, kpts=None):
    log = logger.Logger(mydf.stdout, mydf.verbose)
    t1 = t0 = (time.clock(), time.time())
    if kpts is None:
        kpts_lst = numpy.zeros((1, 3))
    else:
        kpts_lst = numpy.reshape(kpts, (-1, 3))
    nkpts = len(kpts_lst)
    if mydf._cderi is None:
        mydf.build()
    cell = mydf.cell
    fused_cell, fuse = fuse_auxcell_(mydf, mydf.auxcell)

    nao = cell.nao_nr()
    charge = -cell.atom_charges()
    j2c = pgto.intor_cross("cint2c2e_sph", fused_cell, _fake_nuc(cell))
    jaux = j2c.dot(charge)
    jaux -= charge.sum() * mydf.auxbar(fused_cell)
    Gv = cell.get_Gv(mydf.gs)
    SI = cell.get_SI(Gv)
    # The normal nuclues have been considered in function get_gth_vlocG_part1
    # The result vG is the potential in G-space for erf part of the pp nuclues and
    # "numpy.dot(charge, SI) * coulG" for normal nuclues.
    vpplocG = pgto.pseudo.pp_int.get_gth_vlocG_part1(cell, Gv)
    vG = -1.0 / cell.vol * numpy.einsum("ij,ij->j", SI, vpplocG)
    kpt_allow = numpy.zeros(3)

    if is_zero(kpts_lst):
        vj = numpy.zeros((nkpts, nao ** 2))
    else:
        vj = numpy.zeros((nkpts, nao ** 2), dtype=numpy.complex128)
    max_memory = max(2000, mydf.max_memory - lib.current_memory()[0])
    for k, pqkR, pqkI, p0, p1 in mydf.ft_loop(cell, mydf.gs, kpt_allow, kpts_lst, max_memory=max_memory):
        if not gamma_point(kpts_lst[k]):
            vj[k] += numpy.einsum("k,xk->x", vG.real, pqkI) * 1j
            vj[k] += numpy.einsum("k,xk->x", vG.imag, pqkR) * -1j
        vj[k] += numpy.einsum("k,xk->x", vG.real, pqkR)
        vj[k] += numpy.einsum("k,xk->x", vG.imag, pqkI)
        pqkR = pqkI = None

    Gv = cell.get_Gv(mydf.gs)
    aoaux = ft_ao.ft_ao(fused_cell, Gv)
    jaux -= numpy.einsum("x,xj->j", vG.real, aoaux.real)
    jaux -= numpy.einsum("x,xj->j", vG.imag, aoaux.imag)
    jaux = fuse(jaux)

    vj = vj.reshape(-1, nao, nao)
    for k, kpt in enumerate(kpts_lst):
        with mydf.load_Lpq((kpt, kpt)) as Lpq:
            v = 0
            for p0, p1 in lib.prange(0, jaux.size, mydf.blockdim):
                v += numpy.dot(jaux[p0:p1], numpy.asarray(Lpq[p0:p1]))
            if gamma_point(kpt):
                vj[k] += lib.unpack_tril(numpy.asarray(v.real, order="C"))
            else:
                vj[k] += lib.unpack_tril(v)

    if kpts is None or numpy.shape(kpts) == (3,):
        vj = vj[0]
    return vj
Beispiel #19
0
def make_h1(hessobj, mo_coeff, mo_occ, chkfile=None, atmlst=None, verbose=None):
    mol = hessobj.mol
    if atmlst is None:
        atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    dm0 = numpy.dot(mocc, mocc.T) * 2
    hcore_deriv = hessobj.base.nuc_grad_method().hcore_generator(mol)

    mf = hessobj.base
    ni = mf._numint
    ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory*.9-mem_now)
    h1ao = _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory)
    aoslices = mol.aoslice_by_atom()
    for i0, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        shls_slice = (shl0, shl1) + (0, mol.nbas)*3
        if abs(hyb) > 1e-10:
            vj1, vj2, vk1, vk2 = \
                    rhf_hess._get_jk(mol, 'int2e_ip1', 3, 's2kl',
                                     ['ji->s2kl', -dm0[:,p0:p1],  # vj1
                                      'lk->s1ij', -dm0         ,  # vj2
                                      'li->s1kj', -dm0[:,p0:p1],  # vk1
                                      'jk->s1il', -dm0         ], # vk2
                                     shls_slice=shls_slice)
            veff = vj1 - hyb * .5 * vk1
            veff[:,p0:p1] += vj2 - hyb * .5 * vk2
            if abs(omega) > 1e-10:
                with mol.with_range_coulomb(omega):
                    vk1, vk2 = \
                        rhf_hess._get_jk(mol, 'int2e_ip1', 3, 's2kl',
                                         ['li->s1kj', -dm0[:,p0:p1],  # vk1
                                          'jk->s1il', -dm0         ], # vk2
                                         shls_slice=shls_slice)
                veff -= (alpha-hyb) * .5 * vk1
                veff[:,p0:p1] -= (alpha-hyb) * .5 * vk2
        else:
            vj1, vj2 = rhf_hess._get_jk(mol, 'int2e_ip1', 3, 's2kl',
                                        ['ji->s2kl', -dm0[:,p0:p1],  # vj1
                                         'lk->s1ij', -dm0         ], # vj2
                                        shls_slice=shls_slice)
            veff = vj1
            veff[:,p0:p1] += vj2

        h1ao[ia] += veff + veff.transpose(0,2,1)
        h1ao[ia] += hcore_deriv(ia)

    if chkfile is None:
        return h1ao
    else:
        for ia in atmlst:
            lib.chkfile.save(chkfile, 'scf_f1ao/%d'%ia, h1ao[ia])
        return chkfile
Beispiel #20
0
 def get_block_size(self):
     #return 8
     nmo = self.nmo
     nocc = self.nocc
     nvir = nmo - nocc
     unit = _memory_usage_inloop(nmo, nocc)*1e6/8
     rest = (self.max_memory-lib.current_memory()[0])*1e6/8*.9 \
             - nocc**4 - nocc**3*nvir - (nocc*nvir)**2*2
     return min(nocc, max(1, int(rest/unit/8)*8))
Beispiel #21
0
def _make_eris_outcore(mycc, mo_coeff=None):
    cput0 = (time.clock(), time.time())
    log = logger.Logger(mycc.stdout, mycc.verbose)
    eris = _ChemistsERIs()
    eris._common_init_(mycc, mo_coeff)

    mol = mycc.mol
    mo_coeff = eris.mo_coeff
    nocc = eris.nocc
    nao, nmo = mo_coeff.shape
    nvir = nmo - nocc
    orbo = mo_coeff[:,:nocc]
    orbv = mo_coeff[:,nocc:]
    nvpair = nvir * (nvir+1) // 2
    eris.feri1 = lib.H5TmpFile()
    eris.oooo = eris.feri1.create_dataset('oooo', (nocc,nocc,nocc,nocc), 'f8')
    eris.ovoo = eris.feri1.create_dataset('ovoo', (nocc,nvir,nocc,nocc), 'f8', chunks=(nocc,1,nocc,nocc))
    eris.ovov = eris.feri1.create_dataset('ovov', (nocc,nvir,nocc,nvir), 'f8', chunks=(nocc,1,nocc,nvir))
    eris.ovvo = eris.feri1.create_dataset('ovvo', (nocc,nvir,nvir,nocc), 'f8', chunks=(nocc,1,nvir,nocc))
    eris.ovvv = eris.feri1.create_dataset('ovvv', (nocc,nvir,nvir,nvir), 'f8')
    eris.oovv = eris.feri1.create_dataset('oovv', (nocc,nocc,nvir,nvir), 'f8', chunks=(nocc,nocc,1,nvir))
    eris.vvvv = eris.feri1.create_dataset('vvvv', (nvir,nvir,nvir,nvir), 'f8')
    max_memory = max(MEMORYMIN, mycc.max_memory-lib.current_memory()[0])

    ftmp = lib.H5TmpFile()
    ao2mo.full(mol, mo_coeff, ftmp, max_memory=max_memory, verbose=log)
    eri = ftmp['eri_mo']

    nocc_pair = nocc*(nocc+1)//2
    tril2sq = lib.square_mat_in_trilu_indices(nmo)
    oo = eri[:nocc_pair]
    eris.oooo[:] = ao2mo.restore(1, oo[:,:nocc_pair], nocc)
    oovv = lib.take_2d(oo, tril2sq[:nocc,:nocc].ravel(), tril2sq[nocc:,nocc:].ravel())
    eris.oovv[:] = oovv.reshape(nocc,nocc,nvir,nvir)
    oo = oovv = None

    tril2sq = lib.square_mat_in_trilu_indices(nmo)
    blksize = min(nvir, max(BLKMIN, int(max_memory*1e6/8/nmo**3/2)))
    for p0, p1 in lib.prange(0, nvir, blksize):
        q0, q1 = p0+nocc, p1+nocc
        off0 = q0*(q0+1)//2
        off1 = q1*(q1+1)//2
        buf = lib.unpack_tril(eri[off0:off1])

        tmp = buf[ tril2sq[q0:q1,:nocc] - off0 ]
        eris.ovoo[:,p0:p1] = tmp[:,:,:nocc,:nocc].transpose(1,0,2,3)
        eris.ovvo[:,p0:p1] = tmp[:,:,nocc:,:nocc].transpose(1,0,2,3)
        eris.ovov[:,p0:p1] = tmp[:,:,:nocc,nocc:].transpose(1,0,2,3)
        eris.ovvv[:,p0:p1] = tmp[:,:,nocc:,nocc:].transpose(1,0,2,3)

        tmp = buf[ tril2sq[q0:q1,nocc:q1] - off0 ]
        eris.vvvv[p0:p1,:p1] = tmp[:,:,nocc:,nocc:]
        if p0 > 0:
            eris.vvvv[:p0,p0:p1] = tmp[:,:p0,nocc:,nocc:].transpose(1,0,2,3)
        buf = tmp = None
    log.timer('CCSD integral transformation', *cput0)
    return eris
Beispiel #22
0
 def kernel(self, t1=None, t2=None):
     eris = self.ao2mo()
     self._conv, self.ecc, self.t1, self.t2 = \
             kernel(self, eris, t1, t2, max_cycle=self.max_cycle,
                    tol=self.conv_tol,
                    tolnormt=self.conv_tol_normt,
                    max_memory=self.max_memory-lib.current_memory()[0],
                    verbose=self.verbose)
     return self.ecc, self.t1, self.t2
Beispiel #23
0
 def dump_flags(self):
     log = logger.Logger(self.stdout, self.verbose)
     log.info('')
     log.info('******** %s ********', self.__class__)
     log.info('nocc = %s, nmo = %s', self.nocc, self.nmo)
     if self.frozen is not 0:
         log.info('frozen orbitals %s', self.frozen)
     log.info('max_memory %d MB (current use %d MB)',
              self.max_memory, lib.current_memory()[0])
     return self
Beispiel #24
0
    def ao2mo(self, mo_coeff=None):
        nkpts = self.nkpts
        nmo = self.nmo
        mem_incore = nkpts**3 * nmo**4 * 8 / 1e6
        mem_now = lib.current_memory()[0]

        if (mem_incore + mem_now < self.max_memory) or self.mol.incore_anyway:
            return _make_eris_incore(self, mo_coeff)
        else:
            raise NotImplementedError
Beispiel #25
0
 def dump_flags(self):
     log = logger.Logger(self.stdout, self.verbose)
     log.info('\n')
     if not self.base.converged:
         log.warn('Ground state CASSCF not converged')
     log.info('******** %s for %s ********',
              self.__class__, self.base.__class__)
     log.info('max_memory %d MB (current use %d MB)',
              self.max_memory, lib.current_memory()[0])
     return self
Beispiel #26
0
def _make_eris(mp, mo_coeff=None, ao2mofn=None, verbose=None):
    log = logger.new_logger(mp, verbose)
    time0 = (time.clock(), time.time())
    eris = _ChemistsERIs(mp, mo_coeff)

    nocca, noccb = mp.get_nocc()
    nmoa, nmob = mp.get_nmo()
    nvira, nvirb = nmoa-nocca, nmob-noccb
    nao = eris.mo_coeff[0].shape[0]
    nmo_pair = nmoa * (nmoa+1) // 2
    nao_pair = nao * (nao+1) // 2
    mem_incore = (nao_pair**2 + nmo_pair**2) * 8/1e6
    mem_now = lib.current_memory()[0]
    max_memory = max(0, mp.max_memory-mem_now)

    moa = eris.mo_coeff[0]
    mob = eris.mo_coeff[1]
    orboa = moa[:,:nocca]
    orbob = mob[:,:noccb]
    orbva = moa[:,nocca:]
    orbvb = mob[:,noccb:]

    if (mp.mol.incore_anyway or
        (mp._scf._eri is not None and mem_incore+mem_now < mp.max_memory)):
        log.debug('transform (ia|jb) incore')
        if callable(ao2mofn):
            eris.ovov = ao2mofn((orboa,orbva,orboa,orbva)).reshape(nocca*nvira,nocca*nvira)
            eris.ovOV = ao2mofn((orboa,orbva,orbob,orbvb)).reshape(nocca*nvira,noccb*nvirb)
            eris.OVOV = ao2mofn((orbob,orbvb,orbob,orbvb)).reshape(noccb*nvirb,noccb*nvirb)
        else:
            eris.ovov = ao2mo.general(mp._scf._eri, (orboa,orbva,orboa,orbva))
            eris.ovOV = ao2mo.general(mp._scf._eri, (orboa,orbva,orbob,orbvb))
            eris.OVOV = ao2mo.general(mp._scf._eri, (orbob,orbvb,orbob,orbvb))

    elif getattr(mp._scf, 'with_df', None):
        logger.warn(mp, 'UMP2 detected DF being used in the HF object. '
                    'MO integrals are computed based on the DF 3-index tensors.\n'
                    'It\'s recommended to use DF-UMP2 module.')
        log.debug('transform (ia|jb) with_df')
        eris.ovov = mp._scf.with_df.ao2mo((orboa,orbva,orboa,orbva))
        eris.ovOV = mp._scf.with_df.ao2mo((orboa,orbva,orbob,orbvb))
        eris.OVOV = mp._scf.with_df.ao2mo((orbob,orbvb,orbob,orbvb))

    else:
        log.debug('transform (ia|jb) outcore')
        eris.feri = lib.H5TmpFile()
        _ao2mo_ovov(mp, (orboa,orbva,orbob,orbvb), eris.feri,
                    max(2000, max_memory), log)
        eris.ovov = eris.feri['ovov']
        eris.ovOV = eris.feri['ovOV']
        eris.OVOV = eris.feri['OVOV']

    time1 = log.timer('Integral transformation', *time0)
    return eris
Beispiel #27
0
def get_eri(mydf, kpts=None,
            compact=getattr(__config__, 'pbc_df_ao2mo_get_eri_compact', True)):
    cell = mydf.cell
    nao = cell.nao_nr()
    kptijkl = _format_kpts(kpts)
    if not _iskconserv(cell, kptijkl):
        lib.logger.warn(cell, 'fft_ao2mo: momentum conservation not found in '
                        'the given k-points %s', kptijkl)
        return numpy.zeros((nao,nao,nao,nao))

    kpti, kptj, kptk, kptl = kptijkl
    q = kptj - kpti
    coulG = tools.get_coulG(cell, q, mesh=mydf.mesh)
    coords = cell.gen_uniform_grids(mydf.mesh)
    max_memory = mydf.max_memory - lib.current_memory()[0]

####################
# gamma point, the integral is real and with s4 symmetry
    if gamma_point(kptijkl):
        #:ao_pairs_G = get_ao_pairs_G(mydf, kptijkl[:2], q, compact=compact)
        #:ao_pairs_G *= numpy.sqrt(coulG).reshape(-1,1)
        #:eri = lib.dot(ao_pairs_G.T, ao_pairs_G, cell.vol/ngrids**2)
        ao = mydf._numint.eval_ao(cell, coords, kpti)[0]
        ao = numpy.asarray(ao.T, order='C')
        eri = _contract_compact(mydf, (ao,ao), coulG, max_memory=max_memory)
        if not compact:
            eri = ao2mo.restore(1, eri, nao).reshape(nao**2,nao**2)
        return eri

####################
# aosym = s1, complex integrals
    else:
        #:ao_pairs_G = get_ao_pairs_G(mydf, kptijkl[:2], q, compact=False)
        #:# ao_pairs_invG = rho_kl(-(G+k_ij)) = conj(rho_lk(G+k_ij)).swap(r,s)
        #:#=get_ao_pairs_G(mydf, [kptl,kptk], q, compact=False).transpose(0,2,1).conj()
        #:ao_pairs_invG = get_ao_pairs_G(mydf, -kptijkl[2:], q, compact=False).conj()
        #:ao_pairs_G *= coulG.reshape(-1,1)
        #:eri = lib.dot(ao_pairs_G.T, ao_pairs_invG, cell.vol/ngrids**2)
        if is_zero(kpti-kptl) and is_zero(kptj-kptk):
            if is_zero(kpti-kptj):
                aoi = mydf._numint.eval_ao(cell, coords, kpti)[0]
                aoi = aoj = numpy.asarray(aoi.T, order='C')
            else:
                aoi, aoj = mydf._numint.eval_ao(cell, coords, kptijkl[:2])
                aoi = numpy.asarray(aoi.T, order='C')
                aoj = numpy.asarray(aoj.T, order='C')
            aos = (aoi, aoj, aoj, aoi)
        else:
            aos = mydf._numint.eval_ao(cell, coords, kptijkl)
            aos = [numpy.asarray(x.T, order='C') for x in aos]
        fac = numpy.exp(-1j * numpy.dot(coords, q))
        max_memory = max_memory - aos[0].nbytes*4*1e-6
        eri = _contract_plain(mydf, aos, coulG, fac, max_memory=max_memory)
        return eri
Beispiel #28
0
 def ao2mo(self, mo_coeff=None):
     nmo = self.nmo
     mem_incore = nmo**4*2 * 8/1e6
     mem_now = lib.current_memory()[0]
     if (self._scf._eri is not None and
         (mem_incore+mem_now < self.max_memory) or self.mol.incore_anyway):
         return gccsd._make_eris_incore(self, mo_coeff)
     elif getattr(self._scf, 'with_df', None):
         raise NotImplementedError
     else:
         return gccsd._make_eris_outcore(self, mo_coeff)
Beispiel #29
0
    def get_vind(self, xys):
        '''
        [ A  B][X]
        [-B -A][Y]
        '''
        mol = self.mol
        mo_coeff = self._scf.mo_coeff
        mo_energy = self._scf.mo_energy
        nao, nmo = mo_coeff.shape
        nocc = (self._scf.mo_occ>0).sum()
        nvir = nmo - nocc
        orbv = mo_coeff[:,nocc:]
        orbo = mo_coeff[:,:nocc]
        nz = len(xys)
        dms = numpy.empty((nz*2,nao,nao))
        for i in range(nz):
            x, y = xys[i].reshape(2,nvir,nocc)
            dmx = reduce(numpy.dot, (orbv, x, orbo.T))
            dmy = reduce(numpy.dot, (orbv, y, orbo.T))
            dms[i   ] = dmx + dmy.T  # AX + BY
            dms[i+nz] = dms[i].T # = dmy + dmx.T  # AY + BX

        hyb = self._scf._numint.hybrid_coeff(self._scf.xc, spin=(mol.spin>0)+1)

        if abs(hyb) > 1e-10:
            vj, vk = self._scf.get_jk(self.mol, dms, hermi=0)
            if self.singlet:
                veff = vj * 2 - hyb * vk
            else:
                veff = -hyb * vk
        else:
            if self.singlet:
                vj = self._scf.get_j(self.mol, dms, hermi=1)
                veff = vj * 2
            else:
                veff = numpy.zeros((nz*2,nao,nao))

        mem_now = lib.current_memory()[0]
        max_memory = max(2000, self.max_memory*.9-mem_now)
        v1xc = _contract_xc_kernel(self, self._scf.xc, dms[:nz],
                                   singlet=self.singlet, max_memory=max_memory)
        veff[:nz] += v1xc
        veff[nz:] += v1xc

        veff = _ao2mo.nr_e2(veff, mo_coeff, (nocc,nmo,0,nocc)).reshape(-1,nvir*nocc)
        eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])
        eai = eai.ravel()
        for i, z in enumerate(xys):
            x, y = z.reshape(2,-1)
            veff[i   ] += eai * x  # AX
            veff[i+nz] += eai * y  # AY
        hx = numpy.hstack((veff[:nz], -veff[nz:]))
        return hx.reshape(nz,-1)
Beispiel #30
0
def _aft_quad_integrals(mydf, dm, efg_nuc):
    # Use AFTDF to compute the integrals of quadrupole operator 
    # (3 \vec{r} \vec{r} - r^2) / r^5
    cell = mydf.cell
    if cell.dimension != 3:
        raise NotImplementedError

    log = lib.logger.new_logger(mydf)
    t0 = t1 = (time.clock(), time.time())

    mesh = mydf.mesh
    kpts = mydf.kpts
    kpts_lst = numpy.reshape(kpts, (-1,3))
    nkpts = len(kpts_lst)
    nao = cell.nao_nr()
    dm_kpts = dm.reshape((nkpts,nao,nao), order='C')

    ngrids = numpy.prod(mesh)
    rhoG = numpy.zeros(ngrids, dtype=numpy.complex128)
    kpt_allow = numpy.zeros(3)
    max_memory = max(2000, mydf.max_memory-lib.current_memory()[0])
    for aoaoks, p0, p1 in mydf.ft_loop(mesh, kpt_allow, kpts_lst,
                                       max_memory=max_memory, aosym='s1'):
        rhoG[p0:p1] = numpy.einsum('kgpq,kqp->g', aoaoks.reshape(nkpts,p1-p0,nao,nao),
                                   dm_kpts)
        t1 = log.timer_debug1('contracting Vnuc [%s:%s]'%(p0, p1), *t1)
    t0 = log.timer_debug1('contracting Vnuc', *t0)
    rhoG *= 1./nkpts

    Gv, Gvbase, kws = cell.get_Gv_weights(mesh)
    coulG = tools.get_coulG(cell, mesh=mesh, Gv=Gv)
    GG = numpy.einsum('gx,gy->gxy', Gv, Gv)
    absG2 = numpy.einsum('gxx->g', GG)

    # Corresponding to FC term, that makes the tensor traceless
    idx = numpy.arange(3)
    GG[:,idx,idx] -= 1./3 * absG2[:,None]
    vG = 1./cell.vol * numpy.einsum('g,g,gxy->gxy', rhoG, coulG, GG)

    if mydf.eta == 0:
        SI = cell.get_SI(Gv)
        efg_e = numpy.einsum('zg,gxy->zxy', SI[efg_nuc], vG.conj()).real

    else:
        nuccell = aft._compensate_nuccell(mydf)
        # PP-loc part1 is handled by fakenuc in _int_nuc_vloc
        efg_e = _int_nuc_vloc(mydf, nuccell, kpts_lst, dm_kpts)
        t0 = log.timer_debug1('vnuc pass1: analytic int', *t0)

        aoaux = df.ft_ao.ft_ao(nuccell, Gv)
        efg_e += numpy.einsum('gz,gxy->zxy', aoaux[:,efg_nuc], vG.conj()).real
    return efg_e
Beispiel #31
0
def update_lambda(mycc, t1, t2, l1, l2, eris=None, imds=None):
    if imds is None: imds = make_intermediates(mycc, t1, t2, eris)
    time1 = time0 = time.clock(), time.time()
    log = logger.Logger(mycc.stdout, mycc.verbose)
    nocc, nvir = t1.shape
    nov = nocc * nvir
    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 = tmp1 = 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 = m4buf = 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 = tmp1 = tmp_ovov = 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
    ij = 0
    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 #32
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.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
    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 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 = mycc.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)
    nvira = nmoa - nocca
    nvirb = nmob - noccb
    with_frozen = not (mycc.frozen is None or mycc.frozen is 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')
    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)

    de += mf_grad.grad_nuc(mol)
    log.timer('%s gradients' % mycc.__class__.__name__, *time0)
    return de
Beispiel #33
0
def get_eri(mydf, kpts=None, compact=True):
    if mydf._cderi is None:
        mydf.build()

    cell = mydf.cell
    kptijkl = _format_kpts(kpts)
    kpti, kptj, kptk, kptl = kptijkl
    nao = cell.nao_nr()
    nao_pair = nao * (nao+1) // 2
    max_memory = max(2000, mydf.max_memory-lib.current_memory()[0]-nao**4*8/1e6)

####################
# gamma point, the integral is real and with s4 symmetry
    if gamma_point(kptijkl):
        eriR = numpy.zeros((nao_pair,nao_pair))
        for LpqR, LpqI in mydf.sr_loop(kptijkl[:2], max_memory, True):
            lib.ddot(LpqR.T, LpqR, 1, eriR, 1)
            LpqR = LpqI = None
        if not compact:
            eriR = ao2mo.restore(1, eriR, nao).reshape(nao**2,-1)
        return eriR

    elif is_zero(kpti-kptk) and is_zero(kptj-kptl):
        eriR = numpy.zeros((nao*nao,nao*nao))
        eriI = numpy.zeros((nao*nao,nao*nao))
        for LpqR, LpqI in mydf.sr_loop(kptijkl[:2], max_memory, False):
            zdotNN(LpqR.T, LpqI.T, LpqR, LpqI, 1, eriR, eriI, 1)
            LpqR = LpqI = None
        return eriR + eriI*1j

####################
# (kpt) i == j == k == l != 0
#
# (kpt) i == l && j == k && i != j && j != k  =>
# both vbar and ovlp are zero. It corresponds to the exchange integral.
#
# complex integrals, N^4 elements
    elif is_zero(kpti-kptl) and is_zero(kptj-kptk):
        eriR = numpy.zeros((nao*nao,nao*nao))
        eriI = numpy.zeros((nao*nao,nao*nao))
        for LpqR, LpqI in mydf.sr_loop(kptijkl[:2], max_memory, False):
            zdotNC(LpqR.T, LpqI.T, LpqR, LpqI, 1, eriR, eriI, 1)
            LpqR = LpqI = None
# transpose(0,1,3,2) because
# j == k && i == l  =>
# (L|ij).transpose(0,2,1).conj() = (L^*|ji) = (L^*|kl)  =>  (M|kl)
        eri = lib.transpose((eriR+eriI*1j).reshape(-1,nao,nao), axes=(0,2,1))
        return eri.reshape(nao**2,-1)

####################
# aosym = s1, complex integrals
#
# kpti == kptj  =>  kptl == kptk
# If kpti == kptj, (kptl-kptk)*a has to be multiples of 2pi because of the wave
# vector symmetry.  k is a fraction of reciprocal basis, 0 < k/b < 1, by definition.
# So  kptl/b - kptk/b  must be -1 < k/b < 1.
#
    else:
        eriR = numpy.zeros((nao*nao,nao*nao))
        eriI = numpy.zeros((nao*nao,nao*nao))
        for (LpqR, LpqI), (LrsR, LrsI) in \
                lib.izip(mydf.sr_loop(kptijkl[:2], max_memory, False),
                         mydf.sr_loop(kptijkl[2:], max_memory, False)):
            zdotNN(LpqR.T, LpqI.T, LrsR, LrsI, 1, eriR, eriI, 1)
            LpqR = LpqI = LrsR = LrsI = None
        return eriR + eriI*1j
Beispiel #34
0
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None):
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if with_symmetry and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbida = orbsyma[viridxa].reshape(-1, 1) != orbsyma[occidxa]
        sym_forbidb = orbsymb[viridxb].reshape(-1, 1) != orbsymb[occidxb]
        sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    h1e = mf.get_hcore()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    fock_ao = h1e + mf.get_veff(mol, dm0)
    focka = reduce(numpy.dot, (mo_coeff[0].T, fock_ao[0], mo_coeff[0]))
    fockb = reduce(numpy.dot, (mo_coeff[1].T, fock_ao[1], mo_coeff[1]))
    fooa = focka[occidxa[:, None], occidxa]
    fvva = focka[viridxa[:, None], viridxa]
    foob = fockb[occidxb[:, None], occidxb]
    fvvb = fockb[viridxb[:, None], viridxb]

    h_diaga = (focka[viridxa, viridxa].reshape(-1, 1) -
               focka[occidxa, occidxa])
    h_diagb = (fockb[viridxb, viridxb].reshape(-1, 1) -
               fockb[occidxb, occidxb])
    hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1)))
    if with_symmetry and mol.symmetry:
        hdiag1[sym_forbid1] = 0

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)

    vrespz = _gen_uhf_response(mf, with_j=False, hermi=2)

    def hop_real2complex(x1):
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid1] = 0
        x1a = x1[:nvira * nocca].reshape(nvira, nocca)
        x1b = x1[nvira * nocca:].reshape(nvirb, noccb)
        x2a = numpy.einsum('pr,rq->pq', fvva, x1a)
        x2a -= numpy.einsum('sq,ps->pq', fooa, x1a)
        x2b = numpy.einsum('pr,rq->pq', fvvb, x1b)
        x2b -= numpy.einsum('qs,ps->pq', foob, x1b)

        d1a = reduce(numpy.dot, (orbva, x1a, orboa.T.conj()))
        d1b = reduce(numpy.dot, (orbvb, x1b, orbob.T.conj()))
        dm1 = numpy.array((d1a - d1a.T.conj(), d1b - d1b.T.conj()))

        v1 = vrespz(dm1)
        x2a += reduce(numpy.dot, (orbva.T.conj(), v1[0], orboa))
        x2b += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orbob))
        x2 = numpy.hstack((x2a.ravel(), x2b.ravel()))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid1] = 0
        return x2

    if with_symmetry and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbidab = orbsyma[viridxa].reshape(-1, 1) != orbsymb[occidxb]
        sym_forbidba = orbsymb[viridxb].reshape(-1, 1) != orbsyma[occidxa]
        sym_forbid2 = numpy.hstack(
            (sym_forbidab.ravel(), sym_forbidba.ravel()))
    hdiagab = fvva.diagonal().reshape(-1, 1) - foob.diagonal()
    hdiagba = fvvb.diagonal().reshape(-1, 1) - fooa.diagonal()
    hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel()))
    if with_symmetry and mol.symmetry:
        hdiag2[sym_forbid2] = 0

    vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0)

    # Spin flip GHF solution is not considered
    def hop_uhf2ghf(x1):
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid2] = 0
        x1ab = x1[:nvira * noccb].reshape(nvira, noccb)
        x1ba = x1[nvira * noccb:].reshape(nvirb, nocca)
        x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab)
        x2ab -= numpy.einsum('sq,ps->pq', foob, x1ab)
        x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba)
        x2ba -= numpy.einsum('qs,ps->pq', fooa, x1ba)

        d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.T.conj()))
        d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.T.conj()))
        dm1 = numpy.array((d1ab + d1ba.T.conj(), d1ba + d1ab.T.conj()))
        v1 = vresp1(dm1)
        x2ab += reduce(numpy.dot, (orbva.T.conj(), v1[0], orbob))
        x2ba += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orboa))
        x2 = numpy.hstack((x2ab.ravel(), x2ba.ravel()))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid2] = 0
        return x2

    return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
Beispiel #35
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)
Beispiel #36
0
def kernel(mycc, eris, t1=None, t2=None, max_memory=2000, verbose=logger.INFO):
    '''Returns the CCSD(T) for restricted closed-shell systems with k-points.

    Note:
        Returns real part of the CCSD(T) energy, raises warning if there is
        a complex part.

    Args:
        mycc (:class:`RCCSD`): Coupled-cluster object storing results of
            a coupled-cluster calculation.
        eris (:class:`_ERIS`): Integral object holding the relevant electron-
            repulsion integrals and Fock matrix elements
        t1 (:obj:`ndarray`): t1 coupled-cluster amplitudes
        t2 (:obj:`ndarray`): t2 coupled-cluster amplitudes
        max_memory (float): Maximum memory used in calculation (NOT USED)
        verbose (int, :class:`Logger`): verbosity of calculation

    Returns:
        energy_t (float): The real-part of the k-point CCSD(T) energy.
    '''
    assert isinstance(mycc, pyscf.pbc.cc.kccsd_rhf.RCCSD)
    cpu1 = cpu0 = (logger.process_clock(), logger.perf_counter())
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(mycc.stdout, verbose)

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

    if eris is None:
        raise TypeError(
            'Electron repulsion integrals, `eris`, must be passed in '
            'to the CCSD(T) kernel or created in the cc object for '
            'the k-point CCSD(T) to run!')
    if t1 is None or t2 is None:
        raise TypeError(
            'Must pass in t1/t2 amplitudes to k-point CCSD(T)! (Maybe '
            'need to run `.ccsd()` on the ccsd object?)')

    cell = mycc._scf.cell
    kpts = mycc.kpts

    # The dtype of any local arrays that will be created
    dtype = t1.dtype

    nkpts, nocc, nvir = t1.shape

    mo_energy_occ = [eris.mo_energy[ki][:nocc] for ki in range(nkpts)]
    mo_energy_vir = [eris.mo_energy[ki][nocc:] for ki in range(nkpts)]
    mo_energy = np.asarray([eris.mo_energy[ki] for ki in range(nkpts)],
                           dtype=np.float,
                           order='C')
    fov = eris.fock[:, :nocc, nocc:]

    mo_e = mo_energy
    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    # Set up class for k-point conservation
    kconserv = kpts_helper.get_kconserv(cell, kpts)

    # Create necessary temporary eris for fast read
    feri_tmp, t2T, eris_vvop, eris_vooo_C = create_t3_eris(
        mycc, kconserv, [eris.vovv, eris.oovv, eris.ooov, t2])
    t1T = np.array([x.T for x in t1], dtype=np.complex, order='C')
    fvo = np.array([x.T for x in fov], dtype=np.complex, order='C')
    cpu1 = log.timer_debug1('CCSD(T) tmp eri creation', *cpu1)

    #def get_w_old(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1, out=None):
    #    '''Wijkabc intermediate as described in Scuseria paper before Pijkabc acts'''
    #    km = kconserv[kc, kk, kb]
    #    kf = kconserv[kk, kc, kj]
    #    ret = einsum('kjcf,fiba->abcijk', t2[kk,kj,kc,:,:,c0:c1,:], eris.vovv[kf,ki,kb,:,:,b0:b1,a0:a1].conj())
    #    ret = ret - einsum('mkbc,jima->abcijk', t2[km,kk,kb,:,:,b0:b1,c0:c1], eris.ooov[kj,ki,km,:,:,:,a0:a1].conj())
    #    return ret

    def get_w(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
        '''Wijkabc intermediate as described in Scuseria paper before Pijkabc acts

        Uses tranposed eris for fast data access.'''
        km = kconserv[kc, kk, kb]
        kf = kconserv[kk, kc, kj]
        out = einsum('cfjk,abif->abcijk', t2T[kc, kf, kj, c0:c1, :, :, :],
                     eris_vvop[ka, kb, ki, a0:a1, b0:b1, :, nocc:])
        out = out - einsum('cbmk,aijm->abcijk', t2T[kc, kb, km, c0:c1,
                                                    b0:b1, :, :],
                           eris_vooo_C[ka, ki, kj, a0:a1, :, :, :])
        return out

    def get_permuted_w(ki, kj, kk, ka, kb, kc, orb_indices):
        '''Pijkabc operating on Wijkabc intermediate as described in Scuseria paper'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        out = get_w(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1)
        out = out + get_w(kj, kk, ki, kb, kc, ka, b0, b1, c0, c1, a0,
                          a1).transpose(2, 0, 1, 5, 3, 4)
        out = out + get_w(kk, ki, kj, kc, ka, kb, c0, c1, a0, a1, b0,
                          b1).transpose(1, 2, 0, 4, 5, 3)
        out = out + get_w(ki, kk, kj, ka, kc, kb, a0, a1, c0, c1, b0,
                          b1).transpose(0, 2, 1, 3, 5, 4)
        out = out + get_w(kk, kj, ki, kc, kb, ka, c0, c1, b0, b1, a0,
                          a1).transpose(2, 1, 0, 5, 4, 3)
        out = out + get_w(kj, ki, kk, kb, ka, kc, b0, b1, a0, a1, c0,
                          c1).transpose(1, 0, 2, 4, 3, 5)
        return out

    def get_rw(ki, kj, kk, ka, kb, kc, orb_indices):
        '''R operating on Wijkabc intermediate as described in Scuseria paper'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        ret = (4. * get_permuted_w(ki, kj, kk, ka, kb, kc, orb_indices) +
               1. * get_permuted_w(kj, kk, ki, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 5, 3, 4) +
               1. * get_permuted_w(kk, ki, kj, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 4, 5, 3) -
               2. * get_permuted_w(ki, kk, kj, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 3, 5, 4) -
               2. * get_permuted_w(kk, kj, ki, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 5, 4, 3) -
               2. * get_permuted_w(kj, ki, kk, ka, kb, kc,
                                   orb_indices).transpose(0, 1, 2, 4, 3, 5))
        return ret

    #def get_v_old(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
    #    '''Vijkabc intermediate as described in Scuseria paper'''
    #    km = kconserv[ki,ka,kj]
    #    kf = kconserv[ki,ka,kj]
    #    out = np.zeros((a1-a0,b1-b0,c1-c0) + (nocc,)*3, dtype=dtype)
    #    if kk == kc:
    #        out = out + einsum('kc,ijab->abcijk', 0.5*t1[kk,:,c0:c1], eris.oovv[ki,kj,ka,:,:,a0:a1,b0:b1].conj())
    #        out = out + einsum('kc,ijab->abcijk', 0.5*fov[kk,:,c0:c1], t2[ki,kj,ka,:,:,a0:a1,b0:b1])
    #    return out

    def get_v(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
        '''Vijkabc intermediate as described in Scuseria paper'''
        #km = kconserv[ki,ka,kj]
        #kf = kconserv[ki,ka,kj]
        out = np.zeros((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3, dtype=dtype)
        if kk == kc:
            out = out + einsum('ck,baji->abcijk', 0.5 * t1T[kk, c0:c1, :],
                               eris_vvop[kb, ka, kj, b0:b1, a0:a1, :, :nocc])
            # We see this is the same t2T term needed for the `w` contraction:
            #     einsum('cbmk,aijm->abcijk', t2T[kc,kb,km,c0:c1,b0:b1], eris_vooo_C[ka,ki,kj,a0:a1])
            #
            # For the kpoint indices [kk,ki,kj,kc,ka,kb] we have that we need
            #     t2T[kb,ka,km], where km = kconserv[kb,kj,ka]
            # The remaining k-point not used in t2T, i.e. kc, has the condition kc == kk in the case of
            # get_v.  So, we have from 3-particle conservation
            #     (kk-kc) + ki + kj - ka - kb = 0,
            # i.e. ki = km.
            out = out + einsum('ck,baij->abcijk', 0.5 * fvo[kk, c0:c1, :],
                               t2T[kb, ka, ki, b0:b1, a0:a1, :, :])
        return out

    def get_permuted_v(ki, kj, kk, ka, kb, kc, orb_indices):
        '''Pijkabc operating on Vijkabc intermediate as described in Scuseria paper'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        ret = get_v(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1)
        ret = ret + get_v(kj, kk, ki, kb, kc, ka, b0, b1, c0, c1, a0,
                          a1).transpose(2, 0, 1, 5, 3, 4)
        ret = ret + get_v(kk, ki, kj, kc, ka, kb, c0, c1, a0, a1, b0,
                          b1).transpose(1, 2, 0, 4, 5, 3)
        ret = ret + get_v(ki, kk, kj, ka, kc, kb, a0, a1, c0, c1, b0,
                          b1).transpose(0, 2, 1, 3, 5, 4)
        ret = ret + get_v(kk, kj, ki, kc, kb, ka, c0, c1, b0, b1, a0,
                          a1).transpose(2, 1, 0, 5, 4, 3)
        ret = ret + get_v(kj, ki, kk, kb, ka, kc, b0, b1, a0, a1, c0,
                          c1).transpose(1, 0, 2, 4, 3, 5)
        return ret

    def contract_t3Tv(kpt_indices, orb_indices, data):
        '''Calculate t3T(ransposed) array using C driver.'''
        ki, kj, kk, ka, kb, kc = kpt_indices
        a0, a1, b0, b1, c0, c1 = orb_indices
        slices = np.array([a0, a1, b0, b1, c0, c1], dtype=np.int32)

        mo_offset = np.array([ki, kj, kk, ka, kb, kc], dtype=np.int32)

        vvop_ab = np.asarray(data[0][0], dtype=np.complex, order='C')
        vvop_ac = np.asarray(data[0][1], dtype=np.complex, order='C')
        vvop_ba = np.asarray(data[0][2], dtype=np.complex, order='C')
        vvop_bc = np.asarray(data[0][3], dtype=np.complex, order='C')
        vvop_ca = np.asarray(data[0][4], dtype=np.complex, order='C')
        vvop_cb = np.asarray(data[0][5], dtype=np.complex, order='C')

        vooo_aj = np.asarray(data[1][0], dtype=np.complex, order='C')
        vooo_ak = np.asarray(data[1][1], dtype=np.complex, order='C')
        vooo_bi = np.asarray(data[1][2], dtype=np.complex, order='C')
        vooo_bk = np.asarray(data[1][3], dtype=np.complex, order='C')
        vooo_ci = np.asarray(data[1][4], dtype=np.complex, order='C')
        vooo_cj = np.asarray(data[1][5], dtype=np.complex, order='C')

        t2T_cj = np.asarray(data[2][0], dtype=np.complex, order='C')
        t2T_bk = np.asarray(data[2][1], dtype=np.complex, order='C')
        t2T_ci = np.asarray(data[2][2], dtype=np.complex, order='C')
        t2T_ak = np.asarray(data[2][3], dtype=np.complex, order='C')
        t2T_bi = np.asarray(data[2][4], dtype=np.complex, order='C')
        t2T_aj = np.asarray(data[2][5], dtype=np.complex, order='C')

        t2T_cb = np.asarray(data[3][0], dtype=np.complex, order='C')
        t2T_bc = np.asarray(data[3][1], dtype=np.complex, order='C')
        t2T_ca = np.asarray(data[3][2], dtype=np.complex, order='C')
        t2T_ac = np.asarray(data[3][3], dtype=np.complex, order='C')
        t2T_ba = np.asarray(data[3][4], dtype=np.complex, order='C')
        t2T_ab = np.asarray(data[3][5], dtype=np.complex, order='C')

        data = [
            vvop_ab, vvop_ac, vvop_ba, vvop_bc, vvop_ca, vvop_cb, vooo_aj,
            vooo_ak, vooo_bi, vooo_bk, vooo_ci, vooo_cj, t2T_cj, t2T_cb,
            t2T_bk, t2T_bc, t2T_ci, t2T_ca, t2T_ak, t2T_ac, t2T_bi, t2T_ba,
            t2T_aj, t2T_ab
        ]
        data_ptrs = [x.ctypes.data_as(ctypes.c_void_p) for x in data]
        data_ptrs = (ctypes.c_void_p * 24)(*data_ptrs)

        a0, a1, b0, b1, c0, c1 = task
        t3Tw = np.empty((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                        dtype=np.complex,
                        order='C')
        t3Tv = np.empty((a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                        dtype=np.complex,
                        order='C')

        drv = _ccsd.libcc.CCsd_zcontract_t3T
        drv(t3Tw.ctypes.data_as(ctypes.c_void_p),
            t3Tv.ctypes.data_as(ctypes.c_void_p),
            mo_e.ctypes.data_as(ctypes.c_void_p),
            t1T.ctypes.data_as(ctypes.c_void_p),
            fvo.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(nocc),
            ctypes.c_int(nvir), ctypes.c_int(nkpts),
            mo_offset.ctypes.data_as(ctypes.c_void_p),
            slices.ctypes.data_as(ctypes.c_void_p), data_ptrs)
        return t3Tw, t3Tv

    def get_data(kpt_indices):
        idx_args = get_data_slices(kpt_indices, task, kconserv)
        vvop_indices, vooo_indices, t2T_vvop_indices, t2T_vooo_indices = idx_args
        vvop_data = [eris_vvop[tuple(x)] for x in vvop_indices]
        vooo_data = [eris_vooo_C[tuple(x)] for x in vooo_indices]
        t2T_vvop_data = [t2T[tuple(x)] for x in t2T_vvop_indices]
        t2T_vooo_data = [t2T[tuple(x)] for x in t2T_vooo_indices]
        data = [vvop_data, vooo_data, t2T_vvop_data, t2T_vooo_data]
        return data

    energy_t = 0.0

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(mycc, kind="split")

    mem_now = lib.current_memory()[0]
    max_memory = max(0, mycc.max_memory - mem_now)
    blkmin = 4
    # temporary t3 array is size:    2 * nkpts**3 * blksize**3 * nocc**3 * 16
    vir_blksize = min(
        nvir,
        max(blkmin,
            int((max_memory * .9e6 / 16 / nocc**3 / nkpts**3 / 2)**(1. / 3))))
    tasks = []
    log.debug('max_memory %d MB (%d MB in use)', max_memory, mem_now)
    log.debug('virtual blksize = %d (nvir = %d)', nvir, vir_blksize)
    for a0, a1 in lib.prange(0, nvir, vir_blksize):
        for b0, b1 in lib.prange(0, nvir, vir_blksize):
            for c0, c1 in lib.prange(0, nvir, vir_blksize):
                tasks.append((a0, a1, b0, b1, c0, c1))

    for ka in range(nkpts):
        for kb in range(ka + 1):
            for task_id, task in enumerate(tasks):
                a0, a1, b0, b1, c0, c1 = task
                my_permuted_w = np.zeros(
                    (nkpts, ) * 3 + (a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                    dtype=dtype)
                my_permuted_v = np.zeros(
                    (nkpts, ) * 3 + (a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                    dtype=dtype)
                for ki, kj, kk in product(range(nkpts), repeat=3):
                    # Find momentum conservation condition for triples
                    # amplitude t3ijkabc
                    kc = kpts_helper.get_kconserv3(cell, kpts,
                                                   [ki, kj, kk, ka, kb])
                    if not (ka >= kb and kb >= kc):
                        continue

                    kpt_indices = [ki, kj, kk, ka, kb, kc]
                    data = get_data(kpt_indices)
                    t3Tw, t3Tv = contract_t3Tv(kpt_indices, task, data)
                    my_permuted_w[ki, kj, kk] = t3Tw
                    my_permuted_v[ki, kj, kk] = t3Tv
                    #my_permuted_w[ki,kj,kk] = get_permuted_w(ki,kj,kk,ka,kb,kc,task)
                    #my_permuted_v[ki,kj,kk] = get_permuted_v(ki,kj,kk,ka,kb,kc,task)

                for ki, kj, kk in product(range(nkpts), repeat=3):
                    # eigenvalue denominator: e(i) + e(j) + e(k)
                    eijk = _get_epqr([0, nocc, ki, mo_e_o, nonzero_opadding],
                                     [0, nocc, kj, mo_e_o, nonzero_opadding],
                                     [0, nocc, kk, mo_e_o, nonzero_opadding])

                    # Find momentum conservation condition for triples
                    # amplitude t3ijkabc
                    kc = kpts_helper.get_kconserv3(cell, kpts,
                                                   [ki, kj, kk, ka, kb])
                    if not (ka >= kb and kb >= kc):
                        continue

                    if ka == kb and kb == kc:
                        symm_kpt = 1.
                    elif ka == kb or kb == kc:
                        symm_kpt = 3.
                    else:
                        symm_kpt = 6.

                    eabc = _get_epqr([a0, a1, ka, mo_e_v, nonzero_vpadding],
                                     [b0, b1, kb, mo_e_v, nonzero_vpadding],
                                     [c0, c1, kc, mo_e_v, nonzero_vpadding],
                                     fac=[-1., -1., -1.])
                    eijkabc = (eijk[None, None, None, :, :, :] +
                               eabc[:, :, :, None, None, None])

                    pwijk = my_permuted_w[ki, kj, kk] + my_permuted_v[ki, kj,
                                                                      kk]
                    rwijk = (
                        4. * my_permuted_w[ki, kj, kk] + 1. *
                        my_permuted_w[kj, kk, ki].transpose(0, 1, 2, 5, 3, 4) +
                        1. *
                        my_permuted_w[kk, ki, kj].transpose(0, 1, 2, 4, 5, 3) -
                        2. *
                        my_permuted_w[ki, kk, kj].transpose(0, 1, 2, 3, 5, 4) -
                        2. *
                        my_permuted_w[kk, kj, ki].transpose(0, 1, 2, 5, 4, 3) -
                        2. *
                        my_permuted_w[kj, ki, kk].transpose(0, 1, 2, 4, 3, 5))
                    rwijk = rwijk / eijkabc
                    energy_t += symm_kpt * einsum('abcijk,abcijk', rwijk,
                                                  pwijk.conj())

    energy_t *= (1. / 3)
    energy_t /= nkpts

    if abs(energy_t.imag) > 1e-4:
        log.warn('Non-zero imaginary part of CCSD(T) energy was found %s',
                 energy_t.imag)
    log.timer('CCSD(T)', *cpu0)
    log.note('CCSD(T) correction per cell = %.15g', energy_t.real)
    log.note('CCSD(T) correction per cell (imag) = %.15g', energy_t.imag)
    return energy_t.real
Beispiel #37
0
def gen_tda_operation(mf, fock_ao=None, wfnsym=None):
    '''(A+B)x

    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma_in_d2h = numpy.asarray(orbsyma) % 10
        orbsymb_in_d2h = numpy.asarray(orbsymb) % 10
        sym_forbida = (orbsyma_in_d2h[occidxa, None]
                       ^ orbsyma_in_d2h[viridxa]) != wfnsym
        sym_forbidb = (orbsymb_in_d2h[occidxb, None]
                       ^ orbsymb_in_d2h[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
    e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
    e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = mf.gen_response(hermi=0, max_memory=max_memory)

    def vind(zs):
        zs = numpy.asarray(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs)
            zs[:, sym_forbid] = 0

        za = zs[:, :nocca * nvira].reshape(-1, nocca, nvira)
        zb = zs[:, nocca * nvira:].reshape(-1, noccb, nvirb)
        dmova = lib.einsum('xov,po,qv->xpq', za, orboa, orbva.conj())
        dmovb = lib.einsum('xov,po,qv->xpq', zb, orbob, orbvb.conj())

        v1ao = vresp(numpy.asarray((dmova, dmovb)))

        v1a = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva)
        v1b = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb)
        v1a += numpy.einsum('xia,ia->xia', za, e_ia_a)
        v1b += numpy.einsum('xia,ia->xia', zb, e_ia_b)

        nz = zs.shape[0]
        hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
        if wfnsym is not None and mol.symmetry:
            hx[:, sym_forbid] = 0
        return hx

    return vind, hdiag
Beispiel #38
0
def _gen_uhf_response(mf, mo_coeff=None, mo_occ=None,
                      with_j=True, hermi=0, max_memory=None):
    '''Generate a function to compute the product of UHF response function and
    UHF density matrices.
    '''
    if mo_coeff is None: mo_coeff = mf.mo_coeff
    if mo_occ is None: mo_occ = mf.mo_occ
    mol = mf.mol
    if _is_dft_object(mf):
        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)
        hybrid = abs(hyb) > 1e-10

        # mf can be pbc.dft.UKS object with multigrid
        if (not hybrid and
            'MultiGridFFTDF' == getattr(mf, 'with_df', None).__class__.__name__):
            from pyscf.pbc.dft import multigrid
            dm0 = mf.make_rdm1(mo_coeff, mo_occ)
            return multigrid._gen_uhf_response(mf, dm0, with_j, hermi)

        rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc,
                                            mo_coeff, mo_occ, 1)
        #dm0 =(numpy.dot(mo_coeff[0]*mo_occ[0], mo_coeff[0].T.conj()),
        #      numpy.dot(mo_coeff[1]*mo_occ[1], mo_coeff[1].T.conj()))
        dm0 = None

        if max_memory is None:
            mem_now = lib.current_memory()[0]
            max_memory = max(2000, mf.max_memory*.8-mem_now)

        def vind(dm1):
            if hermi == 2:
                v1 = numpy.zeros_like(dm1)
            else:
                v1 = ni.nr_uks_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, hermi,
                                   rho0, vxc, fxc, max_memory=max_memory)
            if not hybrid:
                if with_j:
                    vj = mf.get_j(mol, dm1, hermi=hermi)
                    v1 += vj[0] + vj[1]
            else:
                if with_j:
                    vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
                    vk *= hyb
                    if omega > 1e-10:  # For range separated Coulomb
                        vk += mf.get_k(mol, dm1, hermi, omega) * (alpha-hyb)
                    v1 += vj[0] + vj[1] - vk
                else:
                    vk = mf.get_k(mol, dm1, hermi=hermi)
                    vk *= hyb
                    if omega > 1e-10:  # For range separated Coulomb
                        vk += mf.get_k(mol, dm1, hermi, omega) * (alpha-hyb)
                    v1 -= vk
            return v1

    elif with_j:
        def vind(dm1):
            vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
            v1 = vj[0] + vj[1] - vk
            return v1

    else:
        def vind(dm1):
            return -mf.get_k(mol, dm1, hermi=hermi)

    return vind
Beispiel #39
0
def _gen_rhf_response(mf, mo_coeff=None, mo_occ=None,
                      singlet=None, hermi=0, max_memory=None):
    '''Generate a function to compute the product of RHF response function and
    RHF density matrices.

    Kwargs:
        singlet (None or boolean) : If singlet is None, response function for
            orbital hessian or CPHF will be generated. If singlet is boolean,
            it is used in TDDFT response kernel.
    '''
    assert(not isinstance(mf, (uhf.UHF, rohf.ROHF)))

    if mo_coeff is None: mo_coeff = mf.mo_coeff
    if mo_occ is None: mo_occ = mf.mo_occ
    mol = mf.mol
    if _is_dft_object(mf):
        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)
        hybrid = abs(hyb) > 1e-10

        # mf can be pbc.dft.RKS object with multigrid
        if (not hybrid and
            'MultiGridFFTDF' == getattr(mf, 'with_df', None).__class__.__name__):
            from pyscf.pbc.dft import multigrid
            dm0 = mf.make_rdm1(mo_coeff, mo_occ)
            return multigrid._gen_rhf_response(mf, dm0, singlet, hermi)

        if singlet is None:
            # for ground state orbital hessian
            rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc,
                                                mo_coeff, mo_occ, 0)
        else:
            rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc,
                                                [mo_coeff]*2, [mo_occ*.5]*2, spin=1)
        dm0 = None  #mf.make_rdm1(mo_coeff, mo_occ)

        if max_memory is None:
            mem_now = lib.current_memory()[0]
            max_memory = max(2000, mf.max_memory*.8-mem_now)

        if singlet is None:
            # Without specify singlet, used in ground state orbital hessian
            def vind(dm1):
                # The singlet hessian
                if hermi == 2:
                    v1 = numpy.zeros_like(dm1)
                else:
                    v1 = ni.nr_rks_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, hermi,
                                       rho0, vxc, fxc, max_memory=max_memory)
                if hybrid:
                    if hermi != 2:
                        vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
                        vk *= hyb
                        if omega > 1e-10:  # For range separated Coulomb
                            vk += mf.get_k(mol, dm1, hermi, omega) * (alpha-hyb)
                        v1 += vj - .5 * vk
                    else:
                        v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi)
                elif hermi != 2:
                    v1 += mf.get_j(mol, dm1, hermi=hermi)
                return v1

        elif singlet:
            def vind(dm1):
                if hermi == 2:
                    v1 = numpy.zeros_like(dm1)
                else:
                    # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled
                    v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0,
                                              True, rho0, vxc, fxc,
                                              max_memory=max_memory)
                    v1 *= .5
                if hybrid:
                    if hermi != 2:
                        vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
                        vk *= hyb
                        if omega > 1e-10:  # For range separated Coulomb
                            vk += mf.get_k(mol, dm1, hermi, omega) * (alpha-hyb)
                        v1 += vj - .5 * vk
                    else:
                        v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi)
                elif hermi != 2:
                    v1 += mf.get_j(mol, dm1, hermi=hermi)
                return v1
        else:  # triplet
            def vind(dm1):
                if hermi == 2:
                    v1 = numpy.zeros_like(dm1)
                else:
                    # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled
                    v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0,
                                              False, rho0, vxc, fxc,
                                              max_memory=max_memory)
                    v1 *= .5
                if hybrid:
                    vk = mf.get_k(mol, dm1, hermi=hermi)
                    vk *= hyb
                    if omega > 1e-10:  # For range separated Coulomb
                        vk += mf.get_k(mol, dm1, hermi, omega) * (alpha-hyb)
                    v1 += -.5 * vk
                return v1

    else:  # HF
        if (singlet is None or singlet) and hermi != 2:
            def vind(dm1):
                vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
                return vj - .5 * vk
        else:
            def vind(dm1):
                return -.5 * mf.get_k(mol, dm1, hermi=hermi)

    return vind
Beispiel #40
0
def grad_elec(td_grad,
              x_y,
              singlet=True,
              atmlst=None,
              max_memory=2000,
              verbose=logger.INFO):
    '''
    Electronic part of TDA, TDDFT nuclear gradients

    Args:
        td_grad : grad.tdrhf.Gradients or grad.tdrks.Gradients object.

        x_y : a two-element list of numpy arrays
            TDDFT X and Y amplitudes. If Y is set to 0, this function computes
            TDA energy gradients.
    '''
    log = logger.new_logger(td_grad, verbose)
    time0 = logger.process_clock(), logger.perf_counter()

    mol = td_grad.mol
    mf = td_grad.base._scf
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    nocc = (mo_occ > 0).sum()
    nvir = nmo - nocc
    x, y = x_y
    xpy = (x + y).reshape(nocc, nvir).T
    xmy = (x - y).reshape(nocc, nvir).T
    orbv = mo_coeff[:, nocc:]
    orbo = mo_coeff[:, :nocc]

    dvv = numpy.einsum('ai,bi->ab', xpy, xpy) + numpy.einsum(
        'ai,bi->ab', xmy, xmy)
    doo = -numpy.einsum('ai,aj->ij', xpy, xpy) - numpy.einsum(
        'ai,aj->ij', xmy, xmy)
    dmxpy = reduce(numpy.dot, (orbv, xpy, orbo.T))
    dmxmy = reduce(numpy.dot, (orbv, xmy, orbo.T))
    dmzoo = reduce(numpy.dot, (orbo, doo, orbo.T))
    dmzoo += reduce(numpy.dot, (orbv, dvv, orbv.T))

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, td_grad.max_memory * .9 - mem_now)

    ni = mf._numint
    ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)
    # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing
    # fxc since rho0 is passed to fxc function.
    rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol,
                                        mf.grids,
                                        mf.xc, [mo_coeff] * 2,
                                        [mo_occ * .5] * 2,
                                        spin=1)
    f1vo, f1oo, vxc1, k1ao = \
            _contract_xc_kernel(td_grad, mf.xc, dmxpy,
                                dmzoo, True, True, singlet, max_memory)

    if abs(hyb) > 1e-10:
        dm = (dmzoo, dmxpy + dmxpy.T, dmxmy - dmxmy.T)
        vj, vk = mf.get_jk(mol, dm, hermi=0)
        vk *= hyb
        if abs(omega) > 1e-10:
            vk += mf.get_k(mol, dm, hermi=0, omega=omega) * (alpha - hyb)
        veff0doo = vj[0] * 2 - vk[0] + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 - vk[1] + f1vo[0] * 2
        else:
            veff = -vk[1] + f1vo[0] * 2
        veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:, nocc:], xpy) * 2
        veff = -vk[2]
        veff0mom = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mom[:nocc, :nocc], xmy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mom[nocc:, nocc:], xmy) * 2
    else:
        vj = mf.get_j(mol, (dmzoo, dmxpy + dmxpy.T), hermi=1)
        veff0doo = vj[0] * 2 + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 + f1vo[0] * 2
        else:
            veff = f1vo[0] * 2
        veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:, nocc:], xpy) * 2
        veff0mom = numpy.zeros((nmo, nmo))

    # set singlet=None, generate function for CPHF type response kernel
    vresp = mf.gen_response(singlet=None, hermi=1)

    def fvind(x):
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc) * 2, orbo.T))
        v1ao = vresp(dm + dm.T)
        return reduce(numpy.dot, (orbv.T, v1ao, orbo)).ravel()

    z1 = cphf.solve(fvind,
                    mo_energy,
                    mo_occ,
                    wvo,
                    max_cycle=td_grad.cphf_max_cycle,
                    tol=td_grad.cphf_conv_tol)[0]
    z1 = z1.reshape(nvir, nocc)
    time1 = log.timer('Z-vector using CPHF solver', *time0)

    z1ao = reduce(numpy.dot, (orbv, z1, orbo.T))
    veff = vresp(z1ao + z1ao.T)

    im0 = numpy.zeros((nmo, nmo))
    im0[:nocc, :nocc] = reduce(numpy.dot, (orbo.T, veff0doo + veff, orbo))
    im0[:nocc, :nocc] += numpy.einsum('ak,ai->ki', veff0mop[nocc:, :nocc], xpy)
    im0[:nocc, :nocc] += numpy.einsum('ak,ai->ki', veff0mom[nocc:, :nocc], xmy)
    im0[nocc:, nocc:] = numpy.einsum('ci,ai->ac', veff0mop[nocc:, :nocc], xpy)
    im0[nocc:, nocc:] += numpy.einsum('ci,ai->ac', veff0mom[nocc:, :nocc], xmy)
    im0[nocc:, :nocc] = numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc],
                                     xpy) * 2
    im0[nocc:, :nocc] += numpy.einsum('ki,ai->ak', veff0mom[:nocc, :nocc],
                                      xmy) * 2

    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:, :nocc] = mo_energy[:nocc]
    zeta[:nocc, nocc:] = mo_energy[nocc:]
    dm1 = numpy.zeros((nmo, nmo))
    dm1[:nocc, :nocc] = doo
    dm1[nocc:, nocc:] = dvv
    dm1[nocc:, :nocc] = z1
    dm1[:nocc, :nocc] += numpy.eye(nocc) * 2  # for ground state
    im0 = reduce(numpy.dot, (mo_coeff, im0 + zeta * dm1, mo_coeff.T))

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

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    if abs(hyb) > 1e-10:
        dm = (oo0, dmz1doo + dmz1doo.T, dmxpy + dmxpy.T, dmxmy - dmxmy.T)
        vj, vk = td_grad.get_jk(mol, dm)
        vk *= hyb
        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vk += td_grad.get_k(mol, dm) * (alpha - hyb)
        vj = vj.reshape(-1, 3, nao, nao)
        vk = vk.reshape(-1, 3, nao, nao)
        if singlet:
            veff1 = vj * 2 - vk
        else:
            veff1 = numpy.vstack((vj[:2] * 2 - vk[:2], -vk[2:]))
    else:
        vj = td_grad.get_j(mol, (oo0, dmz1doo + dmz1doo.T, dmxpy + dmxpy.T))
        vj = vj.reshape(-1, 3, nao, nao)
        veff1 = numpy.zeros((4, 3, nao, nao))
        if singlet:
            veff1[:3] = vj * 2
        else:
            veff1[:2] = vj[:2] * 2

    fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False, True,
                                max_memory)[0]

    veff1[0] += vxc1[1:]
    veff1[1] += (f1oo[1:] + fxcz1[1:] +
                 k1ao[1:] * 2) * 2  # *2 for dmz1doo+dmz1oo.T
    veff1[2] += f1vo[1:] * 2
    time1 = log.timer('2e AO integral derivatives', *time1)

    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]

        # Ground state gradients
        h1ao = hcore_deriv(ia)
        h1ao[:, p0:p1] += veff1[0, :, p0:p1]
        h1ao[:, :, p0:p1] += veff1[0, :, p0:p1].transpose(0, 2, 1)
        # oo0*2 for doubly occupied orbitals
        e1 = numpy.einsum('xpq,pq->x', h1ao, oo0) * 2

        e1 += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)
        e1 -= numpy.einsum('xpq,pq->x', s1[:, p0:p1], im0[p0:p1])
        e1 -= numpy.einsum('xqp,pq->x', s1[:, p0:p1], im0[:, p0:p1])

        e1 += numpy.einsum('xij,ij->x', veff1[1, :, p0:p1], oo0[p0:p1])
        e1 += numpy.einsum('xij,ij->x', veff1[2, :, p0:p1],
                           dmxpy[p0:p1, :]) * 2
        e1 += numpy.einsum('xij,ij->x', veff1[3, :, p0:p1],
                           dmxmy[p0:p1, :]) * 2
        e1 += numpy.einsum('xji,ij->x', veff1[2, :, p0:p1], dmxpy[:,
                                                                  p0:p1]) * 2
        e1 -= numpy.einsum('xji,ij->x', veff1[3, :, p0:p1], dmxmy[:,
                                                                  p0:p1]) * 2

        de[k] = e1

    log.timer('TDDFT nuclear gradients', *time0)
    return de
Beispiel #41
0
def build_se_part(agf2, eri, gf_occ, gf_vir, os_factor=1.0, ss_factor=1.0):
    ''' Builds either the auxiliaries of the occupied self-energy,
        or virtual if :attr:`gf_occ` and :attr:`gf_vir` are swapped.

    Args:
        eri : _ChemistsERIs
            Electronic repulsion integrals
        gf_occ : GreensFunction
            Occupied Green's function
        gf_vir : GreensFunction
            Virtual Green's function

    Kwargs:
        os_factor : float
            Opposite-spin factor for spin-component-scaled (SCS)
            calculations. Default 1.0
        ss_factor : float
            Same-spin factor for spin-component-scaled (SCS)
            calculations. Default 1.0

    Returns:
        :class:`SelfEnergy`
    '''

    cput0 = (logger.process_clock(), logger.perf_counter())
    log = logger.Logger(agf2.stdout, agf2.verbose)

    assert type(gf_occ[0]) is aux.GreensFunction
    assert type(gf_occ[1]) is aux.GreensFunction
    assert type(gf_vir[0]) is aux.GreensFunction
    assert type(gf_vir[1]) is aux.GreensFunction

    nmoa, nmob = eri.nmo
    nocca, nvira = gf_occ[0].naux, gf_vir[0].naux
    noccb, nvirb = gf_occ[1].naux, gf_vir[1].naux
    naux = agf2.with_df.get_naoaux()
    tol = agf2.weight_tol
    facs = dict(os_factor=os_factor, ss_factor=ss_factor)

    ci_a, ei_a = gf_occ[0].coupling, gf_occ[0].energy
    ci_b, ei_b = gf_occ[1].coupling, gf_occ[1].energy
    ca_a, ea_a = gf_vir[0].coupling, gf_vir[0].energy
    ca_b, ea_b = gf_vir[1].coupling, gf_vir[1].energy

    qeri = _make_qmo_eris_incore(agf2, eri, (ci_a, ci_a, ca_a),
                                 (ci_b, ci_b, ca_b))
    (qxi_a, qja_a), (qxi_b, qja_b) = qeri
    qxi = (qxi_a, qxi_b)
    qja = (qja_a, qja_b)

    himem_required = naux * (nvira + nmoa) + (
        nocca * nvira + noccb * nvirb) * (1 + 2 * nmoa) + (2 * nmoa**2)
    himem_required *= 8e-6
    himem_required *= lib.num_threads()

    if ((himem_required * 1.05 + lib.current_memory()[0]) > agf2.max_memory
            and agf2.allow_lowmem_build) or agf2.allow_lowmem_build == 'force':
        log.debug(
            'Thread-private memory overhead %.3f exceeds max_memory, using '
            'low-memory version.', himem_required)
        build_mats_dfuagf2 = _agf2.build_mats_dfuagf2_lowmem
    else:
        build_mats_dfuagf2 = _agf2.build_mats_dfuagf2_incore

    vv, vev = build_mats_dfuagf2(qxi, qja, (ei_a, ei_b), (ea_a, ea_b), **facs)
    e, c = _agf2.cholesky_build(vv, vev)
    se_a = aux.SelfEnergy(e, c, chempot=gf_occ[0].chempot)
    se_a.remove_uncoupled(tol=tol)

    if not (agf2.frozen is None or agf2.frozen == 0):
        mask = uagf2.get_frozen_mask(agf2)
        coupling = np.zeros((nmoa, se_a.naux))
        coupling[mask[0]] = se_a.coupling
        se_a = aux.SelfEnergy(se_a.energy, coupling, chempot=se_a.chempot)

    cput0 = log.timer('se part (alpha)', *cput0)

    himem_required = naux * (nvirb + nmob) + (
        noccb * nvirb + nocca * nvira) * (1 + 2 * nmob) + (2 * nmob**2)
    himem_required *= 8e-6
    himem_required *= lib.num_threads()

    if ((himem_required * 1.05 + lib.current_memory()[0]) > agf2.max_memory
            and agf2.allow_lowmem_build) or agf2.allow_lowmem_build == 'force':
        log.debug(
            'Thread-private memory overhead %.3f exceeds max_memory, using '
            'low-memory version.', himem_required)
        build_mats_dfuagf2 = _agf2.build_mats_dfuagf2_lowmem
    else:
        build_mats_dfuagf2 = _agf2.build_mats_dfuagf2_incore

    rv = np.s_[::-1]
    vv, vev = build_mats_dfuagf2(qxi[rv], qja[rv], (ei_b, ei_a), (ea_b, ea_a),
                                 **facs)
    e, c = _agf2.cholesky_build(vv, vev)
    se_b = aux.SelfEnergy(e, c, chempot=gf_occ[1].chempot)
    se_b.remove_uncoupled(tol=tol)

    if not (agf2.frozen is None or agf2.frozen == 0):
        mask = uagf2.get_frozen_mask(agf2)
        coupling = np.zeros((nmoa, se_b.naux))
        coupling[mask[1]] = se_b.coupling
        se_b = aux.SelfEnergy(se_b.energy, coupling, chempot=se_b.chempot)

    cput0 = log.timer('se part (beta)', *cput0)

    return (se_a, se_b)
Beispiel #42
0
    def __init__(self, cc, mo_coeff=None, method='incore', ao2mofn=ao2mo.full):
        cput0 = (time.clock(), time.time())
        moidx = _active_idx(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):
            if ao2mofn == ao2mo.full:
                if cc._scf._eri is not None:
                    eri = ao2mo.restore(1, ao2mofn(cc._scf._eri, mo_coeff),
                                        nmo)
                else:
                    eri = ao2mo.restore(
                        1, ao2mofn(cc._scf.mol, mo_coeff, compact=0), nmo)
            else:
                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)

            self.dtype = eri.dtype
            self.oooo = eri[:nocc, :nocc, :nocc, :nocc].copy()
            self.ooov = eri[:nocc, :nocc, :nocc, nocc:].copy()
            self.ovoo = eri[:nocc, nocc:, :nocc, :nocc].copy()
            self.oovo = eri[:nocc, :nocc, nocc:, :nocc].copy()
            self.ovov = eri[:nocc, nocc:, :nocc, nocc:].copy()
            self.oovv = eri[:nocc, :nocc, nocc:, nocc:].copy()
            self.ovvo = eri[:nocc, nocc:, nocc:, :nocc].copy()
            self.ovvv = eri[:nocc, nocc:, nocc:, nocc:].copy()

        elif hasattr(cc._scf, 'with_df') and cc._scf.with_df:
            raise NotImplementedError

        else:
            orbo = mo_coeff[:, :nocc]
            self.dtype = mo_coeff.dtype
            ds_type = mo_coeff.dtype.char
            self.feri = lib.H5TmpFile()
            self.oooo = self.feri.create_dataset('oooo',
                                                 (nocc, nocc, nocc, nocc),
                                                 ds_type)
            self.ooov = self.feri.create_dataset('ooov',
                                                 (nocc, nocc, nocc, nvir),
                                                 ds_type)
            self.ovoo = self.feri.create_dataset('ovoo',
                                                 (nocc, nvir, nocc, nocc),
                                                 ds_type)
            self.oovo = self.feri.create_dataset('oovo',
                                                 (nocc, nocc, nvir, nocc),
                                                 ds_type)
            self.ovov = self.feri.create_dataset('ovov',
                                                 (nocc, nvir, nocc, nvir),
                                                 ds_type)
            self.oovv = self.feri.create_dataset('oovv',
                                                 (nocc, nocc, nvir, nvir),
                                                 ds_type)
            self.ovvo = self.feri.create_dataset('ovvo',
                                                 (nocc, nvir, nvir, nocc),
                                                 ds_type)
            self.ovvv = self.feri.create_dataset('ovvv',
                                                 (nocc, nvir, nvir, nvir),
                                                 ds_type)

            cput1 = time.clock(), time.time()
            # <ij||pq> = <ij|pq> - <ij|qp> = (ip|jq) - (iq|jp)
            tmpfile2 = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR)
            ao2mo.general(cc.mol, (orbo, mo_coeff, mo_coeff, mo_coeff),
                          tmpfile2.name, 'aa')
            with h5py.File(tmpfile2.name) as f:
                buf = numpy.empty((nmo, nmo, nmo))
                for i in range(nocc):
                    lib.unpack_tril(f['aa'][i * nmo:(i + 1) * nmo], out=buf)
                    self.oooo[i] = buf[:nocc, :nocc, :nocc]
                    self.ooov[i] = buf[:nocc, :nocc, nocc:]
                    self.ovoo[i] = buf[nocc:, :nocc, :nocc]
                    self.ovov[i] = buf[nocc:, :nocc, nocc:]
                    self.oovo[i] = buf[:nocc, nocc:, :nocc]
                    self.oovv[i] = buf[:nocc, nocc:, nocc:]
                    self.ovvo[i] = buf[nocc:, nocc:, :nocc]
                    self.ovvv[i] = buf[nocc:, nocc:, nocc:]
                del (f['aa'])
                buf = None

            cput1 = log.timer_debug1('transforming oopq, ovpq', *cput1)

        log.timer('GW integral transformation', *cput0)
Beispiel #43
0
def _rdm2_mo2ao(mycc, d2, mo_coeff, fsave=None):
    log = logger.Logger(mycc.stdout, mycc.verbose)
    time1 = time.clock(), time.time()
    if fsave is None:
        incore = True
        fsave = lib.H5TmpFile()
    else:
        incore = False
    dovov, dovOV, dOVov, dOVOV = d2[0]
    dvvvv, dvvVV, dVVvv, dVVVV = d2[1]
    doooo, dooOO, dOOoo, dOOOO = d2[2]
    doovv, dooVV, dOOvv, dOOVV = d2[3]
    dovvo, dovVO, dOVvo, dOVVO = d2[4]
    dvvov, dvvOV, dVVov, dVVOV = d2[5]
    dovvv, dovVV, dOVvv, dOVVV = d2[6]
    dooov, dooOV, dOOov, dOOOV = d2[7]
    mo_a = numpy.asarray(mo_coeff[0], order='F')
    mo_b = numpy.asarray(mo_coeff[1], order='F')

    nocca, nvira, noccb, nvirb = dovOV.shape
    nao, nmoa = mo_a.shape
    nmob = mo_b.shape[1]
    nao_pair = nao * (nao + 1) // 2
    nvira_pair = nvira * (nvira + 1) // 2
    nvirb_pair = nvirb * (nvirb + 1) // 2

    fdrv = getattr(_ccsd.libcc, 'AO2MOnr_e2_drv')
    ftrans = _ccsd.libcc.AO2MOtranse2_nr_s1
    fmm = _ccsd.libcc.CCmmm_transpose_sum
    pao_loc = ctypes.POINTER(ctypes.c_void_p)()

    def _trans(vin, mo_coeff, orbs_slice, out=None):
        nrow = vin.shape[0]
        if out is None:
            out = numpy.empty((nrow, nao_pair))
        fdrv(ftrans, fmm, out.ctypes.data_as(ctypes.c_void_p),
             vin.ctypes.data_as(ctypes.c_void_p),
             mo_coeff.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(nrow),
             ctypes.c_int(nao), (ctypes.c_int * 4)(*orbs_slice), pao_loc,
             ctypes.c_int(0))
        return out

    fswap = lib.H5TmpFile()
    max_memory = mycc.max_memory - lib.current_memory()[0]
    blksize_a = int(max_memory * .9e6 / 8 / (nao_pair + nmoa**2))
    blksize_a = min(nvira_pair, max(ccsd.BLKMIN, blksize_a))
    v_aa = fswap.create_dataset('v_aa', (nao_pair, nvira_pair),
                                'f8',
                                chunks=(nao_pair, blksize_a))
    for p0, p1 in lib.prange(0, nvira_pair, blksize_a):
        v_aa[:, p0:p1] = _trans(lib.unpack_tril(dvvvv[p0:p1] * .25), mo_a,
                                (nocca, nmoa, nocca, nmoa)).T

    v_ba = fswap.create_dataset('v_ab', (nao_pair, nvira_pair),
                                'f8',
                                chunks=(nao_pair, blksize_a))
    dvvOP = fswap.create_dataset('dvvOP', (nvira_pair, noccb, nmob),
                                 'f8',
                                 chunks=(nvira_pair, 1, nmob))
    for i in range(noccb):
        buf1 = numpy.empty((nmob, nvira, nvira))
        buf1[:noccb] = dOOvv[i] * .5
        buf1[noccb:] = dOVvv[i]
        buf1 = buf1.transpose(1, 2, 0) + buf1.transpose(2, 1, 0)
        dvvOP[:, i] = buf1[numpy.tril_indices(nvira)]
    for p0, p1 in lib.prange(0, nvira_pair, blksize_a):
        buf1 = numpy.zeros((p1 - p0, nmob, nmob))
        buf1[:, noccb:, noccb:] = lib.unpack_tril(dvvVV[p0:p1] * .5)
        buf1[:, :noccb, :] = dvvOP[p0:p1] * .5
        v_ba[:, p0:p1] = _trans(buf1, mo_b, (0, nmob, 0, nmob)).T
    dvvOO = dvvOV = None

    blksize_b = int(max_memory * .9e6 / 8 / (nao_pair + nmob**2))
    blksize_b = min(nvirb_pair, max(ccsd.BLKMIN, blksize_b))
    v_bb = fswap.create_dataset('v_bb', (nao_pair, nvirb_pair),
                                'f8',
                                chunks=(nao_pair, blksize_b))
    for p0, p1 in lib.prange(0, nvirb_pair, blksize_b):
        v_bb[:, p0:p1] = _trans(lib.unpack_tril(dVVVV[p0:p1] * .25), mo_b,
                                (noccb, nmob, noccb, nmob)).T
    time1 = log.timer_debug1('_rdm2_mo2ao pass 1', *time1)

    # transform dm2_ij to get lower triangular (dm2+dm2.transpose(0,1,3,2))
    blksize = int(max_memory * .9e6 / 8 / (nao_pair + nmoa**2))
    blksize = min(nao_pair, max(ccsd.BLKMIN, blksize))
    o_aa = fswap.create_dataset('o_aa', (nmoa, nocca, nao_pair),
                                'f8',
                                chunks=(nmoa, nocca, blksize))
    o_ab = fswap.create_dataset('o_ab', (nmoa, nocca, nao_pair),
                                'f8',
                                chunks=(nmoa, nocca, blksize))
    o_bb = fswap.create_dataset('o_bb', (nmob, noccb, nao_pair),
                                'f8',
                                chunks=(nmob, noccb, blksize))
    buf1 = numpy.zeros((nocca, nocca, nmoa, nmoa))
    buf1[:, :, :nocca, :nocca] = _cp(doooo) * .25
    buf1[:, :, nocca:, nocca:] = _cp(doovv) * .5
    buf1 = _trans(buf1.reshape(nocca**2, -1), mo_a, (0, nmoa, 0, nmoa))
    o_aa[:nocca] = buf1.reshape(nocca, nocca, nao_pair)

    buf1 = numpy.zeros((nocca, nocca, nmob, nmob))
    buf1[:, :, :noccb, :noccb] = _cp(dooOO) * .5
    buf1[:, :, :noccb, noccb:] = _cp(dooOV)
    buf1[:, :, noccb:, noccb:] = _cp(dooVV) * .5
    buf1 = _trans(buf1.reshape(nocca**2, -1), mo_b, (0, nmob, 0, nmob))
    o_ab[:nocca] = buf1.reshape(nocca, nocca, nao_pair)

    buf1 = numpy.zeros((noccb, noccb, nmob, nmob))
    buf1[:, :, :noccb, :noccb] = _cp(dOOOO) * .25
    buf1[:, :, noccb:, noccb:] = _cp(dOOVV) * .5
    buf1 = _trans(buf1.reshape(noccb**2, -1), mo_b, (0, nmob, 0, nmob))
    o_bb[:noccb] = buf1.reshape(noccb, noccb, nao_pair)

    dovoo = numpy.asarray(dooov).transpose(2, 3, 0, 1)
    dovOO = numpy.asarray(dOOov).transpose(2, 3, 0, 1)
    dOVOO = numpy.asarray(dOOOV).transpose(2, 3, 0, 1)
    for p0, p1 in lib.prange(nocca, nmoa, nocca):
        buf1 = numpy.zeros((nocca, p1 - p0, nmoa, nmoa))
        buf1[:, :, :nocca, :nocca] = dovoo[:, p0 - nocca:p1 - nocca]
        buf1[:, :, nocca:, :nocca] = dovvo[:, p0 - nocca:p1 - nocca] * .5
        buf1[:, :, :nocca, nocca:] = dovov[:, p0 - nocca:p1 - nocca] * .5
        buf1[:, :, nocca:, nocca:] = dovvv[:, p0 - nocca:p1 - nocca]
        buf1 = buf1.transpose(1, 0, 3, 2).reshape((p1 - p0) * nocca, -1)
        buf1 = _trans(buf1, mo_a, (0, nmoa, 0, nmoa))
        o_aa[p0:p1] = buf1.reshape(p1 - p0, nocca, nao_pair)

        buf1 = numpy.zeros((nocca, p1 - p0, nmob, nmob))
        buf1[:, :, :noccb, :noccb] = dovOO[:, p0 - nocca:p1 - nocca]
        buf1[:, :, noccb:, :noccb] = dovVO[:, p0 - nocca:p1 - nocca]
        buf1[:, :, :noccb, noccb:] = dovOV[:, p0 - nocca:p1 - nocca]
        buf1[:, :, noccb:, noccb:] = dovVV[:, p0 - nocca:p1 - nocca]
        buf1 = buf1.transpose(1, 0, 3, 2).reshape((p1 - p0) * nocca, -1)
        buf1 = _trans(buf1, mo_b, (0, nmob, 0, nmob))
        o_ab[p0:p1] = buf1.reshape(p1 - p0, nocca, nao_pair)

    for p0, p1 in lib.prange(noccb, nmob, noccb):
        buf1 = numpy.zeros((noccb, p1 - p0, nmob, nmob))
        buf1[:, :, :noccb, :noccb] = dOVOO[:, p0 - noccb:p1 - noccb]
        buf1[:, :, noccb:, :noccb] = dOVVO[:, p0 - noccb:p1 - noccb] * .5
        buf1[:, :, :noccb, noccb:] = dOVOV[:, p0 - noccb:p1 - noccb] * .5
        buf1[:, :, noccb:, noccb:] = dOVVV[:, p0 - noccb:p1 - noccb]
        buf1 = buf1.transpose(1, 0, 3, 2).reshape((p1 - p0) * noccb, -1)
        buf1 = _trans(buf1, mo_b, (0, nmob, 0, nmob))
        o_bb[p0:p1] = buf1.reshape(p1 - p0, noccb, nao_pair)
    time1 = log.timer_debug1('_rdm2_mo2ao pass 2', *time1)
    dovoo = buf1 = None

    # transform dm2_kl then dm2 + dm2.transpose(2,3,0,1)
    dm2a = fsave.create_dataset('dm2aa+ab', (nao_pair, nao_pair),
                                'f8',
                                chunks=(nao_pair, blksize))
    dm2b = fsave.create_dataset('dm2bb+ab', (nao_pair, nao_pair),
                                'f8',
                                chunks=(nao_pair, blksize))
    for p0, p1 in lib.prange(0, nao_pair, blksize):
        buf1 = numpy.zeros((p1 - p0, nmoa, nmoa))
        buf1[:, nocca:, nocca:] = lib.unpack_tril(_cp(v_aa[p0:p1]))
        buf1[:, :, :nocca] = o_aa[:, :, p0:p1].transpose(2, 0, 1)
        buf2 = _trans(buf1, mo_a, (0, nmoa, 0, nmoa))
        if p0 > 0:
            buf1 = _cp(dm2a[:p0, p0:p1])
            buf1[:p0, :p1 - p0] += buf2[:p1 - p0, :p0].T
            buf2[:p1 - p0, :p0] = buf1[:p0, :p1 - p0].T
            dm2a[:p0, p0:p1] = buf1
        lib.transpose_sum(buf2[:, p0:p1], inplace=True)
        dm2a[p0:p1] = buf2
        buf1 = buf2 = None

    for p0, p1 in lib.prange(0, nao_pair, blksize):
        buf1 = numpy.zeros((p1 - p0, nmob, nmob))
        buf1[:, noccb:, noccb:] = lib.unpack_tril(_cp(v_bb[p0:p1]))
        buf1[:, :, :noccb] = o_bb[:, :, p0:p1].transpose(2, 0, 1)
        buf2 = _trans(buf1, mo_b, (0, nmob, 0, nmob))
        if p0 > 0:
            buf1 = _cp(dm2b[:p0, p0:p1])
            buf1[:p0, :p1 - p0] += buf2[:p1 - p0, :p0].T
            buf2[:p1 - p0, :p0] = buf1[:p0, :p1 - p0].T
            dm2b[:p0, p0:p1] = buf1
        lib.transpose_sum(buf2[:, p0:p1], inplace=True)
        dm2b[p0:p1] = buf2
        buf1 = buf2 = None

    for p0, p1 in lib.prange(0, nao_pair, blksize):
        buf1 = numpy.zeros((p1 - p0, nmoa, nmoa))
        buf1[:, nocca:, nocca:] = lib.unpack_tril(_cp(v_ba[p0:p1]))
        buf1[:, :, :nocca] = o_ab[:, :, p0:p1].transpose(2, 0, 1)
        buf2 = _trans(buf1, mo_a, (0, nmoa, 0, nmoa))
        dm2a[:, p0:p1] = dm2a[:, p0:p1] + buf2.T
        dm2b[p0:p1] = dm2b[p0:p1] + buf2
        buf1 = buf2 = None

    time1 = log.timer_debug1('_rdm2_mo2ao pass 3', *time1)
    if incore:
        return (fsave['dm2aa+ab'].value, fsave['dm2bb+ab'].value)
    else:
        return fsave
Beispiel #44
0
def kernel(mc,
           mo_coeff=None,
           ci=None,
           atmlst=None,
           mf_grad=None,
           verbose=None):
    if mo_coeff is None: mo_coeff = mc._scf.mo_coeff
    if ci is None: ci = mc.ci
    if mf_grad is None: mf_grad = mc._scf.nuc_grad_method()

    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_energy = mc._scf.mo_energy

    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)
    mo_occ = mo_coeff[:, :nocc]
    mo_core = mo_coeff[:, :ncore]
    mo_cas = mo_coeff[:, ncore:nocc]

    casdm1, casdm2 = mc.fcisolver.make_rdm12(mc.ci, ncas, nelecas)

    # gfock = Generalized Fock, Adv. Chem. Phys., 69, 63
    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_occ, mo_cas), compact=False)
    aapa = aapa.reshape(ncas, ncas, nocc, 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
    gfock = reduce(numpy.dot, (mo_occ.T, h1 + vhf_c + vhf_a, mo_occ)) * 2
    gfock[:, ncore:nocc] = reduce(numpy.dot,
                                  (mo_occ.T, h1 + vhf_c, mo_cas, casdm1))
    gfock[:, ncore:nocc] += numpy.einsum('uviw,vuwt->it', aapa, casdm2)
    dme0 = reduce(numpy.dot, (mo_occ, (gfock + gfock.T) * .5, mo_occ.T))
    aapa = vj = vk = vhf_c = vhf_a = h1 = gfock = None

    dm1 = dm_core + dm_cas
    vhf1c, vhf1a = mf_grad.get_veff(mol, (dm_core, dm_cas))

    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

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

    max_memory = mc.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, dm1)
        #de[k] -= numpy.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)
            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
            eri1 = None
        de[k] += numpy.einsum('xij,ij->x', vhf1c[:, p0:p1], dm1[p0:p1]) * 2
        de[k] += numpy.einsum('xij,ij->x', vhf1a[:, p0:p1], dm_core[p0:p1]) * 2

    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
    eri0 = ao2mo.restore(1, ao2mo.full(mc._scf._eri, mo_coeff), nmo)
    Imat = numpy.einsum('pjkl,qjkl->pq', eri0, dm2)

    dm1 = numpy.zeros((nmo, nmo))
    for i in range(ncore):
        dm1[i, i] = 2
    dm1[ncore:nocc, ncore:nocc] = casdm1

    neleca, nelecb = mol.nelec

    h1 = -(mol.intor('int1e_ipkin', comp=3) + mol.intor('int1e_ipnuc', comp=3))
    s1 = -mol.intor('int1e_ipovlp', comp=3)
    eri1 = mol.intor('int2e_ip1', comp=3).reshape(3, nao, nao, nao, nao)
    eri1 = numpy.einsum('xipkl,pj->xijkl', eri1, mo_coeff)
    eri1 = numpy.einsum('xijpl,pk->xijkl', eri1, mo_coeff)
    eri1 = numpy.einsum('xijkp,pl->xijkl', eri1, mo_coeff)
    h0 = reduce(numpy.dot, (mo_coeff.T, mc._scf.get_hcore(), mo_coeff))
    g0 = ao2mo.restore(1, ao2mo.full(mol, mo_coeff), nmo)

    def hess():
        nocc = mol.nelectron // 2
        nvir = nmo - nocc
        eri_mo = g0
        eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])
        h = eri_mo[nocc:, :nocc, nocc:, :nocc] * 4
        h -= numpy.einsum('cdlk->ckdl', eri_mo[nocc:, nocc:, :nocc, :nocc])
        h -= numpy.einsum('cldk->ckdl', eri_mo[nocc:, :nocc, nocc:, :nocc])
        for a in range(nvir):
            for i in range(nocc):
                h[a, i, a, i] += eai[a, i]
        return -h.reshape(nocc * nvir, -1)

    hh = hess()
    ee = mo_energy[:, None] - mo_energy

    for k, (sh0, sh1, p0, p1) in enumerate(mol.offset_nr_by_atom()):
        mol.set_rinv_origin(mol.atom_coord(k))
        vrinv = -mol.atom_charge(k) * mol.intor('int1e_iprinv', comp=3)

        # 2e AO integrals dot 2pdm
        for i in range(3):
            g1 = numpy.einsum('pjkl,pi->ijkl', eri1[i, p0:p1], mo_coeff[p0:p1])
            g1 = g1 + g1.transpose(1, 0, 2, 3)
            g1 = g1 + g1.transpose(2, 3, 0, 1)
            g1 *= -1
            hx = (numpy.einsum('pq,pi,qj->ij', h1[i, p0:p1], mo_coeff[p0:p1],
                               mo_coeff) +
                  reduce(numpy.dot, (mo_coeff.T, vrinv[i], mo_coeff)))
            hx = hx + hx.T
            sx = numpy.einsum('pq,pi,qj->ij', s1[i, p0:p1], mo_coeff[p0:p1],
                              mo_coeff)
            sx = sx + sx.T

            fij = (hx[:neleca, :neleca] - numpy.einsum(
                'ij,j->ij', sx[:neleca, :neleca], mo_energy[:neleca]) -
                   numpy.einsum('kl,ijlk->ij', sx[:neleca, :neleca],
                                g0[:neleca, :neleca, :neleca, :neleca]) * 2 +
                   numpy.einsum('kl,iklj->ij', sx[:neleca, :neleca],
                                g0[:neleca, :neleca, :neleca, :neleca]) +
                   numpy.einsum('ijkk->ij',
                                g1[:neleca, :neleca, :neleca, :neleca]) * 2 -
                   numpy.einsum('ikkj->ij',
                                g1[:neleca, :neleca, :neleca, :neleca]))

            fab = (hx[neleca:, neleca:] - numpy.einsum(
                'ij,j->ij', sx[neleca:, neleca:], mo_energy[neleca:]) -
                   numpy.einsum('kl,ijlk->ij', sx[:neleca, :neleca],
                                g0[neleca:, neleca:, :neleca, :neleca]) * 2 +
                   numpy.einsum('kl,iklj->ij', sx[:neleca, :neleca],
                                g0[neleca:, :neleca, :neleca, neleca:]) +
                   numpy.einsum('ijkk->ij',
                                g1[neleca:, neleca:, :neleca, :neleca]) * 2 -
                   numpy.einsum('ikkj->ij', g1[neleca:, :neleca, :neleca,
                                               neleca:]))

            fai = (hx[neleca:, :neleca] - numpy.einsum(
                'ai,i->ai', sx[neleca:, :neleca], mo_energy[:neleca]) -
                   numpy.einsum('kl,ijlk->ij', sx[:neleca, :neleca],
                                g0[neleca:, :neleca, :neleca, :neleca]) * 2 +
                   numpy.einsum('kl,iklj->ij', sx[:neleca, :neleca],
                                g0[neleca:, :neleca, :neleca, :neleca]) +
                   numpy.einsum('ijkk->ij',
                                g1[neleca:, :neleca, :neleca, :neleca]) * 2 -
                   numpy.einsum('ikkj->ij',
                                g1[neleca:, :neleca, :neleca, :neleca]))
            c1 = numpy.zeros((nmo, nmo))
            c1[:neleca, :neleca] = -.5 * sx[:neleca, :neleca]
            c1[neleca:, neleca:] = -.5 * sx[neleca:, neleca:]
            cvo1 = numpy.linalg.solve(hh, fai.ravel()).reshape(-1, neleca)
            cov1 = -(sx[neleca:, :neleca] + cvo1).T
            c1[neleca:, :neleca] = cvo1
            c1[:neleca, neleca:] = cov1
            v1 = numpy.einsum('pqai,ai->pq', g0[:, :, neleca:, :neleca],
                              cvo1) * 4
            v1 -= numpy.einsum('paiq,ai->pq', g0[:, neleca:, :neleca, :], cvo1)
            v1 -= numpy.einsum('piaq,ai->pq', g0[:, :neleca, neleca:, :], cvo1)
            fij += v1[:neleca, :neleca]
            fab += v1[neleca:, neleca:]
            c1[:ncore,
               ncore:neleca] = -fij[:ncore, ncore:] / ee[:ncore, ncore:neleca]
            c1[ncore:neleca, :ncore] = -fij[ncore:, :ncore] / ee[
                ncore:neleca, :ncore]
            m = nocc - neleca
            c1[nocc:, neleca:nocc] = -fab[m:, :m] / ee[nocc:, neleca:nocc]
            c1[neleca:nocc, nocc:] = -fab[:m, m:] / ee[neleca:nocc, nocc:]
            h0c1 = h0.dot(c1)
            h0c1 = h0c1 + h0c1.T
            g0c1 = numpy.einsum('pjkl,pi->ijkl', g0, c1)
            g0c1 = g0c1 + g0c1.transpose(1, 0, 2, 3)
            g0c1 = g0c1 + g0c1.transpose(2, 3, 0, 1)

            de[k, i] += numpy.einsum('ij,ji', h0c1, dm1)
            de[k, i] += numpy.einsum('ijkl,jilk', g0c1, dm2) * .5

    de += rhf_grad.grad_nuc(mol)
    return de
Beispiel #45
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma_in_d2h = numpy.asarray(orbsyma) % 10
        orbsymb_in_d2h = numpy.asarray(orbsymb) % 10
        sym_forbida = (orbsyma_in_d2h[occidxa, None]
                       ^ orbsyma_in_d2h[viridxa]) != wfnsym
        sym_forbidb = (orbsymb_in_d2h[occidxb, None]
                       ^ orbsymb_in_d2h[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
    e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
    e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = mf.gen_response(hermi=0, max_memory=max_memory)

    def vind(xys):
        nz = len(xys)
        xys = numpy.asarray(xys).reshape(nz, 2, -1)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,-1): 2 ~ X,Y
            xys = numpy.copy(xys)
            xys[:, :, sym_forbid] = 0

        xs, ys = xys.transpose(1, 0, 2)
        xa = xs[:, :nocca * nvira].reshape(nz, nocca, nvira)
        xb = xs[:, nocca * nvira:].reshape(nz, noccb, nvirb)
        ya = ys[:, :nocca * nvira].reshape(nz, nocca, nvira)
        yb = ys[:, nocca * nvira:].reshape(nz, noccb, nvirb)
        # dms = AX + BY
        dmsa = lib.einsum('xov,po,qv->xpq', xa, orboa, orbva.conj())
        dmsa += lib.einsum('xov,pv,qo->xpq', ya, orbva, orboa.conj())
        dmsb = lib.einsum('xov,po,qv->xpq', xb, orbob, orbvb.conj())
        dmsb += lib.einsum('xov,pv,qo->xpq', yb, orbvb, orbob.conj())

        v1ao = vresp(numpy.asarray((dmsa, dmsb)))

        v1aov = lib.einsum('xpq,po,qv->xov', v1ao[0], orboa.conj(), orbva)
        v1bov = lib.einsum('xpq,po,qv->xov', v1ao[1], orbob.conj(), orbvb)
        v1avo = lib.einsum('xpq,pv,qo->xov', v1ao[0], orbva.conj(), orboa)
        v1bvo = lib.einsum('xpq,pv,qo->xov', v1ao[1], orbvb.conj(), orbob)

        v1ov = xs * e_ia  # AX
        v1vo = ys * e_ia  # AY
        v1ov[:, :nocca * nvira] += v1aov.reshape(nz, -1)
        v1vo[:, :nocca * nvira] += v1avo.reshape(nz, -1)
        v1ov[:, nocca * nvira:] += v1bov.reshape(nz, -1)
        v1vo[:, nocca * nvira:] += v1bvo.reshape(nz, -1)
        if wfnsym is not None and mol.symmetry:
            v1ov[:, sym_forbid] = 0
            v1vo[:, sym_forbid] = 0
        hx = numpy.hstack((v1ov, -v1vo))
        return hx

    return vind, hdiag
Beispiel #46
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):
        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 #47
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):
        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 #48
0
def _ci_min_epdft_fp(mc, mo_coeff, ci0, hcas=None, verbose=None):
    ''' Minimize the PDFT energy of a single state by repeated diagonalizations of the effective 
    PDFT Hamiltonian hpdft = Pcas (vnuc + dE/drdm1 op1 + dE/drdm2 op2) Pcas
    (as if that makes sense...) 

    Args:
        mc : mcscf object
        mo_coeff : ndarray of shape (nao,nmo)
        ci0 : ndarray of size (ndeta*ndetb)
            Initial guess CI vector; required!

    Kwargs:
        hcas : (float, [ncas,]*2 ndarray, [ncas,]*4 ndarray) or None
            The true Hamiltonian projected into the active space
        verbose : integer
            logger verbosity of function output; defaults to mc.verbose

    Returns:
        epdft : float
            Minimized MC-PDFT energy
        h0_pdft : float
            At convergence, the constant term of hpdft
            You might need this because ????
        ci1 : ndarray of size (ndeta*ndetb)
            Optimized CI vector
        emcscf : float or None
            <ci1|hcas|ci1>
    '''
    t0 = (time.process_time(), time.time())
    ncas, nelecas = mc.ncas, mc.nelecas
    if verbose is None: verbose = mc.verbose
    log = logger.new_logger(mc, verbose)
    if hasattr(mc.fcisolver, 'gen_linkstr'):
        linkstrl = mc.fcisolver.gen_linkstr(ncas, nelecas, True)
    else:
        linkstrl = None
    h0_pdft, h1_pdft, h2_pdft = get_heff_cas(mc, mo_coeff, ci0)
    max_memory = max(400, mc.max_memory - lib.current_memory()[0])

    epdft = 0
    chc_last = 0
    emcscf = None
    ci1 = ci0.copy()
    for it in range(mc.max_cycle_fp):
        h2eff = mc.fcisolver.absorb_h1e(h1_pdft, h2_pdft, ncas, nelecas, 0.5)
        hc = mc.fcisolver.contract_2e(h2eff,
                                      ci1,
                                      ncas,
                                      nelecas,
                                      link_index=linkstrl).ravel()
        chc = ci1.conj().ravel().dot(hc)
        ci_grad = hc - (chc * ci1.ravel())
        ci_grad_norm = ci_grad.dot(ci_grad)
        epdft_last = epdft
        epdft = mcpdft.energy_tot(mc, mc.otfnal, mo_coeff=mo_coeff, ci=ci1)[0]

        dchc = chc + h0_pdft - chc_last  # careful; don't mess up ci_grad
        depdft = epdft - epdft_last
        if hcas is None:
            log.info(
                'MC-PDFT CI fp iter %d EPDFT = %e, |grad| = %e, dEPDFT = %e, d<c.Hpdft.c> = %e',
                it, epdft, ci_grad_norm, depdft, dchc)
        else:
            h2eff = mc.fcisolver.absorb_h1e(hcas[1], hcas[2], ncas, nelecas,
                                            0.5)
            hc = mc.fcisolver.contract_2e(h2eff,
                                          ci1,
                                          ncas,
                                          nelecas,
                                          link_index=linkstrl).ravel()
            emcscf = ci1.conj().ravel().dot(hc) + hcas[0]
            log.info(
                'MC-PDFT CI fp iter %d ECAS = %e, EPDFT = %e, |grad| = %e, dEPDFT = %e, d<c.Hpdft.c> = %e',
                it, emcscf, epdft, ci_grad_norm, depdft, dchc)

        if ci_grad_norm < mc.conv_tol_ci_fp and np.abs(
                dchc) < mc.conv_tol_ci_fp:
            break

        chc_last, ci1 = mc.fcisolver.kernel(h1_pdft,
                                            h2_pdft,
                                            ncas,
                                            nelecas,
                                            ci0=ci1,
                                            verbose=log,
                                            max_memory=max_memory,
                                            ecore=h0_pdft)
        h0_pdft, h1_pdft, h2_pdft = get_heff_cas(mc, mo_coeff, ci1)
        # putting this at the bottom to 1) get a good max_memory outside the loop with 2) as few integrations as possible

    log.timer('MC-PDFT CI fp iteration', *t0)
    return epdft, h0_pdft, ci1, emcscf
Beispiel #49
0
def cas_natorb(mc,
               mo_coeff=None,
               ci=None,
               eris=None,
               sort=False,
               casdm1=None,
               verbose=None,
               with_meta_lowdin=WITH_META_LOWDIN):
    '''Transform active orbitals to natrual orbitals, and update the CI wfn
    accordingly

    Args:
        mc : a CASSCF/CASCI object or RHF object

    Kwargs:
        sort : bool
            Sort natural orbitals wrt the occupancy.

    Returns:
        A tuple, the first item is natural orbitals, the second is updated CI
        coefficients, the third is the natural occupancy associated to the
        natural orbitals.
    '''
    from pyscf.lo import orth
    from pyscf.tools import dump_mat
    from pyscf.tools.mo_mapping import mo_1to1map
    if mo_coeff is None: mo_coeff = mc.mo_coeff
    if ci is None: ci = mc.ci
    log = logger.new_logger(mc, verbose)
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    if casdm1 is None:
        casdm1 = mc.fcisolver.make_rdm1(ci, ncas, nelecas)
    # orbital symmetry is reserved in this _eig call
    occ, ucas = mc._eig(-casdm1, ncore, nocc)
    if sort:
        casorb_idx = numpy.argsort(occ.round(9), kind='mergesort')
        occ = occ[casorb_idx]
        ucas = ucas[:, casorb_idx]

    occ = -occ
    mo_occ = numpy.zeros(mo_coeff.shape[1])
    mo_occ[:ncore] = 2
    mo_occ[ncore:nocc] = occ

    mo_coeff1 = mo_coeff.copy()
    mo_coeff1[:, ncore:nocc] = numpy.dot(mo_coeff[:, ncore:nocc], ucas)
    if getattr(mo_coeff, 'orbsym', None) is not None:
        orbsym = numpy.copy(mo_coeff.orbsym)
        if sort:
            orbsym[ncore:nocc] = orbsym[ncore:nocc][casorb_idx]
        mo_coeff1 = lib.tag_array(mo_coeff1, orbsym=orbsym)

    fcivec = None
    if getattr(mc.fcisolver, 'transform_ci_for_orbital_rotation', None):
        if isinstance(ci, numpy.ndarray):
            fcivec = mc.fcisolver.transform_ci_for_orbital_rotation(
                ci, ncas, nelecas, ucas)
        elif (isinstance(ci, (list, tuple))
              and all(isinstance(x[0], numpy.ndarray) for x in ci)):
            fcivec = [
                mc.fcisolver.transform_ci_for_orbital_rotation(
                    x, ncas, nelecas, ucas) for x in ci
            ]
    elif getattr(mc.fcisolver, 'states_transform_ci_for_orbital_rotation',
                 None):
        fcivec = mc.fcisolver.states_transform_ci_for_orbital_rotation(
            ci, ncas, nelecas, ucas)

    if fcivec is None:
        log.info('FCI vector not available, call CASCI to update wavefunction')
        mocas = mo_coeff1[:, ncore:nocc]
        hcore = mc.get_hcore()
        dm_core = numpy.dot(mo_coeff1[:, :ncore] * 2, mo_coeff1[:, :ncore].T)
        ecore = mc.energy_nuc()
        ecore += numpy.einsum('ij,ji', hcore, dm_core)
        h1eff = reduce(numpy.dot, (mocas.T, hcore, mocas))
        if getattr(eris, 'ppaa', None) is not None:
            ecore += eris.vhf_c[:ncore, :ncore].trace()
            h1eff += reduce(numpy.dot,
                            (ucas.T, eris.vhf_c[ncore:nocc, ncore:nocc], ucas))
            aaaa = ao2mo.restore(4, eris.ppaa[ncore:nocc, ncore:nocc, :, :],
                                 ncas)
            aaaa = ao2mo.incore.full(aaaa, ucas)
        else:
            if getattr(mc, 'with_df', None):
                raise NotImplementedError('cas_natorb for DFCASCI/DFCASSCF')
            corevhf = mc.get_veff(mc.mol, dm_core)
            ecore += numpy.einsum('ij,ji', dm_core, corevhf) * .5
            h1eff += reduce(numpy.dot, (mocas.T, corevhf, mocas))
            aaaa = ao2mo.kernel(mc.mol, mocas)

        # See label_symmetry_ function in casci_symm.py which initialize the
        # orbital symmetry information in fcisolver.  This orbital symmetry
        # labels should be reordered to match the sorted active space orbitals.
        if sort and getattr(mo_coeff1, 'orbsym', None) is not None:
            mc.fcisolver.orbsym = mo_coeff1.orbsym[ncore:nocc]

        max_memory = max(400, mc.max_memory - lib.current_memory()[0])
        e, fcivec = mc.fcisolver.kernel(h1eff,
                                        aaaa,
                                        ncas,
                                        nelecas,
                                        ecore=ecore,
                                        max_memory=max_memory,
                                        verbose=log)
        log.debug('In Natural orbital, CASCI energy = %s', e)

    if log.verbose >= logger.INFO:
        ovlp_ao = mc._scf.get_ovlp()
        # where_natorb gives the new locations of the natural orbitals
        where_natorb = mo_1to1map(ucas)
        log.debug('where_natorb %s', str(where_natorb))
        log.info('Natural occ %s', str(occ))
        if with_meta_lowdin:
            log.info(
                'Natural orbital (expansion on meta-Lowdin AOs) in CAS space')
            label = mc.mol.ao_labels()
            orth_coeff = orth.orth_ao(mc.mol, 'meta_lowdin', s=ovlp_ao)
            mo_cas = reduce(numpy.dot,
                            (orth_coeff.T, ovlp_ao, mo_coeff1[:, ncore:nocc]))
        else:
            log.info('Natural orbital (expansion on AOs) in CAS space')
            label = mc.mol.ao_labels()
            mo_cas = mo_coeff1[:, ncore:nocc]
        dump_mat.dump_rec(log.stdout, mo_cas, label, start=1)

        if mc._scf.mo_coeff is not None:
            s = reduce(numpy.dot, (mo_coeff1[:, ncore:nocc].T,
                                   mc._scf.get_ovlp(), mc._scf.mo_coeff))
            idx = numpy.argwhere(abs(s) > .4)
            for i, j in idx:
                log.info('<CAS-nat-orb|mo-hf>  %d  %d  %12.8f', ncore + i + 1,
                         j + 1, s[i, j])
    return mo_coeff1, fcivec, mo_occ
Beispiel #50
0
def cas_natorb(mc,
               mo_coeff=None,
               ci=None,
               eris=None,
               sort=False,
               casdm1=None,
               verbose=None,
               with_meta_lowdin=WITH_META_LOWDIN):
    '''Transform active orbitals to natrual orbitals, and update the CI wfn

    Args:
        mc : a CASSCF/CASCI object or RHF object

    Kwargs:
        sort : bool
            Sort natural orbitals wrt the occupancy.

    Returns:
        A tuple, the first item is natural orbitals, the second is updated CI
        coefficients, the third is the natural occupancy associated to the
        natural orbitals.
    '''
    from pyscf.lo import orth
    from pyscf.tools import dump_mat
    from pyscf.tools.mo_mapping import mo_1to1map
    if mo_coeff is None: mo_coeff = mc.mo_coeff
    if ci is None: ci = mc.ci
    log = logger.new_logger(mc, verbose)
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    if casdm1 is None:
        casdm1 = mc.fcisolver.make_rdm1(ci, ncas, nelecas)
    # orbital symmetry is reserved in this _eig call
    occ, ucas = mc._eig(-casdm1, ncore, nocc)
    if sort:
        casorb_idx = numpy.argsort(occ.round(9), kind='mergesort')
        occ = occ[casorb_idx]
        ucas = ucas[:, casorb_idx]


# restore phase
# where_natorb gives the location of the natural orbital for the input cas
# orbitals.  gen_strings4orblist map thes sorted strings (on CAS orbital) to
# the unsorted determinant strings (on natural orbital). e.g.  (3o,2e) system
#       CAS orbital      1  2  3
#       natural orbital  3  1  2        <= by mo_1to1map
#       CASorb-strings   0b011, 0b101, 0b110
#                    ==  (1,2), (1,3), (2,3)
#       natorb-strings   (3,1), (3,2), (1,2)
#                    ==  0B101, 0B110, 0B011    <= by gen_strings4orblist
# then argsort to translate the string representation to the address
#       [2(=0B011), 0(=0B101), 1(=0B110)]
# to indicate which CASorb-strings address to be loaded in each natorb-strings slot
    where_natorb = mo_1to1map(ucas)

    occ = -occ
    mo_occ = numpy.zeros(mo_coeff.shape[1])
    mo_occ[:ncore] = 2
    mo_occ[ncore:nocc] = occ

    mo_coeff1 = mo_coeff.copy()
    mo_coeff1[:, ncore:nocc] = numpy.dot(mo_coeff[:, ncore:nocc], ucas)
    if hasattr(mo_coeff, 'orbsym'):
        orbsym = numpy.copy(mo_coeff.orbsym)
        if sort:
            orbsym[ncore:nocc] = orbsym[ncore:nocc][casorb_idx]
        mo_coeff1 = lib.tag_array(mo_coeff1, orbsym=orbsym)

    if isinstance(ci, numpy.ndarray):
        fcivec = fci.addons.transform_ci_for_orbital_rotation(
            ci, ncas, nelecas, ucas)
    elif isinstance(ci, (tuple, list)) and isinstance(ci[0], numpy.ndarray):
        # for state-average eigenfunctions
        fcivec = [
            fci.addons.transform_ci_for_orbital_rotation(
                x, ncas, nelecas, ucas) for x in ci
        ]
    else:
        log.info('FCI vector not available, call CASCI for wavefunction')
        mocas = mo_coeff1[:, ncore:nocc]
        hcore = mc.get_hcore()
        dm_core = numpy.dot(mo_coeff1[:, :ncore] * 2, mo_coeff1[:, :ncore].T)
        ecore = mc.energy_nuc()
        ecore += numpy.einsum('ij,ji', hcore, dm_core)
        h1eff = reduce(numpy.dot, (mocas.T, hcore, mocas))
        if eris is not None and hasattr(eris, 'ppaa'):
            ecore += eris.vhf_c[:ncore, :ncore].trace()
            h1eff += reduce(numpy.dot,
                            (ucas.T, eris.vhf_c[ncore:nocc, ncore:nocc], ucas))
            aaaa = ao2mo.restore(4, eris.ppaa[ncore:nocc, ncore:nocc, :, :],
                                 ncas)
            aaaa = ao2mo.incore.full(aaaa, ucas)
        else:
            if getattr(mc, 'with_df', None):
                raise NotImplementedError('cas_natorb for DFCASCI/DFCASSCF')
            corevhf = mc.get_veff(mc.mol, dm_core)
            ecore += numpy.einsum('ij,ji', dm_core, corevhf) * .5
            h1eff += reduce(numpy.dot, (mocas.T, corevhf, mocas))
            aaaa = ao2mo.kernel(mc.mol, mocas)

        # See label_symmetry_ function in casci_symm.py which initialize the
        # orbital symmetry information in fcisolver.  This orbital symmetry
        # labels should be reordered to match the sorted active space orbitals.
        if hasattr(mo_coeff1, 'orbsym') and sort:
            mc.fcisolver.orbsym = mo_coeff1.orbsym[ncore:nocc]

        max_memory = max(400, mc.max_memory - lib.current_memory()[0])
        e, fcivec = mc.fcisolver.kernel(h1eff,
                                        aaaa,
                                        ncas,
                                        nelecas,
                                        ecore=ecore,
                                        max_memory=max_memory,
                                        verbose=log)
        log.debug('In Natural orbital, CASCI energy = %s', e)

    if log.verbose >= logger.INFO:
        ovlp_ao = mc._scf.get_ovlp()
        log.debug('where_natorb %s', str(where_natorb))
        log.info('Natural occ %s', str(occ))
        if with_meta_lowdin:
            log.info(
                'Natural orbital (expansion on meta-Lowdin AOs) in CAS space')
            label = mc.mol.ao_labels()
            orth_coeff = orth.orth_ao(mc.mol, 'meta_lowdin', s=ovlp_ao)
            mo_cas = reduce(numpy.dot,
                            (orth_coeff.T, ovlp_ao, mo_coeff1[:, ncore:nocc]))
        else:
            log.info('Natural orbital (expansion on AOs) in CAS space')
            label = mc.mol.ao_labels()
            mo_cas = mo_coeff1[:, ncore:nocc]
        dump_mat.dump_rec(log.stdout, mo_cas, label, start=1)

        if mc._scf.mo_coeff is not None:
            s = reduce(numpy.dot, (mo_coeff1[:, ncore:nocc].T,
                                   mc._scf.get_ovlp(), mc._scf.mo_coeff))
            idx = numpy.argwhere(abs(s) > .4)
            for i, j in idx:
                log.info('<CAS-nat-orb|mo-hf>  %d  %d  %12.8f', ncore + i + 1,
                         j + 1, s[i, j])
    return mo_coeff1, fcivec, mo_occ
Beispiel #51
0
def gamma2_outcore(mycc, t1, t2, l1, l2, h5fobj, max_memory=2000):
    log = logger.Logger(mycc.stdout, mycc.verbose)
    nocc, nvir = t1.shape
    nov = nocc * nvir
    nvir_pair = nvir * (nvir + 1) // 2
    dovov = h5fobj.create_dataset('dovov', (nocc, nvir, nocc, nvir), 'f8')
    dvvvv = h5fobj.create_dataset('dvvvv', (nvir_pair, nvir_pair), 'f8')
    doooo = h5fobj.create_dataset('doooo', (nocc, nocc, nocc, nocc), 'f8')
    doovv = h5fobj.create_dataset('doovv', (nocc, nocc, nvir, nvir), 'f8')
    dovvo = h5fobj.create_dataset('dovvo', (nocc, nvir, nvir, nocc), 'f8')
    dooov = h5fobj.create_dataset('dooov', (nocc, nocc, nocc, nvir), 'f8')

    _tmpfile = tempfile.NamedTemporaryFile()
    fswap = h5py.File(_tmpfile.name)
    mOvOv = fswap.create_dataset('mOvOv', (nocc, nvir, nocc, nvir), 'f8')
    mOVov = fswap.create_dataset('mOVov', (nocc, nvir, nocc, nvir), 'f8')

    moo = numpy.empty((nocc, nocc))
    mvv = numpy.zeros((nvir, nvir))

    max_memory1 = max_memory - lib.current_memory()[0]
    unit = nocc * nvir**2 * 5
    blksize = max(ccsd.BLKMIN, int(max_memory1 * .95e6 / 8 / unit))
    log.debug1(
        'rdm intermediates pass 1: block size = %d, nocc = %d in %d blocks',
        blksize, nocc, int((nocc + blksize - 1) / blksize))
    time1 = time.clock(), time.time()
    for istep, (p0, p1) in enumerate(prange(0, nocc, blksize)):
        #:theta = make_theta(t2[p0:p1])
        #:pOvOv = numpy.einsum('ikca,jkcb->jbia', l2, t2[p0:p1])
        #:pOVov = -numpy.einsum('ikca,jkbc->jbia', l2, t2[p0:p1])
        #:pOVov += numpy.einsum('ikac,jkbc->jbia', l2, theta)
        pOvOv = numpy.empty((nocc, p1 - p0, nvir, nvir))
        pOVov = numpy.empty((nocc, p1 - p0, nvir, nvir))
        t2a = numpy.empty((p1 - p0, nvir, nocc, nvir))
        t2b = numpy.empty((p1 - p0, nvir, nocc, nvir))
        theta = make_theta(t2[p0:p1])
        tmp = numpy.empty_like(t2a)
        for i in range(p1 - p0):
            t2a[i] = t2[p0 + i].transpose(2, 0, 1)
            t2b[i] = t2[p0 + i].transpose(1, 0, 2)
            tmp[i] = theta[i].transpose(1, 0, 2)
        t2a = t2a.reshape(-1, nov)
        t2b = t2b.reshape(-1, nov)
        theta, tmp = tmp.reshape(-1, nov), None
        for i in range(nocc):
            pOvOv[i] = lib.dot(t2a, l2[i].reshape(nov,
                                                  -1)).reshape(-1, nvir, nvir)
            pOVov[i] = lib.dot(t2b, l2[i].reshape(nov, -1),
                               -1).reshape(-1, nvir, nvir)
            pOVov[i] += lib.dot(theta,
                                _cp(l2[i].transpose(0, 2, 1).reshape(
                                    nov, -1))).reshape(-1, nvir, nvir)
        theta = t2a = t2b = None
        mOvOv[p0:p1] = pOvOv.transpose(1, 2, 0, 3)
        mOVov[p0:p1] = pOVov.transpose(1, 2, 0, 3)
        fswap['mvOvO/%d' % istep] = pOvOv.transpose(3, 1, 2, 0)
        fswap['mvOVo/%d' % istep] = pOVov.transpose(3, 1, 2, 0)
        moo[p0:p1] = (numpy.einsum('ljdd->jl', pOvOv) * 2 +
                      numpy.einsum('ljdd->jl', pOVov))
        mvv += (numpy.einsum('llbd->bd', pOvOv[p0:p1]) * 2 +
                numpy.einsum('llbd->bd', pOVov[p0:p1]))
        pOvOv = pOVov = None
        time1 = log.timer_debug1('rdm intermediates pass1 [%d:%d]' % (p0, p1),
                                 *time1)
    mia = (numpy.einsum('kc,ikac->ia', l1, t2) * 2 -
           numpy.einsum('kc,ikca->ia', l1, t2))
    mab = numpy.einsum('kc,kb->cb', l1, t1)
    mij = numpy.einsum('kc,jc->jk', l1, t1) + moo * .5

    gooov = numpy.einsum('ji,ka->jkia', moo * -.5, t1)
    max_memory1 = max_memory - lib.current_memory()[0]
    unit = nocc**3 + nocc**2 * nvir + nocc * nvir**2 * 6
    blksize = max(ccsd.BLKMIN, int(max_memory1 * .95e6 / 8 / unit))
    log.debug1(
        'rdm intermediates pass 2: block size = %d, nocc = %d in %d blocks',
        blksize, nocc, int((nocc + blksize - 1) / blksize))
    for p0, p1 in prange(0, nocc, blksize):
        tau = _ccsd.make_tau(t2[p0:p1], t1[p0:p1], t1)
        #:goooo = numpy.einsum('ijab,klab->klij', l2, tau)*.5
        goooo = lib.dot(tau.reshape(-1, nvir**2),
                        l2.reshape(-1, nvir**2).T, .5)
        goooo = goooo.reshape(-1, nocc, nocc, nocc)
        h5fobj['doooo'][p0:p1] = make_theta(goooo).transpose(0, 2, 1, 3)

        #:gooov[p0:p1] -= numpy.einsum('ib,jkba->jkia', l1, tau)
        #:gooov[p0:p1] -= numpy.einsum('jkba,ib->jkia', l2[p0:p1], t1)
        #:gooov[p0:p1] += numpy.einsum('jkil,la->jkia', goooo, t1*2)
        for i in range(p0, p1):
            gooov[i] -= lib.dot(
                _cp(tau[i - p0].transpose(0, 2, 1).reshape(-1, nvir)),
                l1.T).reshape(nocc, nvir, nocc).transpose(0, 2, 1)
            gooov[i] -= lib.dot(
                _cp(l2[i].transpose(0, 2, 1).reshape(-1, nvir)),
                t1.T).reshape(nocc, nvir, nocc).transpose(0, 2, 1)
        lib.dot(goooo.reshape(-1, nocc), t1, 2, gooov[p0:p1].reshape(-1, nvir),
                1)

        #:goovv -= numpy.einsum('jk,ikab->ijab', mij, tau)
        goovv = numpy.einsum('ia,jb->ijab', mia[p0:p1], t1)
        for i in range(p1 - p0):
            lib.dot(mij, tau[i].reshape(nocc, -1), -1,
                    goovv[i].reshape(nocc, -1), 1)
            goovv[i] += .5 * l2[p0 + i]
            goovv[i] += .5 * tau[i]
        #:goovv -= numpy.einsum('cb,ijac->ijab', mab, t2[p0:p1])
        #:goovv -= numpy.einsum('bd,ijad->ijab', mvv*.5, tau)
        lib.dot(t2[p0:p1].reshape(-1, nvir), mab, -1, goovv.reshape(-1, nvir),
                1)
        lib.dot(tau.reshape(-1, nvir), mvv.T, -.5, goovv.reshape(-1, nvir), 1)
        tau = None
        #==== mem usage nocc**3 + nocc*nvir**2

        pOvOv = _cp(mOvOv[p0:p1])
        pOVov = _cp(mOVov[p0:p1])
        #:gooov[p0:p1,:] += numpy.einsum('jaic,kc->jkia', pOvOv, t1)
        #:gooov[:,p0:p1] -= numpy.einsum('kaic,jc->jkia', pOVov, t1)
        tmp = lib.dot(pOvOv.reshape(-1, nvir),
                      t1.T).reshape(p1 - p0, -1, nocc, nocc)
        gooov[p0:p1, :] += tmp.transpose(0, 3, 2, 1)
        lib.dot(t1, pOVov.reshape(-1, nvir).T, 1, tmp.reshape(nocc, -1), 0)
        gooov[:, p0:p1] -= tmp.reshape(nocc, p1 - p0, nvir,
                                       nocc).transpose(0, 1, 3, 2)
        #:tmp = numpy.einsum('ikac,jc->jika', l2, t1[p0:p1])
        #:gOvVo -= numpy.einsum('jika,kb->jabi', tmp, t1)
        #:gOvvO = numpy.einsum('jkia,kb->jabi', tmp, t1) + pOvOv.transpose(0,3,1,2)
        tmp = tmp.reshape(-1, nocc, nocc, nvir)
        lib.dot(t1[p0:p1], l2.reshape(-1, nvir).T, 1, tmp.reshape(p1 - p0, -1))
        gOvVo = numpy.einsum('ia,jb->jabi', l1, t1[p0:p1])
        gOvvO = numpy.empty((p1 - p0, nvir, nvir, nocc))
        for i in range(p1 - p0):
            gOvVo[i] -= lib.dot(
                _cp(tmp[i].transpose(0, 2, 1).reshape(-1, nocc)),
                t1).reshape(nocc, nvir, -1).transpose(1, 2, 0)
            gOvVo[i] += pOVov[i].transpose(2, 0, 1)
            gOvvO[i] = lib.dot(tmp[i].reshape(nocc, -1).T,
                               t1).reshape(nocc, nvir, -1).transpose(1, 2, 0)
            gOvvO[i] += pOvOv[i].transpose(2, 0, 1)
        tmp = None
        #==== mem usage nocc**3 + nocc*nvir**6
        dovvo[p0:p1] = (gOvVo * 2 + gOvvO).transpose(0, 2, 1, 3)
        gOvvO *= -2
        gOvvO -= gOvVo
        doovv[p0:p1] = gOvvO.transpose(0, 3, 1, 2)
        gOvvO = gOvVo = None

        for j0, j1 in prange(0, nocc, blksize):
            tau2 = _ccsd.make_tau(t2[j0:j1], t1[j0:j1], t1)
            #:goovv += numpy.einsum('ijkl,klab->ijab', goooo[:,:,j0:j1], tau2)
            lib.dot(goooo[:, :, j0:j1].copy().reshape((p1 - p0) * nocc, -1),
                    tau2.reshape(-1, nvir**2), 1, goovv.reshape(-1, nvir**2),
                    1)
            tau2 += numpy.einsum('ia,jb->ijab', t1[j0:j1], t1)
            tau2 = _cp(tau2.transpose(0, 3, 1, 2).reshape(-1, nov))
            #:goovv[:,j0:j1] += numpy.einsum('ibld,jlda->ijab', pOvOv, tau2) * .5
            #:goovv[:,j0:j1] -= numpy.einsum('iald,jldb->ijab', pOVov, tau2) * .5
            goovv[:, j0:j1] += lib.dot(pOvOv.reshape(-1, nov), tau2.T,
                                       .5).reshape(p1 - p0, nvir, -1,
                                                   nvir).transpose(0, 2, 3, 1)
            goovv[:,
                  j0:j1] += lib.dot(pOVov.reshape(-1, nov), tau2.T,
                                    -.5).reshape(p1 - p0, nvir, -1,
                                                 nvir).transpose(0, 2, 1, 3)
            tau2 = None
#==== mem usage nocc**3 + nocc*nvir**2*7
#:goovv += numpy.einsum('iald,jlbd->ijab', pOVov*2+pOvOv, t2) * .5
        pOVov *= 2
        pOVov += pOvOv
        for j in range(nocc):
            tmp = lib.dot(pOVov.reshape(-1, nov),
                          _cp(t2[j].transpose(0, 2, 1).reshape(-1, nvir)), .5)
            goovv[:, j] += tmp.reshape(-1, nvir, nvir)
            tmp = None
        dovov[p0:p1] = make_theta(goovv).transpose(0, 2, 1, 3)
        goooo = goovv = pOvOv = pOVov = None
        time1 = log.timer_debug1('rdm intermediates pass2 [%d:%d]' % (p0, p1),
                                 *time1)

    h5fobj['dooov'][:] = gooov.transpose(0, 2, 1, 3) * 2 - gooov.transpose(
        1, 2, 0, 3)
    gooov = None

    max_memory1 = max_memory - lib.current_memory()[0]
    unit = max(nocc**2 * nvir * 2 + nocc * nvir**2 * 2,
               nvir**3 * 2 + nocc * nvir**2)
    blksize = max(ccsd.BLKMIN, int(max_memory1 * .95e6 / 8 / unit))
    iobuflen = int(256e6 / 8 / blksize)
    log.debug1(
        'rdm intermediates pass 3: block size = %d, nvir = %d in %d blocks',
        blksize, nocc, int((nvir + blksize - 1) / blksize))
    h5fobj.create_group('dovvv')
    for istep, (p0, p1) in enumerate(prange(0, nvir, blksize)):
        pvOvO = numpy.empty((p1 - p0, nocc, nvir, nocc))
        pvOVo = numpy.empty((p1 - p0, nocc, nvir, nocc))
        ao2mo.outcore._load_from_h5g(fswap['mvOvO'], p0, p1, pvOvO)
        ao2mo.outcore._load_from_h5g(fswap['mvOVo'], p0, p1, pvOVo)
        #:gvovv -= numpy.einsum('aibk,kc->aibc', pvOvO, t1)
        #:gvovv += numpy.einsum('aick,kb->aibc', pvOVo, t1)
        gvovv = lib.dot(pvOVo.reshape(-1, nocc),
                        t1).reshape(-1, nocc, nvir, nvir)
        for i in range(p1 - p0):
            gvovv[i] = gvovv[i].transpose(0, 2, 1)
        lib.dot(pvOvO.reshape(-1, nocc), t1, -1, gvovv.reshape(-1, nvir), 1)
        pvOvO = pvOVo = None
        #==== mem usage nocc**2*nvir*2 + nocc*nvir**2*2

        l2tmp = l2[:, :, p0:p1] * .5
        #:gvvvv = numpy.einsum('ijab,ijcd->abcd', l2tmp, t2)
        #:jabc = numpy.einsum('ijab,ic->jabc', l2tmp, t1)
        #:gvvvv += numpy.einsum('jabc,jd->abcd', jabc, t1)
        gvvvv = lib.dot(l2tmp.reshape(nocc**2, -1).T, t2.reshape(nocc**2, -1))
        jabc = lib.dot(l2tmp.reshape(nocc, -1).T, t1)
        lib.dot(jabc.reshape(nocc, -1).T, t1, 1, gvvvv.reshape(-1, nvir), 1)
        gvvvv = gvvvv.reshape(-1, nvir, nvir, nvir)
        l2tmp = jabc = None

        #:gvovv = numpy.einsum('ja,jibc->aibc', l1[:,p0:p1], t2)
        #:gvovv += numpy.einsum('jibc,ja->aibc', l2, t1[:,p0:p1])
        lib.dot(l1[:, p0:p1].copy().T, t2.reshape(nocc, -1), 1,
                gvovv.reshape(p1 - p0, -1), 1)
        lib.dot(t1[:, p0:p1].copy().T, l2.reshape(nocc, -1), 1,
                gvovv.reshape(p1 - p0, -1), 1)
        tmp = numpy.einsum('ja,jb->ab', l1[:, p0:p1], t1)
        gvovv += numpy.einsum('ab,ic->aibc', tmp, t1)
        gvovv += numpy.einsum('ba,ic->aibc', mvv[:, p0:p1] * .5, t1)
        #:gvovv -= numpy.einsum('adbc,id->aibc', gvvvv, t1*2)
        for j in range(p1 - p0):
            lib.dot(t1, gvvvv[j].reshape(nvir, -1), -2,
                    gvovv[j].reshape(nocc, -1), 1)


# symmetrize dvvvv because it is symmetrized in ccsd_grad and make_rdm2 anyway
#:dvvvv = .5*(gvvvv+gvvvv.transpose(0,1,3,2))
#:dvvvv = .5*(dvvvv+dvvvv.transpose(1,0,3,2))
# now dvvvv == dvvvv.transpose(2,3,0,1) == dvvvv.transpose(0,1,3,2) == dvvvv.transpose(1,0,3,2)
        tmp = numpy.empty((nvir, nvir, nvir))
        tmp1 = numpy.empty((nvir, nvir, nvir))
        tmpvvvv = numpy.empty((p1 - p0, nvir, nvir_pair))
        for i in range(p1 - p0):
            make_theta(gvvvv[i:i + 1], out=tmp)
            tmp1[:] = tmp.transpose(1, 0, 2)
            _ccsd.precontract(tmp1, diag_fac=2, 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(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
        for i in range(p1, nvir):
            off = i * (i + 1) // 2
            dvvvv[off + p0:off + p1] = tmpvvvv[:, i]
        tmp = tmp1 = tmpvvvv = None
        #==== mem usage nvir**3 + nocc*nvir**2
        gvvov = make_theta(gvovv).transpose(0, 2, 1, 3)
        ao2mo.outcore._transpose_to_h5g(h5fobj, 'dovvv/%d' % istep,
                                        gvvov.reshape(-1, nov), iobuflen)
        gvvvv = None
        gvovv = None
        time1 = log.timer_debug1('rdm intermediates pass3 [%d:%d]' % (p0, p1),
                                 *time1)

    del (fswap['mOvOv'])
    del (fswap['mOVov'])
    del (fswap['mvOvO'])
    del (fswap['mvOVo'])
    fswap.close()
    _tmpfile = None
    return (h5fobj['dovov'], h5fobj['dvvvv'], h5fobj['doooo'], h5fobj['doovv'],
            h5fobj['dovvo'], None, h5fobj['dovvv'], h5fobj['dooov'])
Beispiel #52
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional

    .. note::
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Kwargs:
        dm_last : ndarray or a list of ndarrays or 0
            The density matrix baseline.  If not 0, this function computes the
            increment of HF potential w.r.t. the reference HF potential matrix.
        vhf_last : ndarray or a list of ndarrays or 0
            The reference Vxc potential matrix.
        hermi : int
            Whether J, K matrix is hermitian

            | 0 : no hermitian or symmetric
            | 1 : hermitian
            | 2 : anti-hermitian

    Returns:
        matrix Veff = J + Vxc.  Veff can be a list matrices, if the input
        dm is a list of density matrices.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    t0 = (time.clock(), time.time())

    ground_state = (isinstance(dm, numpy.ndarray) and dm.ndim == 2)

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            ks.grids = rks.prune_small_rho_grids_(ks, mol, dm, ks.grids)
        t0 = logger.timer(ks, 'setting up grids', *t0)

    if hermi == 2:  # because rho = 0
        n, exc, vxc = 0, 0, 0
    else:
        max_memory = ks.max_memory - lib.current_memory()[0]
        n, exc, vxc = ks._numint.r_vxc(mol,
                                       ks.grids,
                                       ks.xc,
                                       dm,
                                       hermi=hermi,
                                       max_memory=max_memory)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    omega, alpha, hyb = ks._numint.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)
    if abs(hyb) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm, hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm, hermi)
        vxc += vj
    else:
        #        if (ks._eri is None and ks.direct_scf and
        #            getattr(vhf_last, 'vk', None) is not None):
        #            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
        #            vj, vk = ks.get_jk(mol, ddm, hermi)
        #            vj += vhf_last.vj
        #            vk += vhf_last.vk
        #        else:
        #            vj, vk = ks.get_jk(mol, dm, hermi)
        #        vxc += vj - vk * hyb
        #
        #        if ground_state:
        #            exc -= numpy.einsum('ij,ji', dm, vk) * hyb * .5
        raise NotImplementedError

    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm, vj) * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc
Beispiel #53
0
def general(mydf, mo_coeffs, kpts=None, compact=True):
    if mydf._cderi is None:
        mydf.build()

    kptijkl = _format_kpts(kpts)
    kpti, kptj, kptk, kptl = kptijkl
    if isinstance(mo_coeffs, numpy.ndarray) and mo_coeffs.ndim == 2:
        mo_coeffs = (mo_coeffs,) * 4
    all_real = not any(numpy.iscomplexobj(mo) for mo in mo_coeffs)
    max_memory = max(2000, (mydf.max_memory - lib.current_memory()[0]) * .5)

####################
# gamma point, the integral is real and with s4 symmetry
    if gamma_point(kptijkl) and all_real:
        ijmosym, nij_pair, moij, ijslice = _conc_mos(mo_coeffs[0], mo_coeffs[1], compact)
        klmosym, nkl_pair, mokl, klslice = _conc_mos(mo_coeffs[2], mo_coeffs[3], compact)
        eri_mo = numpy.zeros((nij_pair,nkl_pair))
        sym = (iden_coeffs(mo_coeffs[0], mo_coeffs[2]) and
               iden_coeffs(mo_coeffs[1], mo_coeffs[3]))
        ijR = klR = None
        for LpqR, LpqI in mydf.sr_loop(kptijkl[:2], max_memory, True):
            ijR, klR = _dtrans(LpqR, ijR, ijmosym, moij, ijslice,
                               LpqR, klR, klmosym, mokl, klslice, sym)
            lib.ddot(ijR.T, klR, 1, eri_mo, 1)
            LpqR = LpqI = None
        return eri_mo

    elif is_zero(kpti-kptk) and is_zero(kptj-kptl):
        mo_coeffs = _mo_as_complex(mo_coeffs)
        nij_pair, moij, ijslice = _conc_mos(mo_coeffs[0], mo_coeffs[1])[1:]
        nkl_pair, mokl, klslice = _conc_mos(mo_coeffs[2], mo_coeffs[3])[1:]
        eri_mo = numpy.zeros((nij_pair,nkl_pair), dtype=numpy.complex)
        sym = (iden_coeffs(mo_coeffs[0], mo_coeffs[2]) and
               iden_coeffs(mo_coeffs[1], mo_coeffs[3]))

        zij = zkl = None
        for LpqR, LpqI in mydf.sr_loop(kptijkl[:2], max_memory, False):
            buf = LpqR+LpqI*1j
            zij, zkl = _ztrans(buf, zij, moij, ijslice,
                               buf, zkl, mokl, klslice, sym)
            lib.dot(zij.T, zkl, 1, eri_mo, 1)
            LpqR = LpqI = buf = None
        return eri_mo

####################
# (kpt) i == j == k == l != 0
# (kpt) i == l && j == k && i != j && j != k  =>
#
    elif is_zero(kpti-kptl) and is_zero(kptj-kptk):
        mo_coeffs = _mo_as_complex(mo_coeffs)
        nij_pair, moij, ijslice = _conc_mos(mo_coeffs[0], mo_coeffs[1])[1:]
        nlk_pair, molk, lkslice = _conc_mos(mo_coeffs[3], mo_coeffs[2])[1:]
        eri_mo = numpy.zeros((nij_pair,nlk_pair), dtype=numpy.complex)
        sym = (iden_coeffs(mo_coeffs[0], mo_coeffs[3]) and
               iden_coeffs(mo_coeffs[1], mo_coeffs[2]))

        zij = zlk = None
        for LpqR, LpqI in mydf.sr_loop(kptijkl[:2], max_memory, False):
            buf = LpqR+LpqI*1j
            zij, zlk = _ztrans(buf, zij, moij, ijslice,
                               buf, zlk, molk, lkslice, sym)
            lib.dot(zij.T, zlk.conj(), 1, eri_mo, 1)
            LpqR = LpqI = buf = None
        nmok = mo_coeffs[2].shape[1]
        nmol = mo_coeffs[3].shape[1]
        eri_mo = lib.transpose(eri_mo.reshape(-1,nmol,nmok), axes=(0,2,1))
        return eri_mo.reshape(nij_pair,nlk_pair)

####################
# aosym = s1, complex integrals
#
# If kpti == kptj, (kptl-kptk)*a has to be multiples of 2pi because of the wave
# vector symmetry.  k is a fraction of reciprocal basis, 0 < k/b < 1, by definition.
# So  kptl/b - kptk/b  must be -1 < k/b < 1.  =>  kptl == kptk
#
    else:
        mo_coeffs = _mo_as_complex(mo_coeffs)
        nij_pair, moij, ijslice = _conc_mos(mo_coeffs[0], mo_coeffs[1])[1:]
        nkl_pair, mokl, klslice = _conc_mos(mo_coeffs[2], mo_coeffs[3])[1:]
        eri_mo = numpy.zeros((nij_pair,nkl_pair), dtype=numpy.complex)

        zij = zkl = None
        for (LpqR, LpqI), (LrsR, LrsI) in \
                lib.izip(mydf.sr_loop(kptijkl[:2], max_memory, False),
                         mydf.sr_loop(kptijkl[2:], max_memory, False)):
            zij, zkl = _ztrans(LpqR+LpqI*1j, zij, moij, ijslice,
                               LrsR+LrsI*1j, zkl, mokl, klslice, False)
            lib.dot(zij.T, zkl, 1, eri_mo, 1)
            LpqR = LpqI = LrsR = LrsI = None
        return eri_mo
Beispiel #54
0
    def dump_input(self):

        if self.verbose < logger.INFO:
            return self

        logger.info(self, '')
        logger.info(self, '******** %s flags ********', self.__class__)
        logger.info(self, '* General Info')
        logger.info(self, 'Date %s' % time.ctime())
        logger.info(self, 'Python %s' % sys.version)
        logger.info(self, 'Numpy %s' % numpy.__version__)
        logger.info(self, 'Number of threads %d' % self.nthreads)
        logger.info(self, 'Verbose level %d' % self.verbose)
        logger.info(self, 'Scratch dir %s' % self.scratch)
        logger.info(self, 'Input data file %s' % self.chkfile)
        logger.info(self, 'Max_memory %d MB (current use %d MB)',
                    self.max_memory,
                    lib.current_memory()[0])

        logger.info(self, '* Mol Info')
        logger.info(self, 'Speed light value %f' % self.cspeed)
        logger.info(self, 'Num atoms %d' % self.natm)
        logger.info(self, 'Num electrons %d' % self.nelectron)
        logger.info(self, 'Total charge %d' % self.charge)
        logger.info(self, 'Spin %d ' % self.spin)
        logger.info(self, 'Atom Coordinates (Bohr)')
        for i in range(self.natm):
            logger.info(
                self, 'Nuclei %d with charge %d position : %.6f  %.6f  %.6f',
                i, self.charges[i], *self.coords[i])

        logger.info(self, '* Basis Info')
        logger.info(self, 'Is cartesian %s' % self.cart)
        logger.info(self, 'Number of molecular orbitals %d' % self.nmo)
        logger.info(self, 'Orbital EPS occ criterion %e' % self.occdrop)
        logger.info(self,
                    'Number of occupied molecular orbitals %d' % self.nocc)
        logger.info(self, 'Number of molecular primitives %d' % self.nprims)
        logger.debug(self, 'Occs : %s' % self.mo_occ)

        logger.info(self, '* Surface Info')
        if (self.leb):
            logger.info(self, 'Lebedev quadrature')
        else:
            logger.info(self, 'Theta quadrature %s' % self.iqudt)
            logger.info(self, 'Phi is always trapezoidal')
            logger.info(
                self, 'N(theta,phi) points %d %d' % (self.nptheta, self.npphi))
        logger.info(self, 'Npang points %d' % self.npang)
        logger.info(self, 'Surface file %s' % self.surfile)
        logger.info(self, 'Surface for nuc %d' % self.inuc)
        logger.info(self, 'Rmaxsurface %f' % self.rmaxsurf)
        logger.info(self, 'Ntrial %d' % self.ntrial)
        logger.info(self, 'Rprimer %f' % self.rprimer)
        logger.debug(self, 'Rpru : %s' % self.rpru)
        logger.info(self, 'Epsiscp %f' % self.epsiscp)
        logger.info(self, 'Epsroot %e' % self.epsroot)
        logger.info(self, 'ODE solver %s' % self.backend)
        logger.info(self, 'ODE tool %e' % self.epsilon)
        logger.info(self, 'Max steps in ODE solver %d' % self.mstep)
        logger.info(self, '')

        return self
Beispiel #55
0
def gen_tda_hop(mf, fock_ao=None, wfnsym=None, max_memory=2000):
    '''(A+B)x
    
    Kwargs:
        wfnsym : int
            Point group symmetry for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbida = (orbsyma[viridxa].reshape(-1, 1)
                       ^ orbsyma[occidxa]) != wfnsym
        sym_forbidb = (orbsymb[viridxb].reshape(-1, 1)
                       ^ orbsymb[occidxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ai_a = mo_energy[0][viridxa].reshape(-1, 1) - mo_energy[0][occidxa]
    e_ai_b = mo_energy[1][viridxb].reshape(-1, 1) - mo_energy[1][occidxb]
    e_ai = hdiag = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F')
    mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F')

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, max_memory * .8 - mem_now)
    vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory)

    def vind(zs):
        nz = len(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs)
            zs[:, sym_forbid] = 0
        dmvo = numpy.empty((2, nz, nao, nao))
        for i, z in enumerate(zs):
            za = z[:nocca * nvira].reshape(nvira, nocca)
            zb = z[nocca * nvira:].reshape(nvirb, noccb)
            dmvo[0, i] = reduce(numpy.dot, (orbva, za, orboa.T))
            dmvo[1, i] = reduce(numpy.dot, (orbvb, zb, orbob.T))

        v1ao = vresp(dmvo)
        v1a = _ao2mo.nr_e2(v1ao[0], mo_a,
                           (nocca, nmo, 0, nocca)).reshape(-1, nvira, nocca)
        v1b = _ao2mo.nr_e2(v1ao[1], mo_b,
                           (noccb, nmo, 0, noccb)).reshape(-1, nvirb, noccb)
        for i, z in enumerate(zs):
            za = z[:nocca * nvira].reshape(nvira, nocca)
            zb = z[nocca * nvira:].reshape(nvirb, noccb)
            v1a[i] += numpy.einsum('ai,ai->ai', e_ai_a, za)
            v1b[i] += numpy.einsum('ai,ai->ai', e_ai_b, zb)
        hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
        if wfnsym is not None and mol.symmetry:
            hx[:, sym_forbid] = 0
        return hx

    return vind, hdiag
Beispiel #56
0
def _gamma2_outcore(mycc, t1, t2, l1, l2, h5fobj, compress_vvvv=False):
    log = logger.Logger(mycc.stdout, mycc.verbose)
    nocc, nvir = t1.shape
    nvir_pair = nvir * (nvir + 1) // 2
    dtype = numpy.result_type(t1, t2, l1, l2).char
    if compress_vvvv:
        dvvvv = h5fobj.create_dataset('dvvvv', (nvir_pair, nvir_pair), dtype)
    else:
        dvvvv = h5fobj.create_dataset('dvvvv', (nvir, nvir, nvir, nvir), dtype)
    dovvo = h5fobj.create_dataset('dovvo', (nocc, nvir, nvir, nocc),
                                  dtype,
                                  chunks=(nocc, 1, nvir, nocc))
    fswap = lib.H5TmpFile()

    time1 = logger.process_clock(), logger.perf_counter()
    pvOOv = lib.einsum('ikca,jkcb->aijb', l2, t2)
    moo = numpy.einsum('dljd->jl', pvOOv) * 2
    mvv = numpy.einsum('blld->db', pvOOv) * 2
    gooov = lib.einsum('kc,cija->jkia', t1, pvOOv)
    fswap['mvOOv'] = pvOOv
    pvOOv = None

    pvoOV = -lib.einsum('ikca,jkbc->aijb', l2, t2)
    theta = t2 * 2 - t2.transpose(0, 1, 3, 2)
    pvoOV += lib.einsum('ikac,jkbc->aijb', l2, theta)
    moo += numpy.einsum('dljd->jl', pvoOV)
    mvv += numpy.einsum('blld->db', pvoOV)
    gooov -= lib.einsum('jc,cika->jkia', t1, pvoOV)
    fswap['mvoOV'] = pvoOV
    pvoOV = None

    mia = (numpy.einsum('kc,ikac->ia', l1, t2) * 2 -
           numpy.einsum('kc,ikca->ia', l1, t2))
    mab = numpy.einsum('kc,kb->cb', l1, t1)
    mij = numpy.einsum('kc,jc->jk', l1, t1) + moo * .5

    tau = numpy.einsum('ia,jb->ijab', t1, t1)
    tau += t2
    goooo = lib.einsum('ijab,klab->ijkl', tau, l2) * .5
    h5fobj['doooo'] = (goooo.transpose(0, 2, 1, 3) * 2 -
                       goooo.transpose(0, 3, 1, 2)).conj()

    gooov += numpy.einsum('ji,ka->jkia', -.5 * moo, t1)
    gooov += lib.einsum('la,jkil->jkia', 2 * t1, goooo)
    gooov -= lib.einsum('ib,jkba->jkia', l1, tau)
    gooov = gooov.conj()
    gooov -= lib.einsum('jkba,ib->jkia', l2, t1)
    h5fobj['dooov'] = gooov.transpose(0, 2, 1, 3) * 2 - gooov.transpose(
        1, 2, 0, 3)
    tau = None
    time1 = log.timer_debug1('rdm intermediates pass1', *time1)

    goovv = numpy.einsum('ia,jb->ijab', mia.conj(), t1.conj())
    max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
    unit = nocc**2 * nvir * 6
    blksize = min(nocc, nvir,
                  max(ccsd.BLKMIN, int(max_memory * .95e6 / 8 / unit)))
    doovv = h5fobj.create_dataset('doovv', (nocc, nocc, nvir, nvir),
                                  dtype,
                                  chunks=(nocc, nocc, 1, nvir))

    log.debug1(
        'rdm intermediates pass 2: block size = %d, nvir = %d in %d blocks',
        blksize, nvir, int((nvir + blksize - 1) / blksize))
    for p0, p1 in lib.prange(0, nvir, blksize):
        tau = numpy.einsum('ia,jb->ijab', t1[:, p0:p1], t1)
        tau += t2[:, :, p0:p1]
        tmpoovv = lib.einsum('ijkl,klab->ijab', goooo, tau)
        tmpoovv -= lib.einsum('jk,ikab->ijab', mij, tau)
        tmpoovv -= lib.einsum('cb,ijac->ijab', mab, t2[:, :, p0:p1])
        tmpoovv -= lib.einsum('bd,ijad->ijab', mvv * .5, tau)
        tmpoovv += .5 * tau
        tmpoovv = tmpoovv.conj()
        tmpoovv += .5 * l2[:, :, p0:p1]
        goovv[:, :, p0:p1] += tmpoovv

        pvOOv = fswap['mvOOv'][p0:p1]
        pvoOV = fswap['mvoOV'][p0:p1]
        gOvvO = lib.einsum('kiac,jc,kb->iabj', l2[:, :, p0:p1], t1, t1)
        gOvvO += numpy.einsum('aijb->iabj', pvOOv)
        govVO = numpy.einsum('ia,jb->iabj', l1[:, p0:p1], t1)
        govVO -= lib.einsum('ikac,jc,kb->iabj', l2[:, :, p0:p1], t1, t1)
        govVO += numpy.einsum('aijb->iabj', pvoOV)
        dovvo[:, p0:p1] = 2 * govVO + gOvvO
        doovv[:, :, p0:p1] = (-2 * gOvvO - govVO).transpose(3, 0, 1, 2).conj()
        gOvvO = govVO = None

        tau -= t2[:, :, p0:p1] * .5
        for q0, q1 in lib.prange(0, nvir, blksize):
            goovv[:, :, q0:q1, :] += lib.einsum('dlib,jlda->ijab', pvOOv,
                                                tau[:, :, :, q0:q1]).conj()
            goovv[:, :, :, q0:q1] -= lib.einsum('dlia,jldb->ijab', pvoOV,
                                                tau[:, :, :, q0:q1]).conj()
            tmp = pvoOV[:, :, :, q0:q1] + pvOOv[:, :, :, q0:q1] * .5
            goovv[:, :, q0:q1, :] += lib.einsum('dlia,jlbd->ijab', tmp,
                                                t2[:, :, :, p0:p1]).conj()
        pvOOv = pvoOV = tau = None
        time1 = log.timer_debug1('rdm intermediates pass2 [%d:%d]' % (p0, p1),
                                 *time1)
    h5fobj['dovov'] = goovv.transpose(0, 2, 1, 3) * 2 - goovv.transpose(
        1, 2, 0, 3)
    goovv = goooo = None

    max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
    unit = max(nocc**2 * nvir * 2 + nocc * nvir**2 * 3,
               nvir**3 * 2 + nocc * nvir**2 * 2 + nocc**2 * nvir * 2)
    blksize = min(nvir, max(ccsd.BLKMIN, int(max_memory * .9e6 / 8 / unit)))
    log.debug1(
        'rdm intermediates pass 3: block size = %d, nvir = %d in %d blocks',
        blksize, nocc, int((nvir + blksize - 1) / blksize))
    dovvv = h5fobj.create_dataset('dovvv', (nocc, nvir, nvir, nvir),
                                  dtype,
                                  chunks=(nocc, min(nocc, nvir), 1, nvir))
    time1 = logger.process_clock(), logger.perf_counter()
    for istep, (p0, p1) in enumerate(lib.prange(0, nvir, blksize)):
        l2tmp = l2[:, :, p0:p1]
        gvvvv = lib.einsum('ijab,ijcd->abcd', l2tmp, t2)
        jabc = lib.einsum('ijab,ic->jabc', l2tmp, t1)
        gvvvv += lib.einsum('jabc,jd->abcd', jabc, t1)
        l2tmp = jabc = None

        if compress_vvvv:
            # symmetrize dvvvv because it does not affect the results of ccsd_grad
            # dvvvv = gvvvv.transpose(0,2,1,3)-gvvvv.transpose(0,3,1,2)*.5
            # 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):
                vvv = gvvvv[i].conj().transpose(1, 0, 2)
                tmp[:] = vvv - vvv.transpose(2, 1, 0) * .5
                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):
                vvv = gvvvv[i - p0].conj().transpose(1, 0, 2)
                dvvvv[i] = vvv - vvv.transpose(2, 1, 0) * .5

        gvovv = lib.einsum('adbc,id->aibc', gvvvv, -t1)
        gvvvv = None

        gvovv += lib.einsum('akic,kb->aibc', fswap['mvoOV'][p0:p1], t1)
        gvovv -= lib.einsum('akib,kc->aibc', fswap['mvOOv'][p0:p1], t1)

        gvovv += lib.einsum('ja,jibc->aibc', l1[:, p0:p1], t2)
        gvovv += lib.einsum('ja,jb,ic->aibc', l1[:, p0:p1], t1, t1)
        gvovv += numpy.einsum('ba,ic->aibc', mvv[:, p0:p1] * .5, t1)
        gvovv = gvovv.conj()
        gvovv += lib.einsum('ja,jibc->aibc', t1[:, p0:p1], l2)

        dovvv[:, :, p0:p1] = gvovv.transpose(1, 3, 0, 2) * 2 - gvovv.transpose(
            1, 2, 0, 3)
        gvovv = None
        time1 = log.timer_debug1('rdm intermediates pass3 [%d:%d]' % (p0, p1),
                                 *time1)

    fswap = None
    dvvov = None
    return (h5fobj['dovov'], h5fobj['dvvvv'], h5fobj['doooo'], h5fobj['doovv'],
            h5fobj['dovvo'], dvvov, h5fobj['dovvv'], h5fobj['dooov'])
Beispiel #57
0
    def get_vind(self, mf):
        '''
        [ A  B][X]
        [-B -A][Y]
        '''
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff[0].dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff[0].shape
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        orboa = mo_coeff[0][:, occidxa]
        orbob = mo_coeff[1][:, occidxb]
        orbva = mo_coeff[0][:, viridxa]
        orbvb = mo_coeff[1][:, viridxb]

        if wfnsym is not None and mol.symmetry:
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
            sym_forbida = (orbsyma[viridxa].reshape(-1, 1)
                           ^ orbsyma[occidxa]) != wfnsym
            sym_forbidb = (orbsymb[viridxb].reshape(-1, 1)
                           ^ orbsymb[occidxb]) != wfnsym
            sym_forbid = numpy.hstack(
                (sym_forbida.ravel(), sym_forbidb.ravel()))

        e_ai_a = mo_energy[0][viridxa].reshape(-1, 1) - mo_energy[0][occidxa]
        e_ai_b = mo_energy[1][viridxb].reshape(-1, 1) - mo_energy[1][occidxb]
        e_ai = hdiag = numpy.hstack((e_ai_a.reshape(-1), e_ai_b.reshape(-1)))
        if wfnsym is not None and mol.symmetry:
            hdiag[sym_forbid] = 0
        hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))
        mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F')
        mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F')

        mem_now = lib.current_memory()[0]
        max_memory = max(2000, self.max_memory * .8 - mem_now)
        vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory)

        def vind(xys):
            nz = len(xys)
            if wfnsym is not None and mol.symmetry:
                # shape(nz,2,-1): 2 ~ X,Y
                xys = numpy.copy(zs).reshape(nz, 2, -1)
                xys[:, :, :, sym_forbid] = 0
            dms = numpy.empty((2, nz, nao, nao))  # 2 ~ alpha,beta
            for i in range(nz):
                x, y = xys[i].reshape(2, -1)
                xa = x[:nocca * nvira].reshape(nvira, nocca)
                xb = x[nocca * nvira:].reshape(nvirb, noccb)
                ya = y[:nocca * nvira].reshape(nvira, nocca)
                yb = y[nocca * nvira:].reshape(nvirb, noccb)
                dmx = reduce(numpy.dot, (orbva, xa, orboa.T))
                dmy = reduce(numpy.dot, (orboa, ya.T, orbva.T))
                dms[0, i] = dmx + dmy  # AX + BY
                dmx = reduce(numpy.dot, (orbvb, xb, orbob.T))
                dmy = reduce(numpy.dot, (orbob, yb.T, orbvb.T))
                dms[1, i] = dmx + dmy  # AX + BY

            v1ao = vresp(dms)
            v1avo = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca))
            v1bvo = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb))
            v1aov = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo))
            v1bov = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo))
            hx = numpy.empty((nz, 2, nvira * nocca + nvirb * noccb),
                             dtype=v1avo.dtype)
            for i in range(nz):
                x, y = xys[i].reshape(2, -1)
                hx[i, 0, :nvira * nocca] = v1avo[i].ravel()
                hx[i, 0, nvira * nocca:] = v1bvo[i].ravel()
                hx[i, 0] += e_ai * x  # AX
                hx[i, 1, :nvira *
                   nocca] = -v1aov[i].reshape(nocca, nvira).T.ravel()
                hx[i, 1,
                   nvira * nocca:] = -v1bov[i].reshape(noccb, nvirb).T.ravel()
                hx[i, 1] -= e_ai * y  #-AY

            if wfnsym is not None and mol.symmetry:
                hx[:, :, sym_forbid] = 0
            return hx.reshape(nz, -1)

        return vind, hdiag
Beispiel #58
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional for GKS.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    t0 = (time.clock(), time.time())

    ground_state = (isinstance(dm, numpy.ndarray) and dm.ndim == 2)

    assert (hermi == 1)
    dm = numpy.asarray(dm)
    nso = dm.shape[-1]
    nao = nso // 2
    dm_a = dm[..., :nao, :nao].real
    dm_b = dm[..., nao:, nao:].real

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            ks.grids = rks.prune_small_rho_grids_(ks, mol, dm_a + dm_b,
                                                  ks.grids)
        t0 = logger.timer(ks, 'setting up grids', *t0)
    if ks.nlc != '':
        if ks.nlcgrids.coords is None:
            ks.nlcgrids.build(with_non0tab=True)
            if ks.small_rho_cutoff > 1e-20 and ground_state:
                ks.nlcgrids = rks.prune_small_rho_grids_(
                    ks, mol, dm_a + dm_b, ks.nlcgrids)
            t0 = logger.timer(ks, 'setting up nlc grids', *t0)

    max_memory = ks.max_memory - lib.current_memory()[0]
    ni = ks._numint
    n, exc, vxc = ni.nr_uks(mol,
                            ks.grids,
                            ks.xc, (dm_a, dm_b),
                            max_memory=max_memory)
    if ks.nlc != '':
        assert ('VV10' in ks.nlc.upper())
        _, enlc, vnlc = ni.nr_rks(mol,
                                  ks.nlcgrids,
                                  ks.xc + '__' + ks.nlc,
                                  dm_a + dm_b,
                                  max_memory=max_memory)
        exc += enlc
        vxc += vnlc
    logger.debug(ks, 'nelec by numeric integration = %s', n)
    t0 = logger.timer(ks, 'vxc', *t0)
    if vxc.ndim == 4:
        raise NotImplementedError
    vxc = numpy.asarray(scipy.linalg.block_diag(*vxc), dtype=dm.dtype)

    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm, hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm, hermi)
        vxc += vj
    else:
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vk', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = ks.get_k(mol, ddm, hermi, omega=omega)
                vklr *= (alpha - hyb)
                vk += vklr
            vj += vhf_last.vj
            vk += vhf_last.vk
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = ks.get_k(mol, dm, hermi, omega=omega)
                vklr *= (alpha - hyb)
                vk += vklr
        vxc += vj - vk

        if ground_state:
            exc -= numpy.einsum('ij,ji', dm, vk).real * .5
    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm, vj).real * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc
Beispiel #59
0
def get_k_kpts_occ(mydf,
                   dm_kpts,
                   hermi=1,
                   kpts=np.zeros((1, 3)),
                   kpts_band=None,
                   exxdiv=None):
    '''Get the Coulomb (J) and exchange (K) AO matrices at sampled k-points.

    Args:
        dm_kpts : (nkpts, nao, nao) ndarray
            Density matrix at each k-point
        kpts : (nkpts, 3) ndarray

    Kwargs:
        hermi : int
            Whether K matrix is hermitian

            | 0 : not hermitian and not symmetric
            | 1 : hermitian

        kpts_band : (3,) ndarray or (*,3) ndarray
            A list of arbitrary "band" k-points at which to evalute the matrix.

    Returns:
        vj : (nkpts, nao, nao) ndarray
        vk : (nkpts, nao, nao) ndarray
        or list of vj and vk if the input dm_kpts is a list of DMs
    '''
    Jtime = time.time()

    cell = mydf.cell
    mesh = mydf.mesh
    coords = cell.gen_uniform_grids(mesh)
    ngrids = coords.shape[0]

    if getattr(dm_kpts, 'mo_coeff', None) is not None:
        mo_coeff = dm_kpts.mo_coeff
        mo_occ = dm_kpts.mo_occ
    else:
        mo_coeff = None

    kpts = np.asarray(kpts)
    dm_kpts = lib.asarray(dm_kpts, order='C')
    dms = _format_dms(dm_kpts, kpts)
    nset, nkpts, nao = dms.shape[:3]

    weight = 1. / nkpts * (cell.vol / ngrids)

    kpts_band, input_band = _format_kpts_band(kpts_band, kpts), kpts_band
    nband = len(kpts_band)

    if gamma_point(kpts_band) and gamma_point(kpts):
        vk_kpts = np.zeros((nset, nband, nao, nao), dtype=dms.dtype)
    else:
        vk_kpts = np.zeros((nset, nband, nao, nao), dtype=np.complex128)

    coords = mydf.grids.coords
    ao2_kpts = [
        np.asarray(ao.T, order='C')
        for ao in mydf._numint.eval_ao(cell, coords, kpts=kpts)
    ]
    if input_band is None:
        ao1_kpts = ao2_kpts
    else:
        ao1_kpts = [
            np.asarray(ao.T, order='C')
            for ao in mydf._numint.eval_ao(cell, coords, kpts=kpts_band)
        ]

########################
    if mo_coeff is None:
        return _format_jks(vk_kpts, dm_kpts, input_band, kpts)
    elif nset > 1:
        mem_now = lib.current_memory()[0]
        max_memory = mydf.max_memory - mem_now
        blksize = int(
            min(nao,
                max(1, (max_memory - mem_now) * 1e6 / 16 / 4 / ngrids / nao)))
        lib.logger.debug1(mydf, 'fft_jk: get_k_kpts max_memory %s  blksize %d',
                          max_memory, blksize)
        ao1_dtype = np.result_type(*ao1_kpts)
        ao2_dtype = np.result_type(*ao2_kpts)
        vR_dm = np.empty((nset, nao, ngrids), dtype=vk_kpts.dtype)

        t1 = (time.clock(), time.time())
        for k2, ao2T in enumerate(ao2_kpts):
            if ao2T.size == 0:
                continue

            kpt2 = kpts[k2]
            naoj = ao2T.shape[0]

            if mo_coeff is None or nset > 1:
                ao_dms = [
                    lib.dot(dms[i, k2], ao2T.conj()) for i in range(nset)
                ]
            else:
                ao_dms = [ao2T.conj()]

            for k1, ao1T in enumerate(ao1_kpts):
                kpt1 = kpts_band[k1]
                # If we have an ewald exxdiv, we add the G=0 correction near the
                # end of the function to bypass any discretization errors
                # that arise from the FFT.
                mydf.exxdiv = exxdiv
                if exxdiv == 'ewald' or exxdiv is None:
                    coulG = tools.get_coulG(cell, kpt2 - kpt1, False, mydf,
                                            mesh)
                else:
                    coulG = tools.get_coulG(cell, kpt2 - kpt1, True, mydf,
                                            mesh)
                if is_zero(kpt1 - kpt2):
                    expmikr = np.array(1.)
                else:
                    expmikr = np.exp(-1j * np.dot(coords, kpt2 - kpt1))

                for p0, p1 in lib.prange(0, nao, blksize):
                    rho1 = np.einsum('ig,jg->ijg',
                                     ao1T[p0:p1].conj() * expmikr, ao2T)
                    vG = tools.fft(rho1.reshape(-1, ngrids), mesh)
                    rho1 = None
                    vG *= coulG
                    vR = tools.ifft(vG, mesh).reshape(p1 - p0, naoj, ngrids)
                    vG = None
                    if vR_dm.dtype == np.double:
                        vR = vR.real
                    for i in range(nset):
                        np.einsum('ijg,jg->ig',
                                  vR,
                                  ao_dms[i],
                                  out=vR_dm[i, p0:p1])
                    vR = None
                vR_dm *= expmikr.conj()

                for i in range(nset):
                    vk_kpts[i, k1] += weight * lib.dot(vR_dm[i], ao1T.T)

            t1 = lib.logger.timer_debug1(mydf,
                                         'get_k_kpts: make_kpt (%d,*)' % k2,
                                         *t1)

    # Function _ewald_exxdiv_for_G0 to add back in the G=0 component to vk_kpts
    # Note in the _ewald_exxdiv_for_G0 implementation, the G=0 treatments are
    # different for 1D/2D and 3D systems.  The special treatments for 1D and 2D
    # can only be used with AFTDF/GDF/MDF method.  In the FFTDF method, 1D, 2D
    # and 3D should use the ewald probe charge correction.
        if exxdiv == 'ewald':
            _ewald_exxdiv_for_G0(cell, kpts, dms, vk_kpts, kpts_band=kpts_band)

        return _format_jks(vk_kpts, dm_kpts, input_band, kpts)
################

    if mo_coeff is not None and nset == 1:
        # occ
        mo_coeff0 = [mo_coeff[k][:, occ > 0] for k, occ in enumerate(mo_occ)]
        mo_coeff = [
            mo_coeff[k][:, occ > 0] * np.sqrt(occ[occ > 0])
            for k, occ in enumerate(mo_occ)
        ]
        ao2_kpts = [np.dot(mo_coeff[k].T, ao) for k, ao in enumerate(ao2_kpts)]
    # occ
    if gamma_point(kpts_band) and gamma_point(kpts):
        kiv = np.zeros((nset, nband, mo_coeff0[0].shape[1], nao),
                       dtype=dms.dtype)
    else:
        kiv = [[] * nset]
        for i in range(nset):
            for k1 in range(nband):
                kiv[i].append(
                    np.zeros((mo_coeff0[k1].shape[1], nao),
                             dtype=np.complex128))

    mem_now = lib.current_memory()[0]
    max_memory = mydf.max_memory - mem_now
    blksize = int(
        min(nao, max(1, (max_memory - mem_now) * 1e6 / 16 / 4 / ngrids / nao)))
    lib.logger.debug1(mydf, 'fft_jk: get_k_kpts max_memory %s  blksize %d',
                      max_memory, blksize)
    ao1_dtype = np.result_type(*ao1_kpts)
    ao2_dtype = np.result_type(*ao2_kpts)
    vR_dm = np.empty((nset, nao, ngrids), dtype=vk_kpts.dtype)

    t1 = (time.clock(), time.time())
    for k2, ao2T in enumerate(ao2_kpts):
        if ao2T.size == 0:
            continue

        kpt2 = kpts[k2]
        naoj = ao2T.shape[0]

        if mo_coeff is None or nset > 1:
            ao_dms = [lib.dot(dms[i, k2], ao2T.conj()) for i in range(nset)]
        else:
            ao_dms = [ao2T.conj()]
        for k1, ao1T in enumerate(ao1_kpts):
            kpt1 = kpts_band[k1]
            # occ
            ao3T = np.dot(mo_coeff0[k1].T, ao1T)
            # If we have an ewald exxdiv, we add the G=0 correction near the
            # end of the function to bypass any discretization errors
            # that arise from the FFT.
            mydf.exxdiv = exxdiv
            if exxdiv == 'ewald' or exxdiv is None:
                coulG = tools.get_coulG(cell, kpt2 - kpt1, False, mydf, mesh)
            else:
                coulG = tools.get_coulG(cell, kpt2 - kpt1, True, mydf, mesh)
            if is_zero(kpt1 - kpt2):
                expmikr = np.array(1.)
            else:
                expmikr = np.exp(-1j * np.dot(coords, kpt2 - kpt1))

            m3T = ao3T.shape[0]
            for p0, p1 in lib.prange(0, m3T, blksize):
                rho1 = np.einsum('ig,jg->ijg', ao3T[p0:p1].conj() * expmikr,
                                 ao2T)
                vG = tools.fft(rho1.reshape(-1, ngrids), mesh)
                rho1 = None
                vG *= coulG
                vR = tools.ifft(vG, mesh).reshape(p1 - p0, naoj, ngrids)
                vG = None
                if vR_dm.dtype == np.double:
                    vR = vR.real
                for i in range(nset):
                    np.einsum('ijg,jg->ig', vR, ao_dms[i], out=vR_dm[i, p0:p1])
                vR = None
            vR_dm *= expmikr.conj()
            for i in range(nset):
                # occ
                kiv[i][k1] += weight * lib.dot(
                    vR_dm[i, 0:mo_coeff[k1].shape[1]], ao1T.T)

        t1 = lib.logger.timer_debug1(mydf, 'get_k_kpts: make_kpt (%d,*)' % k2,
                                     *t1)
    for i in range(nset):
        for k1, ao1T in enumerate(ao1_kpts):
            kij = lib.einsum('ui,ju->ij', mo_coeff0[k1], kiv[i][k1])
            kr = scipy.linalg.solve(kij.conj(), kiv[i][k1])
            vk_kpts[i, k1] = lib.dot(kiv[i][k1].T.conj(), kr)

    # Function _ewald_exxdiv_for_G0 to add back in the G=0 component to vk_kpts
    # Note in the _ewald_exxdiv_for_G0 implementation, the G=0 treatments are
    # different for 1D/2D and 3D systems.  The special treatments for 1D and 2D
    # can only be used with AFTDF/GDF/MDF method.  In the FFTDF method, 1D, 2D
    # and 3D should use the ewald probe charge correction.
    if exxdiv == 'ewald':
        _ewald_exxdiv_for_G0(cell, kpts, dms, vk_kpts, kpts_band=kpts_band)

    print "Took this long for occ-X: ", time.time() - Jtime

    return _format_jks(vk_kpts, dm_kpts, input_band, kpts)
Beispiel #60
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 = 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)