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])
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
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
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)
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)
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
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
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
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])
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
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)
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
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)
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
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
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
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)
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
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
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))
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
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
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
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
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
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
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
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)
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)
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
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
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
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
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
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)
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
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
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
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
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
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)
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)
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
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
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
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
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
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
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
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
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'])
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
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
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
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
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'])
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
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
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)
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)