def kernel(cc, eris, t1=None, t2=None, max_cycle=50, tol=1e-8, tolnormt=1e-6, max_memory=2000, verbose=logger.INFO): """Exactly the same as pyscf.cc.ccsd.kernel, which calls a *local* energy() function.""" if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(cc.stdout, verbose) if t1 is None and t2 is None: t1, t2 = cc.init_amps(eris)[1:] elif t1 is None: nocc = cc.get_nocc() nvir = cc.get_nmo() - nocc nkpts = cc.nkpts t1 = numpy.zeros((nkpts, nocc, nvir), numpy.complex128) elif t2 is None: t2 = cc.init_amps(eris)[2] cput1 = cput0 = (time.clock(), time.time()) nkpts, nocc, nvir = t1.shape eold = 0 eccsd = 0 if cc.diis: adiis = lib.diis.DIIS(cc, cc.diis_file) adiis.space = cc.diis_space else: adiis = lambda t1, t2, *args: (t1, t2) conv = False for istep in range(max_cycle): t1new, t2new = cc.update_amps(t1, t2, eris, max_memory) normt = numpy.linalg.norm(t1new - t1) + numpy.linalg.norm(t2new - t2) t1, t2 = t1new, t2new t1new = t2new = None if cc.diis: t1, t2 = cc.diis(t1, t2, istep, normt, eccsd - eold, adiis) eold, eccsd = eccsd, energy(cc, t1, t2, eris) log.info('istep = %d E(CCSD) = %.15g dE = %.9g norm(t1,t2) = %.6g', istep, eccsd, eccsd - eold, normt) cput1 = log.timer('CCSD iter', *cput1) if abs(eccsd - eold) < tol and normt < tolnormt: conv = True break log.timer('CCSD', *cput0) return conv, eccsd, t1, t2
def __init__(self, cc, mo_coeff=None, method='incore'): cput0 = (time.clock(), time.time()) moidx = get_moidx(cc) nkpts = cc.nkpts nmo = cc.get_nmo() assert (sum(numpy.count_nonzero(x) for x in 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. raise NotImplementedError self.mo_coeff = mo_coeff = [ c[:, moidx[k]] for k, c in enumerate(mo_coeff) ] 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.get_nocc() nmo = cc.get_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 = kpts_helper.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 " "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)