def init_amps(self, eris): time0 = time.clock(), time.time() nocc = self.nocc() nvir = self.nmo() - nocc nkpts = self.nkpts t1 = numpy.zeros((nkpts,nocc,nvir), dtype=numpy.complex128) t2 = numpy.zeros((nkpts,nkpts,nkpts,nocc,nocc,nvir,nvir), dtype=numpy.complex128) self.emp2 = 0 foo = eris.fock[:,:nocc,:nocc].copy() fvv = eris.fock[:,nocc:,nocc:].copy() eris_oovv = eris.oovv.copy() eia = numpy.zeros((nocc,nvir)) eijab = numpy.zeros((nocc,nocc,nvir,nvir)) kconserv = tools.get_kconserv(self._scf.cell,self.kpts) for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): kb = kconserv[ki,ka,kj] for i in range(nocc): for a in range(nvir): eia[i,a] = foo[ki,i,i] - fvv[ka,a,a] for j in range(nocc): for b in range(nvir): eijab[i,j,a,b] = ( foo[ki,i,i] + foo[kj,j,j] - fvv[ka,a,a] - fvv[kb,b,b] ) t2[ki,kj,ka,i,j,a,b] = eris_oovv[ki,kj,ka,i,j,a,b]/eijab[i,j,a,b] t2 = numpy.conj(t2) self.emp2 = 0.25*numpy.einsum('pqrijab,pqrijab',t2,eris_oovv).real self.emp2 /= nkpts logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real) logger.timer(self, 'init mp2', *time0) print "MP2 energy =", self.emp2 return self.emp2, t1, t2
def __init__(self, mf, frozen=0, mo_coeff=None, mo_occ=None): if mo_coeff is None: mo_coeff = mf.mo_coeff if mo_occ is None: mo_occ = mf.mo_occ self.mol = mf.mol self._scf = mf self.verbose = self.mol.verbose self.stdout = self.mol.stdout self.max_memory = mf.max_memory self.frozen = frozen ################################################## # don't modify the following attributes, they are not input options self.kpts = mf.kpts self.mo_energy = mf.mo_energy self.nkpts = len(self.kpts) self.kconserv = tools.get_kconserv(mf.cell, mf.kpts) self.mo_energy = mf.mo_energy self.mo_coeff = mo_coeff self.mo_occ = mo_occ self._nocc = None self._nmo = None self.emp2 = None self.e_corr = None self.t2 = None self._keys = set(self.__dict__.keys())
def cc_Wovvo(cc,t1,t2,eris): nkpts, nocc, nvir = t1.shape kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) eris_ovvo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nocc,nvir,nvir,nocc),dtype=t2.dtype) eris_oovo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nocc,nocc,nvir,nocc),dtype=t2.dtype) for km in range(nkpts): for kb in range(nkpts): for ke in range(nkpts): kj = kconserv[km,ke,kb] # <mb||je> -> -<mb||ej> eris_ovvo[km,kb,ke] = -eris.ovov[km,kb,kj].transpose(0,1,3,2) # <mn||je> -> -<mn||ej> # let kb = kn as a dummy variable eris_oovo[km,kb,ke] = -eris.ooov[km,kb,kj].transpose(0,1,3,2) Wmbej = eris_ovvo.copy() for km in range(nkpts): for kb in range(nkpts): for ke in range(nkpts): kj = kconserv[km,ke,kb] Wmbej[km,kb,ke] += einsum('jf,mbef->mbej',t1[kj,:,:],eris.ovvv[km,kb,ke]) Wmbej[km,kb,ke] += -einsum('nb,mnej->mbej',t1[kb,:,:],eris_oovo[km,kb,ke]) for kn in range(nkpts): kf = kconserv[km,ke,kn] Wmbej[km,kb,ke] += -0.5*einsum('jnfb,mnef->mbej',t2[kj,kn,kf], eris.oovv[km,kn,ke]) if kn == kb and kf == kj: Wmbej[km,kb,ke] += -einsum('jf,nb,mnef->mbej',t1[kj],t1[kn], eris.oovv[km,kn,ke]) return Wmbej
def __init__(self, mf, frozen=[], mo_energy=None, mo_coeff=None, mo_occ=None): pyscf.cc.ccsd.CCSD.__init__(self, mf, frozen, mo_energy, mo_coeff, mo_occ) self.kpts = mf.kpts self.nkpts = len(self.kpts) self.kconserv = tools.get_kconserv(mf.cell, mf.kpts) self.khelper = kpoint_helper.unique_pqr_list(mf.cell, mf.kpts) self.made_ee_imds = False self.made_ip_imds = False self.made_ea_imds = False
def __init__(self, mf, frozen=0, mo_coeff=None, mo_occ=None): assert (isinstance(mf, scf.khf.KSCF)) pyscf.cc.ccsd.CCSD.__init__(self, mf, frozen, mo_coeff, mo_occ) self.max_space = 20 self._keys = self._keys.union(['max_space']) self.kpts = mf.kpts self.mo_energy = mf.mo_energy self.nkpts = len(self.kpts) self.kconserv = tools.get_kconserv(mf.cell, mf.kpts) self.khelper = kpoint_helper.unique_pqr_list(mf.cell, mf.kpts) self.made_ee_imds = False self.made_ip_imds = False self.made_ea_imds = False self.diis = None
def __init__(self, kmf, frozen=0, mo_coeff=None, mo_occ=None): if frozen != 0: raise NotImplementedError self._scf = kmf self.kpts = kmf.kpts self.nkpts = len(kmf.kpts) self.kconserv = tools.get_kconserv(kmf.cell, kmf.kpts) self.diis = None self.khelper = kpts_helper.KptsHelper(kmf.cell, kmf.kpts) self.verbose = kmf.verbose if mo_coeff is None: mo_coeff = kmf.mo_coeff if mo_occ is None: mo_occ = kmf.mo_occ self.mo_coeff = mo_coeff self.mo_occ = mo_occ self.mo_energy = kmf.mo_energy self.max_cycle = kmf.max_cycle self.conv_tol = kmf.conv_tol
def check_antisymm_34(cc, kpts, integrals): kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) nkpts = len(kpts) diff = 0.0 for kp in range(nkpts): for kq in range(nkpts): for kr in range(nkpts): ks = kconserv[kp, kr, kq] for p in range(integrals.shape[3]): for q in range(integrals.shape[4]): for r in range(integrals.shape[5]): for s in range(integrals.shape[6]): pqrs = integrals[kp, kq, kr, p, q, r, s] pqsr = integrals[kp, kq, ks, p, q, s, r] cdiff = numpy.linalg.norm(pqrs + pqsr).real print "AS diff = %.15g" % cdiff, pqrs, pqsr, kp, kq, kr, ks, p, q, r, s diff = max(diff, cdiff) print "antisymmetrization : max diff = %.15g" % diff
def check_antisymm_34( cc, kpts, integrals ): kconserv = tools.get_kconserv(cc._scf.cell,cc.kpts) nkpts = len(kpts) diff = 0.0 for kp in range(nkpts): for kq in range(nkpts): for kr in range(nkpts): ks = kconserv[kp,kr,kq] for p in range(integrals.shape[3]): for q in range(integrals.shape[4]): for r in range(integrals.shape[5]): for s in range(integrals.shape[6]): pqrs = integrals[kp,kq,kr,p,q,r,s] pqsr = integrals[kp,kq,ks,p,q,s,r] cdiff = numpy.linalg.norm(pqrs+pqsr).real print "AS diff = %.15g" % cdiff, pqrs, pqsr, kp, kq, kr, ks, p, q, r, s diff = max(diff,cdiff) print "antisymmetrization : max diff = %.15g" % diff
def get_TEI(self, ao2eo): '''Get embedding TEI without density fitting''' kconserv = pbctools.get_kconserv(self.cell, self.kpts) Nkpts, nao, neo = ao2eo.shape TEI = 0.0 for i in range(Nkpts): for j in range(Nkpts): for k in range(Nkpts): l = kconserv[i, j, k] ki, COi = self.kpts[i], ao2eo[i] kj, COj = self.kpts[j], ao2eo[j] kk, C*k = self.kpts[k], ao2eo[k] kl, COl = self.kpts[l], ao2eo[l] TEI += self.kmf.with_df.ao2mo([COi, COj, C*k, COl], [ki, kj, kk, kl], compact=False) return TEI.reshape(neo, neo, neo, neo).real / Nkpts
def make_tau(cc, t2, t1a, t1b, fac=1., out=None): nkpts, nocc, nvir = t1a.shape tau1 = t2.copy() kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) for ki in range(nkpts): for ka in range(nkpts): for kj in range(nkpts): kb = kconserv[ki,ka,kj] tmp = numpy.zeros((nocc,nocc,nvir,nvir),dtype=t2.dtype) if ki == ka and kj == kb: tmp += einsum('ia,jb->ijab',t1a[ki],t1b[kj]) if ki == kb and kj == ka: tmp -= einsum('ib,ja->ijab',t1a[ki],t1b[kj]) if kj == ka and ki == kb: tmp -= einsum('ja,ib->ijab',t1a[kj],t1b[ki]) if kj == kb and ki == ka: tmp += einsum('jb,ia->ijab',t1a[kj],t1b[ki]) tau1[ki,kj,ka] += fac*0.5*tmp return tau1
def cc_Woooo(cc,t1,t2,eris): nkpts, nocc, nvir = t1.shape tau = make_tau(cc,t2,t1,t1) Wmnij = eris.oooo.copy() kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) for km in range(nkpts): for kn in range(nkpts): # Since it's not enough just to switch i and j and need to create the k_i and k_j # so that P(ij) switches both i,j and k_i,k_j # t1[ k_j, j, e ] * v[ k_m, k_n, k_i, m, n, i, e ] -> tmp[ k_i, k_j, m, n, i, j ] # Here, x = k_j and y = k_i tmp = einsum('xje,ymnie->yxmnij',t1,eris.ooov[km,kn]) tmp = tmp - tmp.transpose(1,0,2,3,5,4) for ki in range(nkpts): kj = kconserv[km,ki,kn] Wmnij[km,kn,ki] += tmp[ki,kj] # Here, x = k_e Wmnij[km,kn,ki] += 0.25*einsum('xijef,xmnef->mnij', tau[ki,kj],eris.oovv[km,kn]) return Wmnij
def cc_Wvvvv(cc,t1,t2,eris): nkpts, nocc, nvir = t1.shape eris_vovv = - eris.ovvv.transpose(1,0,2,4,3,5,6) tau = make_tau(cc,t2,t1,t1) Wabef = eris.vvvv.copy() kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) for ka in range(nkpts): for kb in range(nkpts): for ke in range(nkpts): km = kb tmp = einsum('mb,amef->abef',t1[kb],eris_vovv[ka,km,ke]) km = ka tmp -= einsum('ma,bmef->abef',t1[ka],eris_vovv[kb,km,ke]) Wabef[ka,kb,ke] += -tmp # km + kn - ka = kb # => kn = ka - km + kb for km in range(nkpts): kn = kconserv[ka,km,kb] Wabef[ka,kb,ke] += 0.25*einsum('mnab,mnef->abef',tau[km,kn,ka], eris.oovv[km,kn,ke]) return Wabef
def get_loc_TEI(self, ao2lo=None): '''Get local TEI in R-space without density fitting''' kconserv = pbctools.get_kconserv(self.cell, self.kpts) if ao2lo is None: ao2lo = self.ao2lo Nkpts, nao, nlo = ao2lo.shape size = Nkpts * nlo mo_phase = lib.einsum('kui,Rk->kuRi', ao2lo, self.phase.conj()).reshape(Nkpts, nao, size) TEI = 0.0 for i in range(Nkpts): for j in range(Nkpts): for k in range(Nkpts): l = kconserv[i, j, k] ki, COi = self.kpts[i], mo_phase[i] kj, COj = self.kpts[j], mo_phase[j] kk, C*k = self.kpts[k], mo_phase[k] kl, COl = self.kpts[l], mo_phase[l] TEI += self.kmf.with_df.ao2mo([COi, COj, C*k, COl], [ki, kj, kk, kl], compact=False) self.is_real(TEI) return TEI.reshape(size, size, size, size).real / Nkpts
def update_amps(cc, t1, t2, eris, max_memory=2000): time0 = time.clock(), time.time() log = logger.Logger(cc.stdout, cc.verbose) nkpts, nocc, nvir = t1.shape fock = eris.fock fov = fock[:, :nocc, nocc:].copy() foo = fock[:, :nocc, :nocc].copy() fvv = fock[:, nocc:, nocc:].copy() #mo_e = eris.fock.diagonal() #eia = mo_e[:nocc,None] - mo_e[None,nocc:] #eijab = lib.direct_sum('ia,jb->ijab',eia,eia) tau = imdk.make_tau(cc, t2, t1, t1) Fvv = imdk.cc_Fvv(cc, t1, t2, eris) Foo = imdk.cc_Foo(cc, t1, t2, eris) Fov = imdk.cc_Fov(cc, t1, t2, eris) Woooo = imdk.cc_Woooo(cc, t1, t2, eris) Wvvvv = imdk.cc_Wvvvv(cc, t1, t2, eris) Wovvo = imdk.cc_Wovvo(cc, t1, t2, eris) # Move energy terms to the other side for k in range(nkpts): Fvv[k] -= numpy.diag(numpy.diag(fvv[k])) Foo[k] -= numpy.diag(numpy.diag(foo[k])) # Get the momentum conservation array # Note: chemist's notation for momentum conserving t2(ki,kj,ka,kb), even though # integrals are in physics notation kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) eris_ovvo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nocc, nvir, nvir, nocc), dtype=t2.dtype) eris_oovo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nocc, nocc, nvir, nocc), dtype=t2.dtype) eris_vvvo = numpy.zeros(shape=(nkpts, nkpts, nkpts, nvir, nvir, nvir, nocc), dtype=t2.dtype) for km in range(nkpts): for kb in range(nkpts): for ke in range(nkpts): kj = kconserv[km, ke, kb] # <mb||je> -> -<mb||ej> eris_ovvo[km, kb, ke] = -eris.ovov[km, kb, kj].transpose(0, 1, 3, 2) # <mn||je> -> -<mn||ej> # let kb = kn as a dummy variable eris_oovo[km, kb, ke] = -eris.ooov[km, kb, kj].transpose(0, 1, 3, 2) # <ma||be> -> - <be||am>* # let kj = ka as a dummy variable kj = kconserv[km, ke, kb] eris_vvvo[ke, kj, kb] = -eris.ovvv[km, kb, ke].transpose( 2, 3, 1, 0).conj() # T1 equation t1new = numpy.zeros(shape=t1.shape, dtype=t1.dtype) for ka in range(nkpts): ki = ka t1new[ka] += numpy.array(fov[ka, :, :]).conj() t1new[ka] += einsum('ie,ae->ia', t1[ka], Fvv[ka]) t1new[ka] += -einsum('ma,mi->ia', t1[ka], Foo[ka]) for km in range(nkpts): t1new[ka] += einsum('imae,me->ia', t2[ka, km, ka], Fov[km]) t1new[ka] += -einsum('nf,naif->ia', t1[km], eris.ovov[km, ka, ki]) for kn in range(nkpts): ke = kconserv[km, ki, kn] t1new[ka] += -0.5 * einsum('imef,maef->ia', t2[ki, km, ke], eris.ovvv[km, ka, ke]) t1new[ka] += -0.5 * einsum('mnae,nmei->ia', t2[km, kn, ka], eris_oovo[kn, km, ke]) # T2 equation t2new = numpy.array(eris.oovv).conj() for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): # Chemist's notation for momentum conserving t2(ki,kj,ka,kb) kb = kconserv[ki, ka, kj] Ftmp = Fvv[kb] - 0.5 * einsum('mb,me->be', t1[kb], Fov[kb]) tmp = einsum('ijae,be->ijab', t2[ki, kj, ka], Ftmp) t2new[ki, kj, ka] += tmp #t2new[ki,kj,kb] -= tmp.transpose(0,1,3,2) Ftmp = Fvv[ka] - 0.5 * einsum('ma,me->ae', t1[ka], Fov[ka]) tmp = einsum('ijbe,ae->ijab', t2[ki, kj, kb], Ftmp) t2new[ki, kj, ka] -= tmp Ftmp = Foo[kj] + 0.5 * einsum('je,me->mj', t1[kj], Fov[kj]) tmp = einsum('imab,mj->ijab', t2[ki, kj, ka], Ftmp) t2new[ki, kj, ka] -= tmp #t2new[kj,ki,ka] += tmp.transpose(1,0,2,3) Ftmp = Foo[ki] + 0.5 * einsum('ie,me->mi', t1[ki], Fov[ki]) tmp = einsum('jmab,mi->ijab', t2[kj, ki, ka], Ftmp) t2new[ki, kj, ka] += tmp for km in range(nkpts): # Wminj # - km - kn + ka + kb = 0 # => kn = ka - km + kb kn = kconserv[ka, km, kb] t2new[ki, kj, ka] += 0.5 * einsum( 'mnab,mnij->ijab', tau[km, kn, ka], Woooo[km, kn, ki]) ke = km t2new[ki, kj, ka] += 0.5 * einsum( 'ijef,abef->ijab', tau[ki, kj, ke], Wvvvv[ka, kb, ke]) # Wmbej # - km - kb + ke + kj = 0 # => ke = km - kj + kb ke = kconserv[km, kj, kb] tmp = einsum('imae,mbej->ijab', t2[ki, km, ka], Wovvo[km, kb, ke]) # - km - kb + ke + kj = 0 # => ke = km - kj + kb # # t[i,e] => ki = ke # t[m,a] => km = ka if km == ka and ke == ki: tmp -= einsum('ie,ma,mbej->ijab', t1[ki], t1[km], eris_ovvo[km, kb, ke]) t2new[ki, kj, ka] += tmp t2new[ki, kj, kb] -= tmp.transpose(0, 1, 3, 2) t2new[kj, ki, ka] -= tmp.transpose(1, 0, 2, 3) t2new[kj, ki, kb] += tmp.transpose(1, 0, 3, 2) ke = ki tmp = einsum('ie,abej->ijab', t1[ki], eris_vvvo[ka, kb, ke]) t2new[ki, kj, ka] += tmp # P(ij) term ke = kj tmp = einsum('je,abei->ijab', t1[kj], eris_vvvo[ka, kb, ke]) t2new[ki, kj, ka] -= tmp km = ka tmp = einsum('ma,mbij->ijab', t1[ka], eris.ovoo[km, kb, ki]) t2new[ki, kj, ka] -= tmp # P(ab) term km = kb tmp = einsum('mb,maij->ijab', t1[kb], eris.ovoo[km, ka, ki]) t2new[ki, kj, ka] += tmp eia = numpy.zeros(shape=t1new.shape, dtype=t1new.dtype) for ki in range(nkpts): for i in range(nocc): for a in range(nvir): eia[ki, i, a] = foo[ki, i, i] - fvv[ki, a, a] t1new[ki] /= eia[ki] eijab = numpy.zeros(shape=t2new.shape, dtype=t2new.dtype) kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): kb = kconserv[ki, ka, kj] for i in range(nocc): for a in range(nvir): for j in range(nocc): for b in range(nvir): eijab[ki, kj, ka, i, j, a, b] = (foo[ki, i, i] + foo[kj, j, j] - fvv[ka, a, a] - fvv[kb, b, b]) t2new[ki, kj, ka] /= eijab[ki, kj, ka] time0 = log.timer_debug1('update t1 t2', *time0) return t1new, t2new
def __init__(self, cell, kpts): kconserv = tools.get_kconserv(cell, kpts) nkpts = len(kpts) temp = range(0, nkpts) klist = pyscf.lib.cartesian_prod((temp, temp, temp)) completed = numpy.zeros((nkpts, nkpts, nkpts), dtype=int) self.operations = numpy.zeros((nkpts, nkpts, nkpts), dtype=int) self.equivalentList = numpy.zeros((nkpts, nkpts, nkpts, 3), dtype=int) self.nUnique = 0 self.uniqueList = numpy.array([]) ivec = 0 not_done = True while (not_done): current_kvec = klist[ivec] # check to see if it's been done... kp = current_kvec[0] kq = current_kvec[1] kr = current_kvec[2] #print "computing ",kp,kq,kr if completed[kp, kq, kr] == 0: self.nUnique += 1 self.uniqueList = numpy.append(self.uniqueList, current_kvec) ks = kconserv[kp, kq, kr] # Now find all equivalent kvectors by permuting it all possible ways... # and then storing how its related by symmetry completed[kp, kq, kr] = 1 self.operations[kp, kq, kr] = 0 self.equivalentList[kp, kq, kr] = current_kvec.copy() completed[kr, ks, kp] = 1 self.operations[kr, ks, kp] = 1 #.transpose(2,3,0,1) self.equivalentList[kr, ks, kp] = current_kvec.copy() completed[kq, kp, ks] = 1 self.operations[kq, kp, ks] = 2 #numpy.conj(.transpose(1,0,3,2)) self.equivalentList[kq, kp, ks] = current_kvec.copy() completed[ks, kr, kq] = 1 self.operations[ks, kr, kq] = 3 #numpy.conj(.transpose(3,2,1,0)) self.equivalentList[ks, kr, kq] = current_kvec.copy() ivec += 1 if ivec == len(klist): not_done = False self.uniqueList = self.uniqueList.reshape(self.nUnique, -1) if DEBUG == 1: print "::: kpoint helper :::" print "kvector list (in)" print " shape = ", klist.shape print "kvector list (out)" print " shape = ", self.uniqueList.shape print " unique list =" print self.uniqueList print "transformation =" for i in range(klist.shape[0]): pqr = klist[i] irr_pqr = self.equivalentList[pqr[0], pqr[1], pqr[2]] print "%3d %3d %3d -> %3d %3d %3d" % ( pqr[0], pqr[1], pqr[2], irr_pqr[0], irr_pqr[1], irr_pqr[2])
def update_amps(cc, t1, t2, eris, max_memory=2000): time0 = time.clock(), time.time() log = logger.Logger(cc.stdout, cc.verbose) nkpts, nocc, nvir = t1.shape #nov = nocc*nvir fock = eris.fock #t1new = numpy.zeros_like(t1) #t2new = numpy.zeros_like(t2) fov = fock[:,:nocc,nocc:].copy() foo = fock[:,:nocc,:nocc].copy() fvv = fock[:,nocc:,nocc:].copy() #mo_e = eris.fock.diagonal() #eia = mo_e[:nocc,None] - mo_e[None,nocc:] #eijab = lib.direct_sum('ia,jb->ijab',eia,eia) tau = imdk.make_tau(cc,t2,t1,t1) ### From eom-cc hackathon code ### Fvv = imdk.cc_Fvv(cc,t1,t2,eris) Foo = imdk.cc_Foo(cc,t1,t2,eris) Fov = imdk.cc_Fov(cc,t1,t2,eris) Woooo = imdk.cc_Woooo(cc,t1,t2,eris) Wvvvv = imdk.cc_Wvvvv(cc,t1,t2,eris) Wovvo = imdk.cc_Wovvo(cc,t1,t2,eris) # Move energy terms to the other side Fvv -= fvv Foo -= foo # Get the momentum conservation array # Note: chemist's notation for momentum conserving t2(ki,kj,ka,kb), even though # integrals are in physics notation kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) eris_ovvo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nocc,nvir,nvir,nocc), dtype=t2.dtype) eris_oovo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nocc,nocc,nvir,nocc), dtype=t2.dtype) eris_vvvo = numpy.zeros(shape=(nkpts,nkpts,nkpts,nvir,nvir,nvir,nocc), dtype=t2.dtype) for km in range(nkpts): for kb in range(nkpts): for ke in range(nkpts): kj = kconserv[km,ke,kb] # <mb||je> -> -<mb||ej> eris_ovvo[km,kb,ke] = -eris.ovov[km,kb,kj].transpose(0,1,3,2) # <mn||je> -> -<mn||ej> # let kb = kn as a dummy variable eris_oovo[km,kb,ke] = -eris.ooov[km,kb,kj].transpose(0,1,3,2) # <ma||be> -> - <be||am>* # let kj = ka as a dummy variable kj = kconserv[km,ke,kb] eris_vvvo[ke,kj,kb] = -eris.ovvv[km,kb,ke].transpose(2,3,1,0).conj() # T1 equation t1new = numpy.zeros(shape=t1.shape, dtype=t1.dtype) for ka in range(nkpts): ki = ka # TODO: Does this fov need a conj()? Usually zero w/ canonical HF. t1new[ka] += fov[ka,:,:] t1new[ka] += einsum('ie,ae->ia',t1[ka],Fvv[ka]) t1new[ka] += -einsum('ma,mi->ia',t1[ka],Foo[ka]) for km in range(nkpts): t1new[ka] += einsum('imae,me->ia',t2[ka,km,ka],Fov[km]) t1new[ka] += -einsum('nf,naif->ia',t1[km],eris.ovov[km,ka,ki]) for kn in range(nkpts): ke = kconserv[km,ki,kn] t1new[ka] += -0.5*einsum('imef,maef->ia',t2[ki,km,ke],eris.ovvv[km,ka,ke]) t1new[ka] += -0.5*einsum('mnae,nmei->ia',t2[km,kn,ka],eris_oovo[kn,km,ke]) # T2 equation # For conj(), see Hirata and Bartlett, Eq. (36) t2new = eris.oovv.copy().conj() for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): # Chemist's notation for momentum conserving t2(ki,kj,ka,kb) kb = kconserv[ki,ka,kj] Ftmp = Fvv[kb] - 0.5*einsum('mb,me->be',t1[kb],Fov[kb]) tmp = einsum('ijae,be->ijab',t2[ki,kj,ka],Ftmp) t2new[ki,kj,ka] += tmp Ftmp = Fvv[ka] - 0.5*einsum('ma,me->ae',t1[ka],Fov[ka]) tmp = einsum('ijbe,ae->ijab',t2[ki,kj,kb],Ftmp) t2new[ki,kj,ka] -= tmp #t2new[ki,kj,kb] -= tmp.transpose(0,1,3,2) Ftmp = Foo[kj] + 0.5*einsum('je,me->mj',t1[kj],Fov[kj]) tmp = einsum('imab,mj->ijab',t2[ki,kj,ka],Ftmp) t2new[ki,kj,ka] -= tmp Ftmp = Foo[ki] + 0.5*einsum('ie,me->mi',t1[ki],Fov[ki]) tmp = einsum('jmab,mi->ijab',t2[kj,ki,ka],Ftmp) t2new[ki,kj,ka] += tmp #t2new[kj,ki,ka] += tmp.transpose(1,0,2,3) for km in range(nkpts): # Wminj # - km - kn + ka + kb = 0 # => kn = ka - km + kb kn = kconserv[ka,km,kb] t2new[ki,kj,ka] += 0.5*einsum('mnab,mnij->ijab',tau[km,kn,ka],Woooo[km,kn,ki]) ke = km t2new[ki,kj,ka] += 0.5*einsum('ijef,abef->ijab',tau[ki,kj,ke],Wvvvv[ka,kb,ke]) # Wmbej # - km - kb + ke + kj = 0 # => ke = km - kj + kb ke = kconserv[km,kj,kb] tmp = einsum('imae,mbej->ijab',t2[ki,km,ka],Wovvo[km,kb,ke]) # - km - kb + ke + kj = 0 # => ke = km - kj + kb # # t[i,e] => ki = ke # t[m,a] => km = ka if km == ka and ke == ki: tmp -= einsum('ie,ma,mbej->ijab',t1[ki],t1[km],eris_ovvo[km,kb,ke]) t2new[ki,kj,ka] += tmp t2new[ki,kj,kb] -= tmp.transpose(0,1,3,2) t2new[kj,ki,ka] -= tmp.transpose(1,0,2,3) t2new[kj,ki,kb] += tmp.transpose(1,0,3,2) ke = ki tmp = einsum('ie,abej->ijab',t1[ki],eris_vvvo[ka,kb,ke]) t2new[ki,kj,ka] += tmp # P(ij) term ke = kj tmp = einsum('je,abei->ijab',t1[kj],eris_vvvo[ka,kb,ke]) t2new[ki,kj,ka] -= tmp km = ka tmp = einsum('ma,mbij->ijab',t1[ka],eris.ovoo[km,kb,ki]) t2new[ki,kj,ka] -= tmp # P(ab) term km = kb tmp = einsum('mb,maij->ijab',t1[kb],eris.ovoo[km,ka,ki]) t2new[ki,kj,ka] += tmp eia = numpy.zeros(shape=t1new.shape, dtype=t1new.dtype) for ki in range(nkpts): for i in range(nocc): for a in range(nvir): eia[ki,i,a] = foo[ki,i,i] - fvv[ki,a,a] t1new[ki] /= eia[ki] eijab = numpy.zeros(shape=t2new.shape, dtype=t2new.dtype) kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): kb = kconserv[ki,ka,kj] for i in range(nocc): for a in range(nvir): for j in range(nocc): for b in range(nvir): eijab[ki,kj,ka,i,j,a,b] = ( foo[ki,i,i] + foo[kj,j,j] - fvv[ka,a,a] - fvv[kb,b,b] ) t2new[ki,kj,ka] /= eijab[ki,kj,ka] time0 = log.timer_debug1('update t1 t2', *time0) return t1new, t2new
def __init__(self, cc, mo_coeff=None, method='incore'): cput0 = (time.clock(), time.time()) moidx = numpy.ones(shape=cc.mo_energy.shape, dtype=numpy.bool) nkpts = cc.nkpts nmo = cc.nmo() # TODO change this for k-points ... seems like it should work if isinstance(cc.frozen, (int, numpy.integer)): for k in range(nkpts): moidx[k, :cc.frozen] = False elif len(cc.frozen) > 0: for k in range(nkpts): moidx[k, numpy.asarray(cc.frozen)] = False assert (numpy.count_nonzero(moidx) % 2 == 0 ) # works for restricted CCSD only if mo_coeff is None: # TODO make this work for frozen maybe... seems like it should work nao = cc._scf.cell.nao_nr() self.mo_coeff = numpy.zeros((nkpts, nao * 2, nmo), dtype=numpy.complex128) for k in range(nkpts): self.mo_coeff[k] = cc.mo_coeff[k][:, moidx[k]] mo_coeff = self.mo_coeff self.fock = numpy.zeros((nkpts, nmo, nmo)) for k in range(nkpts): self.fock[k] = numpy.diag(cc.mo_energy[k][moidx[k]]) else: # If mo_coeff is not canonical orbital # TODO does this work for k-points? changed to conjugate. 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, (numpy.conj(mo_coeff.T), fockao, mo_coeff)) nocc = cc.nocc() nmo = cc.nmo() nvir = nmo - nocc mem_incore, mem_outcore, mem_basic = pyscf.cc.ccsd._mem_usage( nocc, nvir) mem_now = lib.current_memory()[0] # Convert to spin-orbitals and anti-symmetrize nao = cc._scf.cell.nao_nr() so_coeff = numpy.zeros((nkpts, nao, nmo), dtype=numpy.complex128) so_coeff[:, :, ::2] = so_coeff[:, :, 1::2] = mo_coeff[:, :nao, ::2] log = logger.Logger(cc.stdout, cc.verbose) if (method == 'incore' and cc._scf._eri is None and (mem_incore + mem_now < cc.max_memory) or cc.mol.incore_anyway): kconserv = tools.get_kconserv(cc._scf.cell, cc.kpts) eri = numpy.zeros((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo), dtype=numpy.complex128) fao2mo = cc._scf.with_df.ao2mo for kp in range(nkpts): for kq in range(nkpts): for kr in range(nkpts): ks = kconserv[kp, kq, kr] eri_kpt = fao2mo((so_coeff[kp], so_coeff[kq], so_coeff[kr], so_coeff[ks]), (cc.kpts[kp], cc.kpts[kq], cc.kpts[kr], cc.kpts[ks]), compact=False) eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) eri[kp, kq, kr] = eri_kpt.copy() eri[:, :, :, ::2, 1::2] = eri[:, :, :, 1::2, ::2] = eri[:, :, :, :, :, ::2, 1::2] = eri[:, :, :, :, :, 1::2, ::2] = 0. # Checking some things... maxdiff = 0.0 for kp in range(nkpts): for kq in range(nkpts): for kr in range(nkpts): ks = kconserv[kp, kq, kr] for p in range(nmo): for q in range(nmo): for r in range(nmo): for s in range(nmo): pqrs = eri[kp, kq, kr, p, q, r, s] rspq = eri[kr, ks, kp, r, s, p, q] diff = numpy.linalg.norm(pqrs - rspq).real if diff > 1e-5: print "** Warning: ERI diff at ", print "kp,kq,kr,ks,p,q,r,s =", kp, kq, kr, ks, p, q, r, s maxdiff = max(maxdiff, diff) print "Max difference in (pq|rs) - (rs|pq) = %.15g" % maxdiff #print "ERI =" #print eri # Antisymmetrizing (pq|rs)-(ps|rq), where the latter integral is equal to # (rq|ps); done since we aren't tracking the kpoint of orbital 's' eri1 = eri - eri.transpose(2, 1, 0, 5, 4, 3, 6) # Chemist -> physics notation eri1 = eri1.transpose(0, 2, 1, 3, 5, 4, 6) self.dtype = eri1.dtype self.oooo = eri1[:, :, :, :nocc, :nocc, :nocc, :nocc].copy( ) / nkpts self.ooov = eri1[:, :, :, :nocc, :nocc, :nocc, nocc:].copy() / nkpts self.ovoo = eri1[:, :, :, :nocc, nocc:, :nocc, :nocc].copy() / nkpts self.oovv = eri1[:, :, :, :nocc, :nocc, nocc:, nocc:].copy() / nkpts self.ovov = eri1[:, :, :, :nocc, nocc:, :nocc, nocc:].copy() / nkpts self.ovvv = eri1[:, :, :, :nocc, nocc:, nocc:, nocc:].copy() / nkpts self.vvvv = eri1[:, :, :, nocc:, nocc:, nocc:, nocc:].copy() / nkpts #ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy() #self.ovvv = numpy.empty((nocc,nvir,nvir*(nvir+1)//2)) #for i in range(nocc): # for j in range(nvir): # self.ovvv[i,j] = lib.pack_tril(ovvv[i,j]) #self.vvvv = pyscf.ao2mo.restore(4, eri1[nocc:,nocc:,nocc:,nocc:], nvir) log.timer('CCSD integral transformation', *cput0)
def __init__(self, cc, mo_coeff=None, method='incore'): cput0 = (time.clock(), time.time()) moidx = numpy.ones(shape=cc.mo_energy.shape, dtype=numpy.bool) nkpts = cc.nkpts nmo = cc.nmo() # TODO change this for k-points ... seems like it should work if isinstance(cc.frozen, (int, numpy.integer)): for k in range(nkpts): moidx[k,:cc.frozen] = False elif len(cc.frozen) > 0: for k in range(nkpts): moidx[k,numpy.asarray(cc.frozen)] = False if mo_coeff is None: # TODO make this work for frozen maybe... seems like it should work self.mo_coeff = numpy.zeros((nkpts,nmo,nmo),dtype=numpy.complex128) for k in range(nkpts): self.mo_coeff[k] = cc.mo_coeff[k][:,moidx[k]] mo_coeff = self.mo_coeff self.fock = numpy.zeros((nkpts,nmo,nmo)) for k in range(nkpts): self.fock[k] = numpy.diag(cc.mo_energy[k][moidx[k]]) else: # If mo_coeff is not canonical orbital # TODO does this work for k-points? changed to conjugate. 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, (numpy.conj(mo_coeff.T), fockao, mo_coeff)) nocc = cc.nocc() nmo = cc.nmo() nvir = nmo - nocc mem_incore, mem_outcore, mem_basic = pyscf.cc.ccsd._mem_usage(nocc, nvir) mem_now = lib.current_memory()[0] # Convert to spin-orbitals and anti-symmetrize so_coeff = numpy.zeros((nkpts,nmo/2,nmo),dtype=numpy.complex128) so_coeff[:,:,::2] = so_coeff[:,:,1::2] = mo_coeff[:,:nmo/2,::2] log = logger.Logger(cc.stdout, cc.verbose) if (method == 'incore' and cc._scf._eri is None and (mem_incore+mem_now < cc.max_memory) or cc.mol.incore_anyway): kconserv = tools.get_kconserv(cc._scf.cell,cc.kpts) eri = numpy.zeros((nkpts,nkpts,nkpts,nmo,nmo,nmo,nmo), dtype=numpy.complex128) for kp in range(nkpts): for kq in range(nkpts): for kr in range(nkpts): ks = kconserv[kp,kq,kr] eri_kpt = pyscf.pbc.ao2mo.general(cc._scf.cell, (so_coeff[kp,:,:],so_coeff[kq,:,:],so_coeff[kr,:,:],so_coeff[ks,:,:]), (cc.kpts[kp],cc.kpts[kq],cc.kpts[kr],cc.kpts[ks])) eri_kpt = eri_kpt.reshape(nmo,nmo,nmo,nmo) eri[kp,kq,kr] = eri_kpt.copy() eri[:,:,:,::2,1::2] = eri[:,:,:,1::2,::2] = eri[:,:,:,:,:,::2,1::2] = eri[:,:,:,:,:,1::2,::2] = 0. # Checking some things... maxdiff = 0.0 for kp in range(nkpts): for kq in range(nkpts): for kr in range(nkpts): ks = kconserv[kp,kq,kr] for p in range(nmo): for q in range(nmo): for r in range(nmo): for s in range(nmo): pqrs = eri[kp,kq,kr,p,q,r,s] rspq = eri[kr,ks,kp,r,s,p,q] diff = numpy.linalg.norm(pqrs - rspq).real if diff > 1e-5: print "** Warning: ERI diff at ", print "kp,kq,kr,ks,p,q,r,s =", kp, kq, kr, ks, p, q, r, s maxdiff = max(maxdiff,diff) print "Max difference in (pq|rs) - (rs|pq) = %.15g" % maxdiff #print "ERI =" #print eri # Antisymmetrizing (pq|rs)-(ps|rq), where the latter integral is equal to # (rq|ps); done since we aren't tracking the kpoint of orbital 's' eri1 = eri - eri.transpose(2,1,0,5,4,3,6) # Chemist -> physics notation eri1 = eri1.transpose(0,2,1,3,5,4,6) self.dtype = eri1.dtype self.oooo = eri1[:,:,:,:nocc,:nocc,:nocc,:nocc].copy() / nkpts self.ooov = eri1[:,:,:,:nocc,:nocc,:nocc,nocc:].copy() / nkpts self.ovoo = eri1[:,:,:,:nocc,nocc:,:nocc,:nocc].copy() / nkpts self.oovv = eri1[:,:,:,:nocc,:nocc,nocc:,nocc:].copy() / nkpts self.ovov = eri1[:,:,:,:nocc,nocc:,:nocc,nocc:].copy() / nkpts self.ovvv = eri1[:,:,:,:nocc,nocc:,nocc:,nocc:].copy() / nkpts self.vvvv = eri1[:,:,:,nocc:,nocc:,nocc:,nocc:].copy() / nkpts #ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy() #self.ovvv = numpy.empty((nocc,nvir,nvir*(nvir+1)//2)) #for i in range(nocc): # for j in range(nvir): # self.ovvv[i,j] = lib.pack_tril(ovvv[i,j]) #self.vvvv = pyscf.ao2mo.restore(4, eri1[nocc:,nocc:,nocc:,nocc:], nvir) log.timer('CCSD integral transformation', *cput0)