def get_jk(mf, cell, dm, hermi=1, vhfopt=None, kpt=np.zeros(3), kpt_band=None): dm = np.asarray(dm) nao = dm.shape[-1] coords = gen_grid.gen_uniform_grids(cell) if kpt_band is None: kpt1 = kpt2 = kpt aoR_k1 = aoR_k2 = numint.eval_ao(cell, coords, kpt) else: kpt1 = kpt_band kpt2 = kpt aoR_k1 = numint.eval_ao(cell, coords, kpt1) aoR_k2 = numint.eval_ao(cell, coords, kpt2) vkR_k1k2 = get_vkR(mf, cell, aoR_k1, aoR_k2, kpt1, kpt2) ngs, nao = aoR_k1.shape def contract(dm): vjR_k2 = get_vjR(cell, dm, aoR_k2) vj = (cell.vol/ngs) * np.dot(aoR_k1.T.conj(), vjR_k2.reshape(-1,1)*aoR_k1) #:vk = (cell.vol/ngs) * np.einsum('rs,Rp,Rqs,Rr->pq', dm, aoR_k1.conj(), #: vkR_k1k2, aoR_k2) aoR_dm_k2 = np.dot(aoR_k2, dm) tmp_Rq = np.einsum('Rqs,Rs->Rq', vkR_k1k2, aoR_dm_k2) vk = (cell.vol/ngs) * np.dot(aoR_k1.T.conj(), tmp_Rq) return vj, vk if dm.ndim == 2: vj, vk = contract(dm) else: jk = [contract(x) for x in dm.reshape(-1,nao,nao)] vj = lib.asarray([x[0] for x in jk]) vk = lib.asarray([x[1] for x in jk]) return vj.reshape(dm.shape), vk.reshape(dm.shape)
def get_j_kpts(mf, cell, dm_kpts, kpts, kpt_band=None): coords = gen_grid.gen_uniform_grids(cell) nkpts = len(kpts) ngs = len(coords) dm_kpts = np.asarray(dm_kpts) nao = dm_kpts.shape[-1] ni = numint._KNumInt(kpts) aoR_kpts = ni.eval_ao(cell, coords, kpts) if kpt_band is not None: aoR_kband = numint.eval_ao(cell, coords, kpt_band) dms = dm_kpts.reshape(-1,nkpts,nao,nao) nset = dms.shape[0] vjR = [get_vjR(cell, dms[i], aoR_kpts) for i in range(nset)] if kpt_band is not None: vj_kpts = [cell.vol/ngs * lib.dot(aoR_kband.T.conj()*vjR[i], aoR_kband) for i in range(nset)] if dm_kpts.ndim == 3: # One set of dm_kpts for KRHF vj_kpts = vj_kpts[0] return lib.asarray(vj_kpts) else: vj_kpts = [] for i in range(nset): vj = [cell.vol/ngs * lib.dot(aoR_k.T.conj()*vjR[i], aoR_k) for aoR_k in aoR_kpts] vj_kpts.append(lib.asarray(vj)) return lib.asarray(vj_kpts).reshape(dm_kpts.shape)
def get_j(cell, dm, hermi=1, vhfopt=None, kpt=np.zeros(3), kpt_band=None): dm = np.asarray(dm) nao = dm.shape[-1] coords = gen_grid.gen_uniform_grids(cell) if kpt_band is None: kpt1 = kpt2 = kpt aoR_k1 = aoR_k2 = numint.eval_ao(cell, coords, kpt) else: kpt1 = kpt_band kpt2 = kpt aoR_k1 = numint.eval_ao(cell, coords, kpt1) aoR_k2 = numint.eval_ao(cell, coords, kpt2) ngs, nao = aoR_k1.shape def contract(dm): vjR_k2 = get_vjR(cell, dm, aoR_k2) vj = (cell.vol/ngs) * np.dot(aoR_k1.T.conj(), vjR_k2.reshape(-1,1)*aoR_k1) return vj if dm.ndim == 2: vj = contract(dm) else: vj = lib.asarray([contract(x) for x in dm.reshape(-1,nao,nao)]) return vj.reshape(dm.shape)
def get_jk_kpts(mf, cell, dm_kpts, kpts, kpt_band=None): coords = gen_grid.gen_uniform_grids(cell) nkpts = len(kpts) ngs = len(coords) dm_kpts = np.asarray(dm_kpts) nao = dm_kpts.shape[-1] dms = dm_kpts.reshape(-1,nkpts,nao,nao) nset = dms.shape[0] ni = numint._KNumInt(kpts) aoR_kpts = ni.eval_ao(cell, coords, kpts) if kpt_band is not None: aoR_kband = numint.eval_ao(cell, coords, kpt_band) # J vjR = [get_vjR_kpts(cell, dms[i], aoR_kpts) for i in range(nset)] if kpt_band is not None: vj_kpts = [cell.vol/ngs * lib.dot(aoR_kband.T.conj()*vjR[i], aoR_kband) for i in range(nset)] else: vj_kpts = [] for i in range(nset): vj = [cell.vol/ngs * lib.dot(aoR_k.T.conj()*vjR[i], aoR_k) for aoR_k in aoR_kpts] vj_kpts.append(lib.asarray(vj)) vj_kpts = lib.asarray(vj_kpts) vjR = None # K weight = 1./nkpts * (cell.vol/ngs) vk_kpts = np.zeros_like(vj_kpts) if kpt_band is not None: for k2, kpt2 in enumerate(kpts): aoR_dms = [lib.dot(aoR_kpts[k2], dms[i,k2]) for i in range(nset)] vkR_k1k2 = get_vkR(mf, cell, aoR_kband, aoR_kpts[k2], kpt_band, kpt2) #:vk_kpts = 1./nkpts * (cell.vol/ngs) * np.einsum('rs,Rp,Rqs,Rr->pq', #: dm_kpts[k2], aoR_kband.conj(), #: vkR_k1k2, aoR_kpts[k2]) for i in range(nset): tmp_Rq = np.einsum('Rqs,Rs->Rq', vkR_k1k2, aoR_dms[i]) vk_kpts[i] += weight * lib.dot(aoR_kband.T.conj(), tmp_Rq) vkR_k1k2 = None if dm_kpts.ndim == 3: vj_kpts = vj_kpts[0] vk_kpts = vk_kpts[0] return lib.asarray(vj_kpts), lib.asarray(vk_kpts) else: for k2, kpt2 in enumerate(kpts): aoR_dms = [lib.dot(aoR_kpts[k2], dms[i,k2]) for i in range(nset)] for k1, kpt1 in enumerate(kpts): vkR_k1k2 = get_vkR(mf, cell, aoR_kpts[k1], aoR_kpts[k2], kpt1, kpt2) for i in range(nset): tmp_Rq = np.einsum('Rqs,Rs->Rq', vkR_k1k2, aoR_dms[i]) vk_kpts[i,k1] += weight * lib.dot(aoR_kpts[k1].T.conj(), tmp_Rq) vkR_k1k2 = None return vj_kpts.reshape(dm_kpts.shape), vk_kpts.reshape(dm_kpts.shape)
def aoR_loop(self, cell, gs=None, kpts=None, kpt_band=None): if kpts is None: kpts = self.kpts kpts = numpy.asarray(kpts) if gs is None: gs = self.gs else: self.gs = gs ngrids = numpy.prod(numpy.asarray(gs)*2+1) if (self._numint.cell is None or id(cell) != id(self._numint.cell) or self._numint._deriv != 0 or self._numint._kpts.shape != kpts.shape or abs(self._numint._kpts - kpts).sum() > 1e-9 or self._numint._coords.shape[0] != ngrids or (gs is not None and numpy.any(gs != self.gs))): nkpts = len(kpts) coords = gen_grid.gen_uniform_grids(cell, gs) nao = cell.nao_nr() blksize = int(self.max_memory*1e6/(nkpts*nao*16*numint.BLKSIZE))*numint.BLKSIZE blksize = min(max(blksize, numint.BLKSIZE), ngrids) try: self._numint.cache_ao(cell, kpts, 0, coords, nao, blksize) except IOError as e: sys.stderr.write('HDF5 file cannot be opened twice in different mode.\n') raise e with h5py.File(self._numint._ao.name, 'r') as f: if kpt_band is None: for k in range(len(kpts)): aoR = f['ao/%d'%k].value yield k, aoR else: kpt_band = numpy.reshape(kpt_band, 3) where = numpy.argmin(pyscf.lib.norm(kpts-kpt_band,axis=1)) if abs(kpts[where]-kpt_band).sum() > 1e-9: where = None coords = gen_grid.gen_uniform_grids(cell, gs) yield 0, numint.eval_ao(cell, coords, kpt_band, deriv=deriv) else: yield where, f['ao/%d'%where].value
def get_mo_pairs_G_old(cell, mo_coeffs, kpts=None, q=None): '''Calculate forward (G|ij) and "inverse" (ij|G) FFT of all MO pairs. TODO: - Implement simplifications for real orbitals. Args: mo_coeff: length-2 list of (nao,nmo) ndarrays The two sets of MO coefficients to use in calculating the product |ij). Returns: mo_pairs_G, mo_pairs_invG : (ngs, nmoi*nmoj) ndarray The FFTs of the real-space MO pairs. ''' coords = gen_uniform_grids(cell) if kpts is None: q = np.zeros(3) aoR = eval_ao(cell, coords) ngs = aoR.shape[0] if np.array_equal(mo_coeffs[0], mo_coeffs[1]): nmoi = nmoj = mo_coeffs[0].shape[1] moiR = mojR = einsum('ri,ia->ra', aoR, mo_coeffs[0]) else: nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] moiR = einsum('ri,ia->ra', aoR, mo_coeffs[0]) mojR = einsum('ri,ia->ra', aoR, mo_coeffs[1]) else: if q is None: q = kpts[1]-kpts[0] aoR_ki = eval_ao(cell, coords, kpt=kpts[0]) aoR_kj = eval_ao(cell, coords, kpt=kpts[1]) ngs = aoR_ki.shape[0] nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] moiR = einsum('ri,ia->ra', aoR_ki, mo_coeffs[0]) mojR = einsum('ri,ia->ra', aoR_kj, mo_coeffs[1]) mo_pairs_R = np.einsum('ri,rj->rij', np.conj(moiR), mojR) mo_pairs_G = np.zeros([ngs,nmoi*nmoj], np.complex128) mo_pairs_invG = np.zeros([ngs,nmoi*nmoj], np.complex128) fac = np.exp(-1j*np.dot(coords, q)) for i in xrange(nmoi): for j in xrange(nmoj): mo_pairs_G[:,i*nmoj+j] = tools.fftk(mo_pairs_R[:,i,j], cell.gs, fac) mo_pairs_invG[:,i*nmoj+j] = np.conj(tools.fftk(np.conj(mo_pairs_R[:,i,j]), cell.gs, fac.conj())) return mo_pairs_G, mo_pairs_invG
def get_mo_pairs_G(cell, mo_coeffs, kpts=None, q=None): '''Calculate forward (G|ij) FFT of all MO pairs. TODO: - Implement simplifications for real orbitals. Args: mo_coeff: length-2 list of (nao,nmo) ndarrays The two sets of MO coefficients to use in calculating the product |ij). Returns: mo_pairs_G : (ngs, nmoi*nmoj) ndarray The FFT of the real-space MO pairs. ''' coords = gen_grid.gen_uniform_grids(cell) if kpts is None: q = np.zeros(3) aoR = numint.eval_ao(cell, coords) ngs = aoR.shape[0] if np.array_equal(mo_coeffs[0], mo_coeffs[1]): nmoi = nmoj = mo_coeffs[0].shape[1] moiR = mojR = einsum('ri,ia->ra', aoR, mo_coeffs[0]) else: nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] moiR = einsum('ri,ia->ra', aoR, mo_coeffs[0]) mojR = einsum('ri,ia->ra', aoR, mo_coeffs[1]) else: if q is None: q = kpts[1] - kpts[0] aoR_ki = numint.eval_ao(cell, coords, kpt=kpts[0]) aoR_kj = numint.eval_ao(cell, coords, kpt=kpts[1]) ngs = aoR_ki.shape[0] nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] moiR = einsum('ri,ia->ra', aoR_ki, mo_coeffs[0]) mojR = einsum('ri,ia->ra', aoR_kj, mo_coeffs[1]) #mo_pairs_R = einsum('ri,rj->rij', np.conj(moiR), mojR) mo_pairs_G = np.zeros([ngs, nmoi * nmoj], np.complex128) fac = np.exp(-1j * np.dot(coords, q)) for i in xrange(nmoi): for j in xrange(nmoj): mo_pairs_R_ij = np.conj(moiR[:, i]) * mojR[:, j] mo_pairs_G[:, i * nmoj + j] = tools.fftk(mo_pairs_R_ij, cell.gs, fac) return mo_pairs_G
def get_pp_nl(cell, kpt=np.zeros(3)): coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() aokG = tools.fftk(np.asarray(aoR.T, order='C'), cell.gs, np.exp(-1j*np.dot(coords, kpt))).T ngs = len(aokG) fakemol = pyscf.gto.Mole() fakemol._atm = np.zeros((1,pyscf.gto.ATM_SLOTS), dtype=np.int32) fakemol._bas = np.zeros((1,pyscf.gto.BAS_SLOTS), dtype=np.int32) ptr = pyscf.gto.PTR_ENV_START fakemol._env = np.zeros(ptr+10) fakemol._bas[0,pyscf.gto.NPRIM_OF ] = 1 fakemol._bas[0,pyscf.gto.NCTR_OF ] = 1 fakemol._bas[0,pyscf.gto.PTR_EXP ] = ptr+3 fakemol._bas[0,pyscf.gto.PTR_COEFF] = ptr+4 Gv = np.asarray(cell.Gv+kpt) G_rad = lib.norm(Gv, axis=1) vppnl = np.zeros((nao,nao), dtype=np.complex128) for ia in range(cell.natm): symb = cell.atom_symbol(ia) if symb not in cell._pseudo: continue pp = cell._pseudo[symb] for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: hl = np.asarray(hl) fakemol._bas[0,pyscf.gto.ANG_OF] = l fakemol._env[ptr+3] = .5*rl**2 fakemol._env[ptr+4] = rl**(l+1.5)*np.pi**1.25 pYlm_part = pyscf.dft.numint.eval_ao(fakemol, Gv, deriv=0) pYlm = np.empty((nl,l*2+1,ngs)) for k in range(nl): qkl = pseudo.pp._qli(G_rad*rl, l, k) pYlm[k] = pYlm_part.T * qkl # pYlm is real SPG_lmi = np.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) SPG_lm_aoG = np.einsum('nmg,gp->nmp', SPG_lmi, aokG) tmp = np.einsum('ij,jmp->imp', hl, SPG_lm_aoG) vppnl += np.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) vppnl *= (1./ngs**2) if aoR.dtype == np.double: return vppnl.real else: return vppnl
def get_pp_nl(cell, kpt=np.zeros(3)): coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() aokG = tools.fftk(np.asarray(aoR.T, order='C'), cell.gs, np.exp(-1j * np.dot(coords, kpt))).T ngs = len(aokG) fakemol = pyscf.gto.Mole() fakemol._atm = np.zeros((1, pyscf.gto.ATM_SLOTS), dtype=np.int32) fakemol._bas = np.zeros((1, pyscf.gto.BAS_SLOTS), dtype=np.int32) ptr = pyscf.gto.PTR_ENV_START fakemol._env = np.zeros(ptr + 10) fakemol._bas[0, pyscf.gto.NPRIM_OF] = 1 fakemol._bas[0, pyscf.gto.NCTR_OF] = 1 fakemol._bas[0, pyscf.gto.PTR_EXP] = ptr + 3 fakemol._bas[0, pyscf.gto.PTR_COEFF] = ptr + 4 Gv = np.asarray(cell.Gv + kpt) G_rad = lib.norm(Gv, axis=1) vppnl = np.zeros((nao, nao), dtype=np.complex128) for ia in range(cell.natm): symb = cell.atom_symbol(ia) if symb not in cell._pseudo: continue pp = cell._pseudo[symb] for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: hl = np.asarray(hl) fakemol._bas[0, pyscf.gto.ANG_OF] = l fakemol._env[ptr + 3] = .5 * rl**2 fakemol._env[ptr + 4] = rl**(l + 1.5) * np.pi**1.25 pYlm_part = pyscf.dft.numint.eval_ao(fakemol, Gv, deriv=0) pYlm = np.empty((nl, l * 2 + 1, ngs)) for k in range(nl): qkl = pseudo.pp._qli(G_rad * rl, l, k) pYlm[k] = pYlm_part.T * qkl # pYlm is real SPG_lmi = np.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) SPG_lm_aoG = np.einsum('nmg,gp->nmp', SPG_lmi, aokG) tmp = np.einsum('ij,jmp->imp', hl, SPG_lm_aoG) vppnl += np.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) vppnl *= (1. / ngs**2) if aoR.dtype == np.double: return vppnl.real else: return vppnl
def precompute_exx(cell, kpts): from pyscf.pbc import gto as pbcgto from pyscf.pbc.dft import gen_grid log = lib.logger.Logger(cell.stdout, cell.verbose) log.debug("# Precomputing Wigner-Seitz EXX kernel") Nk = get_monkhorst_pack_size(cell, kpts) log.debug("# Nk = %s", Nk) kcell = pbcgto.Cell() kcell.atom = 'H 0. 0. 0.' kcell.spin = 1 kcell.unit = 'B' kcell.verbose = 0 kcell.a = cell.lattice_vectors() * Nk Lc = 1.0/lib.norm(np.linalg.inv(kcell.a), axis=0) log.debug("# Lc = %s", Lc) Rin = Lc.min() / 2.0 log.debug("# Rin = %s", Rin) # ASE: alpha = 5./Rin # sqrt(-ln eps) / Rc, eps ~ 10^{-11} log.info("WS alpha = %s", alpha) kcell.gs = np.array([2*int(L*alpha*3.0) for L in Lc]) # ~ [60,60,60] # QE: #alpha = 3./Rin * np.sqrt(0.5) #kcell.gs = (4*alpha*np.linalg.norm(kcell.a,axis=1)).astype(int) log.debug("# kcell.gs FFT = %s", kcell.gs) kcell.build(False,False) rs = gen_grid.gen_uniform_grids(kcell) kngs = len(rs) log.debug("# kcell kngs = %d", kngs) corners = np.dot(np.indices((2,2,2)).reshape((3,8)).T, kcell.a) #vR = np.empty(kngs) #for i, rv in enumerate(rs): # # Minimum image convention to corners of kcell parallelepiped # r = lib.norm(rv-corners, axis=1).min() # if np.isclose(r, 0.): # vR[i] = 2*alpha / np.sqrt(np.pi) # else: # vR[i] = scipy.special.erf(alpha*r) / r r = np.min([lib.norm(rs-c, axis=1) for c in corners], axis=0) vR = scipy.special.erf(alpha*r) / (r+1e-200) vR[r<1e-9] = 2*alpha / np.sqrt(np.pi) vG = (kcell.vol/kngs) * fft(vR, kcell.gs) ws_exx = {'alpha': alpha, 'kcell': kcell, 'q' : kcell.Gv, 'vq' : vG} log.debug("# Finished precomputing") return ws_exx
def precompute_exx(cell, kpts): from pyscf.pbc import gto as pbcgto from pyscf.pbc.dft import gen_grid log = lib.logger.Logger(cell.stdout, cell.verbose) log.debug("# Precomputing Wigner-Seitz EXX kernel") Nk = get_monkhorst_pack_size(cell, kpts) log.debug("# Nk = %s", Nk) kcell = pbcgto.Cell() kcell.atom = 'H 0. 0. 0.' kcell.spin = 1 kcell.unit = 'B' kcell.verbose = 0 kcell.a = cell.lattice_vectors() * Nk Lc = 1.0/lib.norm(np.linalg.inv(kcell.a), axis=0) log.debug("# Lc = %s", Lc) Rin = Lc.min() / 2.0 log.debug("# Rin = %s", Rin) # ASE: alpha = 5./Rin # sqrt(-ln eps) / Rc, eps ~ 10^{-11} log.info("WS alpha = %s", alpha) kcell.mesh = np.array([4*int(L*alpha*3.0) for L in Lc]) # ~ [60,60,60] # QE: #alpha = 3./Rin * np.sqrt(0.5) #kcell.mesh = (4*alpha*np.linalg.norm(kcell.a,axis=1)).astype(int) log.debug("# kcell.mesh FFT = %s", kcell.mesh) kcell.build(False,False) rs = gen_grid.gen_uniform_grids(kcell) kngs = len(rs) log.debug("# kcell kngs = %d", kngs) corners = np.dot(np.indices((2,2,2)).reshape((3,8)).T, kcell.a) #vR = np.empty(kngs) #for i, rv in enumerate(rs): # # Minimum image convention to corners of kcell parallelepiped # r = lib.norm(rv-corners, axis=1).min() # if np.isclose(r, 0.): # vR[i] = 2*alpha / np.sqrt(np.pi) # else: # vR[i] = scipy.special.erf(alpha*r) / r r = np.min([lib.norm(rs-c, axis=1) for c in corners], axis=0) vR = scipy.special.erf(alpha*r) / (r+1e-200) vR[r<1e-9] = 2*alpha / np.sqrt(np.pi) vG = (kcell.vol/kngs) * fft(vR, kcell.mesh) ws_exx = {'alpha': alpha, 'kcell': kcell, 'q' : kcell.Gv, 'vq' : vG} log.debug("# Finished precomputing") return ws_exx
def get_nuc(cell, kpt=np.zeros(3)): '''Get the bare periodic nuc-el AO matrix, with G=0 removed. See Martin (12.16)-(12.21). ''' coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) chargs = cell.atom_charges() SI = cell.get_SI() coulG = tools.get_coulG(cell) vneG = -np.dot(chargs, SI) * coulG vneR = tools.ifft(vneG, cell.gs).real vne = np.dot(aoR.T.conj(), vneR.reshape(-1, 1) * aoR) return vne
def get_nuc(cell, kpt=np.zeros(3)): '''Get the bare periodic nuc-el AO matrix, with G=0 removed. See Martin (12.16)-(12.21). ''' coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) chargs = cell.atom_charges() SI = cell.get_SI() coulG = tools.get_coulG(cell) vneG = -np.dot(chargs,SI) * coulG vneR = tools.ifft(vneG, cell.gs).real vne = np.dot(aoR.T.conj(), vneR.reshape(-1,1)*aoR) return vne
def get_pp(cell, kpt=np.zeros(3)): '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. ''' coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() vlocG = pseudo.get_vlocG(cell) vlocG[:, 0] = 0 vpplocG = -np.sum(SI * vlocG, axis=0) # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.mesh) vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1, 1) * aoR) # vppnonloc evaluated in reciprocal space aokG = np.empty(aoR.shape, np.complex128) expmikr = np.exp(-1j * np.dot(coords, kpt)) for i in range(nao): aokG[:, i] = tools.fftk(aoR[:, i], cell.mesh, expmikr) ngrids = len(aokG) vppnl = np.zeros((nao, nao), dtype=np.complex128) hs, projGs = pseudo.get_projG(cell, kpt) for ia, [h_ia, projG_ia] in enumerate(zip(hs, projGs)): for l, h in enumerate(h_ia): nl = h.shape[0] for m in range(-l, l + 1): SPG_lm_aoG = np.zeros((nl, nao), dtype=np.complex128) for i in range(nl): SPG_lmi = SI[ia, :] * projG_ia[l][m][i] SPG_lm_aoG[i, :] = np.einsum('g,gp->p', SPG_lmi.conj(), aokG) for i in range(nl): for j in range(nl): # Note: There is no (-1)^l here. vppnl += h[i, j] * np.einsum('p,q->pq', SPG_lm_aoG[i, :].conj(), SPG_lm_aoG[j, :]) vppnl *= (1. / ngrids**2) ovlp = cell.pbc_intor('int1e_ovlp_sph', hermi=1, kpts=kpt) vpploc += 1. / cell.vol * np.sum(pseudo.get_alphas(cell)) * ovlp return vpploc + vppnl
def get_pp(cell, kpt=np.zeros(3)): '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. ''' coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() vlocG = pseudo.get_vlocG(cell) vlocG[:,0] = 0 vpplocG = -np.sum(SI * vlocG, axis=0) # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.mesh) vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1,1)*aoR) # vppnonloc evaluated in reciprocal space aokG = np.empty(aoR.shape, np.complex128) expmikr = np.exp(-1j*np.dot(coords,kpt)) for i in range(nao): aokG[:,i] = tools.fftk(aoR[:,i], cell.mesh, expmikr) ngrids = len(aokG) vppnl = np.zeros((nao,nao), dtype=np.complex128) hs, projGs = pseudo.get_projG(cell, kpt) for ia, [h_ia,projG_ia] in enumerate(zip(hs,projGs)): for l, h in enumerate(h_ia): nl = h.shape[0] for m in range(-l,l+1): SPG_lm_aoG = np.zeros((nl,nao), dtype=np.complex128) for i in range(nl): SPG_lmi = SI[ia,:] * projG_ia[l][m][i] SPG_lm_aoG[i,:] = np.einsum('g,gp->p', SPG_lmi.conj(), aokG) for i in range(nl): for j in range(nl): # Note: There is no (-1)^l here. vppnl += h[i,j]*np.einsum('p,q->pq', SPG_lm_aoG[i,:].conj(), SPG_lm_aoG[j,:]) vppnl *= (1./ngrids**2) ovlp = cell.pbc_intor('int1e_ovlp_sph', hermi=1, kpts=kpt) vpploc += 1./cell.vol * np.sum(pseudo.get_alphas(cell)) * ovlp return vpploc + vppnl
def get_jk(mf, cell, dm, hermi=1, vhfopt=None, kpt=np.zeros(3), kpts_band=None): dm = np.asarray(dm) nao = dm.shape[-1] coords = gen_grid.gen_uniform_grids(cell) if kpts_band is None: kpt1 = kpt2 = kpt aoR_k1 = aoR_k2 = numint.eval_ao(cell, coords, kpt) else: kpt1 = kpts_band kpt2 = kpt aoR_k1 = numint.eval_ao(cell, coords, kpt1) aoR_k2 = numint.eval_ao(cell, coords, kpt2) vkR_k1k2 = get_vkR(mf, cell, aoR_k1, aoR_k2, kpt1, kpt2) ngs, nao = aoR_k1.shape def contract(dm): vjR_k2 = get_vjR(cell, dm, aoR_k2) vj = (cell.vol / ngs) * np.dot(aoR_k1.T.conj(), vjR_k2.reshape(-1, 1) * aoR_k1) #:vk = (cell.vol/ngs) * np.einsum('rs,Rp,Rqs,Rr->pq', dm, aoR_k1.conj(), #: vkR_k1k2, aoR_k2) aoR_dm_k2 = np.dot(aoR_k2, dm) tmp_Rq = np.einsum('Rqs,Rs->Rq', vkR_k1k2, aoR_dm_k2) vk = (cell.vol / ngs) * np.dot(aoR_k1.T.conj(), tmp_Rq) return vj, vk if dm.ndim == 2: vj, vk = contract(dm) else: jk = [contract(x) for x in dm.reshape(-1, nao, nao)] vj = lib.asarray([x[0] for x in jk]) vk = lib.asarray([x[1] for x in jk]) return vj.reshape(dm.shape), vk.reshape(dm.shape)
def get_vkR(mf, cell, aoR_k1, aoR_k2, kpt1, kpt2): coords = gen_grid.gen_uniform_grids(cell) ngs, nao = aoR_k1.shape expmikr = np.exp(-1j*np.dot(kpt1-kpt2,coords.T)) coulG = tools.get_coulG(cell, kpt1-kpt2, exx=True, mf=mf) def prod(ij): i, j = divmod(ij, nao) rhoR = aoR_k1[:,i] * aoR_k2[:,j].conj() rhoG = tools.fftk(rhoR, cell.gs, expmikr) vG = coulG*rhoG vR = tools.ifftk(vG, cell.gs, expmikr.conj()) return vR if aoR_k1.dtype == np.double and aoR_k2.dtype == np.double: vR = numpy.asarray([prod(ij).real for ij in range(nao**2)]) else: vR = numpy.asarray([prod(ij) for ij in range(nao**2)]) return vR.reshape(nao,nao,-1).transpose(2,0,1)
def get_vkR(mf, cell, aoR_k1, aoR_k2, kpt1, kpt2): coords = gen_grid.gen_uniform_grids(cell) ngs, nao = aoR_k1.shape expmikr = np.exp(-1j * np.dot(kpt1 - kpt2, coords.T)) coulG = tools.get_coulG(cell, kpt1 - kpt2, exx=True, mf=mf) def prod(ij): i, j = divmod(ij, nao) rhoR = aoR_k1[:, i] * aoR_k2[:, j].conj() rhoG = tools.fftk(rhoR, cell.gs, expmikr) vG = coulG * rhoG vR = tools.ifftk(vG, cell.gs, expmikr.conj()) return vR if aoR_k1.dtype == np.double and aoR_k2.dtype == np.double: vR = numpy.asarray([prod(ij).real for ij in range(nao**2)]) else: vR = numpy.asarray([prod(ij) for ij in range(nao**2)]) return vR.reshape(nao, nao, -1).transpose(2, 0, 1)
def get_vkR(mf, cell, aoR_k1, aoR_k2, kpt1, kpt2): '''Get the real-space 2-index "exchange" potential V_{i,k1; j,k2}(r) where {i,k1} = exp^{i k1 r) |i> , {j,k2} = exp^{-i k2 r) <j| ''' coords = gen_grid.gen_uniform_grids(cell) ngrids, nao = aoR_k1.shape expmikr = np.exp(-1j*np.dot(kpt1-kpt2,coords.T)) coulG = tools.get_coulG(cell, kpt1-kpt2, exx=True, mf=mf) def prod(ij): i, j = divmod(ij, nao) rhoR = aoR_k1[:,i] * aoR_k2[:,j].conj() rhoG = tools.fftk(rhoR, cell.mesh, expmikr) vG = coulG*rhoG vR = tools.ifftk(vG, cell.mesh, expmikr.conj()) return vR if aoR_k1.dtype == np.double and aoR_k2.dtype == np.double: vR = numpy.asarray([prod(ij).real for ij in range(nao**2)]) else: vR = numpy.asarray([prod(ij) for ij in range(nao**2)]) return vR.reshape(nao,nao,-1).transpose(2,0,1)
def get_pp_loc_part2(cell, kpt=np.zeros(3)): coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() G = lib.norm(cell.Gv, axis=1) vlocG = np.zeros((cell.natm,len(G))) for ia in range(cell.natm): Zia = cell.atom_charge(ia) symb = cell.atom_symbol(ia) if symb not in cell._pseudo: vlocG[ia] = 0 continue pp = cell._pseudo[symb] rloc, nexp, cexp = pp[1:3+1] G_red = G*rloc cfacs = np.array( [1*G_red**0, 3 - G_red**2, 15 - 10*G_red**2 + G_red**4, 105 - 105*G_red**2 + 21*G_red**4 - G_red**6]) with np.errstate(divide='ignore'): # Note the signs -- potential here is positive vlocG[ia,:] = (# 4*np.pi * Zia * np.exp(-0.5*G_red**2)/G**2 - (2*np.pi)**(3/2.)*rloc**3*np.exp(-0.5*G_red**2)*( np.dot(cexp, cfacs[:nexp])) ) vpplocG = -np.sum(SI * vlocG, axis=0) vpplocR = tools.ifft(vpplocG, cell.gs).real vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1,1)*aoR) if aoR.dtype == np.double: return vpploc.real else: return vpploc
def get_ao_pairs_G(cell, kpt=np.zeros(3)): '''Calculate forward (G|ij) and "inverse" (ij|G) FFT of all AO pairs. Args: cell : instance of :class:`Cell` Returns: ao_pairs_G, ao_pairs_invG : (ngrids, nao*(nao+1)/2) ndarray The FFTs of the real-space AO pairs. ''' coords = gen_uniform_grids(cell) aoR = eval_ao(cell, coords, kpt) # shape = (coords, nao) ngrids, nao = aoR.shape gamma_point = abs(kpt).sum() < 1e-9 if gamma_point: npair = nao * (nao + 1) // 2 ao_pairs_G = np.empty([ngrids, npair], np.complex128) ij = 0 for i in range(nao): for j in range(i + 1): ao_ij_R = np.conj(aoR[:, i]) * aoR[:, j] ao_pairs_G[:, ij] = tools.fft(ao_ij_R, cell.mesh) #ao_pairs_invG[:,ij] = ngrids*tools.ifft(ao_ij_R, cell.mesh) ij += 1 ao_pairs_invG = ao_pairs_G.conj() else: ao_pairs_G = np.zeros([ngrids, nao, nao], np.complex128) for i in range(nao): for j in range(nao): ao_ij_R = np.conj(aoR[:, i]) * aoR[:, j] ao_pairs_G[:, i, j] = tools.fft(ao_ij_R, cell.mesh) ao_pairs_invG = ao_pairs_G.transpose(0, 2, 1).conj().reshape(-1, nao**2) ao_pairs_G = ao_pairs_G.reshape(-1, nao**2) return ao_pairs_G, ao_pairs_invG
def get_ao_pairs_G(cell, kpt=np.zeros(3)): '''Calculate forward (G|ij) and "inverse" (ij|G) FFT of all AO pairs. Args: cell : instance of :class:`Cell` Returns: ao_pairs_G, ao_pairs_invG : (ngs, nao*(nao+1)/2) ndarray The FFTs of the real-space AO pairs. ''' coords = gen_uniform_grids(cell) aoR = eval_ao(cell, coords, kpt) # shape = (coords, nao) ngs, nao = aoR.shape gamma_point = abs(kpt).sum() < 1e-9 if gamma_point: npair = nao*(nao+1)//2 ao_pairs_G = np.empty([ngs, npair], np.complex128) ij = 0 for i in range(nao): for j in range(i+1): ao_ij_R = np.conj(aoR[:,i]) * aoR[:,j] ao_pairs_G[:,ij] = tools.fft(ao_ij_R, cell.gs) #ao_pairs_invG[:,ij] = ngs*tools.ifft(ao_ij_R, cell.gs) ij += 1 ao_pairs_invG = ao_pairs_G.conj() else: ao_pairs_G = np.zeros([ngs, nao,nao], np.complex128) for i in range(nao): for j in range(nao): ao_ij_R = np.conj(aoR[:,i]) * aoR[:,j] ao_pairs_G[:,i,j] = tools.fft(ao_ij_R, cell.gs) ao_pairs_invG = ao_pairs_G.transpose(0,2,1).conj().reshape(-1,nao**2) ao_pairs_G = ao_pairs_G.reshape(-1,nao**2) return ao_pairs_G, ao_pairs_invG
mygs = 4 # grid density alat = 4.0 orbs_to_show = set((('2s', ''), ('2p', 'x'), ('3d', 'xy'), ('3d', 'z^2'))) assert len(orbs_to_show) == 4 # !!!! hard-code 4 plots gs = np.array([mygs] * 3) basis = bfd_basis() cell = gto.M(a=alat * np.eye(3), atom='C 2.0 2.0 2.0', verbose=3, gs=gs, pseudo={'C': 'bfd'}, basis=basis) coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords) grid_shape = 2 * gs + 1 fig = plt.figure() iplot = 0 bas_labels = cell.ao_labels(fmt=False) for ibas in range(len(bas_labels)): iatom, alabel, b_l, b_m = bas_labels[ibas] if (b_l, b_m) not in orbs_to_show: continue iplot += 1 ax = fig.add_subplot(2, 2, iplot, projection='3d')
def test_components(pseudo=None): # The molecular calculation mol = gto.Mole() mol.unit = 'B' L = 60 mol.atom.extend([ ['He', (L / 2., L / 2., L / 2.)], ]) mol.basis = 'sto-3g' mol.build() m = rks.RKS(mol) m.xc = 'LDA,VWN_RPA' print(m.scf()) # -2.90705411168 dm = m.make_rdm1() # The periodic calculation cell = pbcgto.Cell() cell.unit = 'B' cell.a = np.diag([L, L, L]) cell.gs = np.array([80, 80, 80]) cell.atom = mol.atom cell.basis = mol.basis cell.pseudo = pseudo cell.build() # These should match reasonably well (roughly with accuracy of normalization) print "Kinetic energy" tao = pbchf.get_t(cell) tao2 = mol.intor_symmetric('cint1e_kin_sph') print np.dot(np.ravel(tao), np.ravel(dm)) # 2.82793077196 print np.dot(np.ravel(tao2), np.ravel(dm)) # 2.82352636524 print "Overlap" sao = pbchf.get_ovlp(cell) print np.dot(np.ravel(sao), np.ravel(dm)) # 1.99981725342 print np.dot(np.ravel(m.get_ovlp()), np.ravel(dm)) # 2.0 # The next two entries should *not* match, since G=0 component is removed print "Coulomb (G!=0)" jao = pbchf.get_j(cell, dm) print np.dot(np.ravel(dm), np.ravel(jao)) # 4.03425518427 print np.dot(np.ravel(dm), np.ravel(m.get_j(dm))) # 4.22285177049 # The next two entries should *not* match, since G=0 component is removed print "Nuc-el (G!=0)" if cell.pseudo: vppao = pbchf.get_pp(cell) print np.dot(np.ravel(dm), np.ravel(vppao)) else: neao = pbchf.get_nuc(cell) print np.dot(np.ravel(dm), np.ravel(neao)) # -6.50203360062 vne = mol.intor_symmetric('cint1e_nuc_sph') print np.dot(np.ravel(dm), np.ravel(vne)) # -6.68702326551 print "Normalization" coords = gen_uniform_grids(cell) aoR = eval_ao(cell, coords) rhoR = eval_rho(cell, aoR, dm) print cell.vol / len(rhoR) * np.sum(rhoR) # 1.99981725342 (should be 2.0) print "(Hartree + vne) * DM" print np.dot(np.ravel(dm), np.ravel(m.get_j(dm))) + np.dot( np.ravel(dm), np.ravel(vne)) if cell.pseudo: print np.einsum("ij,ij", dm, vppao + jao + pbchf.get_jvloc_G0(cell)) else: print np.einsum("ij,ij", dm, neao + jao) ew_cut = (40, 40, 40) ew_eta = 0.05 for ew_eta in [0.1, 0.5, 1.]: ew = pbchf.ewald(cell, ew_eta, ew_cut) print "Ewald (eta, energy)", ew_eta, ew # should be same for all eta print "Ewald divergent terms summation", ew # These two should now match if the box is reasonably big to # remove images, and ngs is big. print "Total coulomb (analytic) ", print(.5 * np.dot(np.ravel(dm), np.ravel(m.get_j(dm))) + np.dot(np.ravel(dm), np.ravel(vne))) # -4.57559738004 if not cell.pseudo: print "Total coulomb (fft coul + ewald)", print np.einsum("ij,ij", dm, neao + .5 * jao) + ew # -4.57948259115 # Exc cell.ew_eta, cell.ew_cut = ew_eta, ew_cut mf = pbcdft.RKS(cell) mf.xc = 'LDA,VWN_RPA' rks.get_veff(mf, cell, dm) print "Exc", mf._exc # -1.05967570089
def precompute_exx(cell, kpts): from pyscf.pbc import gto as pbcgto from pyscf.pbc.dft import gen_grid log = lib.logger.Logger(cell.stdout, cell.verbose) log.debug("# Precomputing Wigner-Seitz EXX kernel") Nk = get_monkhorst_pack_size(cell, kpts) log.debug("# Nk = %s", Nk) kcell = pbcgto.Cell() kcell.atom = 'H 0. 0. 0.' kcell.spin = 1 kcell.unit = 'B' kcell.verbose = 0 kcell.a = cell.lattice_vectors() * Nk Lc = 1.0 / lib.norm(np.linalg.inv(kcell.a), axis=0) log.debug("# Lc = %s", Lc) Rin = Lc.min() / 2.0 log.debug("# Rin = %s", Rin) # ASE: alpha = 5. / Rin # sqrt(-ln eps) / Rc, eps ~ 10^{-11} log.info("WS alpha = %s", alpha) kcell.mesh = np.array([4 * int(L * alpha * 3.0) for L in Lc]) # ~ [120,120,120] # QE: #alpha = 3./Rin * np.sqrt(0.5) #kcell.mesh = (4*alpha*np.linalg.norm(kcell.a,axis=1)).astype(int) log.debug("# kcell.mesh FFT = %s", kcell.mesh) rs = gen_grid.gen_uniform_grids(kcell) kngs = len(rs) log.debug("# kcell kngs = %d", kngs) corners_coord = lib.cartesian_prod(([0, 1], [0, 1], [0, 1])) corners = np.dot(corners_coord, kcell.a) #vR = np.empty(kngs) #for i, rv in enumerate(rs): # # Minimum image convention to corners of kcell parallelepiped # r = lib.norm(rv-corners, axis=1).min() # if np.isclose(r, 0.): # vR[i] = 2*alpha / np.sqrt(np.pi) # else: # vR[i] = scipy.special.erf(alpha*r) / r r = np.min([lib.norm(rs - c, axis=1) for c in corners], axis=0) vR = scipy.special.erf(alpha * r) / (r + 1e-200) vR[r < 1e-9] = 2 * alpha / np.sqrt(np.pi) vG = (kcell.vol / kngs) * fft(vR, kcell.mesh) if abs(vG.imag).max() > 1e-6: # vG should be real in regular lattice. If imaginary part is observed, # this probably means a ws cell was built from a unconventional # lattice. The SR potential erfc(alpha*r) for the charge in the center # of ws cell decays to the region out of ws cell. The Ewald-sum based # on the minimum image convention cannot be used to build the kernel # Eq (12) of PRB 87, 165122 raise RuntimeError('Unconventional lattice was found') ws_exx = { 'alpha': alpha, 'kcell': kcell, 'q': kcell.Gv, 'vq': vG.real.copy() } log.debug("# Finished precomputing") return ws_exx
def get_pp(cell, kpt=np.zeros(3)): '''Get the periodic pseudotential nuc-el AO matrix ''' import pyscf.dft from pyscf.pbc import tools from pyscf.pbc.dft import gen_grid from pyscf.pbc.dft import numint coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() vlocG = get_vlocG(cell) vpplocG = -np.sum(SI * vlocG, axis=0) vpplocG[0] = np.sum(get_alphas(cell)) # from get_jvloc_G0 function # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.gs).real vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1, 1) * aoR) # vppnonloc evaluated in reciprocal space aokG = tools.fftk(np.asarray(aoR.T, order='C'), cell.gs, np.exp(-1j * np.dot(coords, kpt))).T ngs = len(aokG) fakemol = pyscf.gto.Mole() fakemol._atm = np.zeros((1, pyscf.gto.ATM_SLOTS), dtype=np.int32) fakemol._bas = np.zeros((1, pyscf.gto.BAS_SLOTS), dtype=np.int32) ptr = pyscf.gto.PTR_ENV_START fakemol._env = np.zeros(ptr + 10) fakemol._bas[0, pyscf.gto.NPRIM_OF] = 1 fakemol._bas[0, pyscf.gto.NCTR_OF] = 1 fakemol._bas[0, pyscf.gto.PTR_EXP] = ptr + 3 fakemol._bas[0, pyscf.gto.PTR_COEFF] = ptr + 4 Gv = np.asarray(cell.Gv + kpt) G_rad = lib.norm(Gv, axis=1) vppnl = np.zeros((nao, nao), dtype=np.complex128) for ia in range(cell.natm): symb = cell.atom_symbol(ia) if symb not in cell._pseudo: continue pp = cell._pseudo[symb] for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: hl = np.asarray(hl) fakemol._bas[0, pyscf.gto.ANG_OF] = l fakemol._env[ptr + 3] = .5 * rl**2 fakemol._env[ptr + 4] = rl**(l + 1.5) * np.pi**1.25 pYlm_part = pyscf.dft.numint.eval_ao(fakemol, Gv, deriv=0) pYlm = np.empty((nl, l * 2 + 1, ngs)) for k in range(nl): qkl = _qli(G_rad * rl, l, k) pYlm[k] = pYlm_part.T * qkl # pYlm is real SPG_lmi = np.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) SPG_lm_aoG = np.einsum('nmg,gp->nmp', SPG_lmi, aokG) tmp = np.einsum('ij,jmp->imp', hl, SPG_lm_aoG) vppnl += np.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) vppnl *= (1. / ngs**2) if aoR.dtype == np.double: return vpploc.real + vppnl.real else: return vpploc + vppnl
def get_pp(cell, kpt=np.zeros(3)): '''Get the periodic pseudotential nuc-el AO matrix ''' import pyscf.dft from pyscf.pbc import tools from pyscf.pbc.dft import gen_grid from pyscf.pbc.dft import numint coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() vlocG = get_vlocG(cell) vpplocG = -np.sum(SI * vlocG, axis=0) vpplocG[0] = np.sum(get_alphas(cell)) # from get_jvloc_G0 function # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.gs).real vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1,1)*aoR) # vppnonloc evaluated in reciprocal space aokG = tools.fftk(np.asarray(aoR.T, order='C'), cell.gs, np.exp(-1j*np.dot(coords, kpt))).T ngs = len(aokG) fakemol = pyscf.gto.Mole() fakemol._atm = np.zeros((1,pyscf.gto.ATM_SLOTS), dtype=np.int32) fakemol._bas = np.zeros((1,pyscf.gto.BAS_SLOTS), dtype=np.int32) ptr = pyscf.gto.PTR_ENV_START fakemol._env = np.zeros(ptr+10) fakemol._bas[0,pyscf.gto.NPRIM_OF ] = 1 fakemol._bas[0,pyscf.gto.NCTR_OF ] = 1 fakemol._bas[0,pyscf.gto.PTR_EXP ] = ptr+3 fakemol._bas[0,pyscf.gto.PTR_COEFF] = ptr+4 Gv = np.asarray(cell.Gv+kpt) G_rad = lib.norm(Gv, axis=1) vppnl = np.zeros((nao,nao), dtype=np.complex128) for ia in range(cell.natm): symb = cell.atom_symbol(ia) if symb not in cell._pseudo: continue pp = cell._pseudo[symb] for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: hl = np.asarray(hl) fakemol._bas[0,pyscf.gto.ANG_OF] = l fakemol._env[ptr+3] = .5*rl**2 fakemol._env[ptr+4] = rl**(l+1.5)*np.pi**1.25 pYlm_part = pyscf.dft.numint.eval_ao(fakemol, Gv, deriv=0) pYlm = np.empty((nl,l*2+1,ngs)) for k in range(nl): qkl = _qli(G_rad*rl, l, k) pYlm[k] = pYlm_part.T * qkl # pYlm is real SPG_lmi = np.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) SPG_lm_aoG = np.einsum('nmg,gp->nmp', SPG_lmi, aokG) tmp = np.einsum('ij,jmp->imp', hl, SPG_lm_aoG) vppnl += np.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) vppnl *= (1./ngs**2) if aoR.dtype == np.double: return vpploc.real + vppnl.real else: return vpploc + vppnl
def test_components(pseudo=None): # The molecular calculation mol = gto.Mole() mol.unit = 'B' L = 60 mol.atom.extend([['He', (L/2.,L/2.,L/2.)], ]) mol.basis = 'sto-3g' mol.build() m = rks.RKS(mol) m.xc = 'LDA,VWN_RPA' print(m.scf()) # -2.90705411168 dm = m.make_rdm1() # The periodic calculation cell = pbcgto.Cell() cell.unit = 'B' cell.a = np.diag([L,L,L]) cell.gs = np.array([80,80,80]) cell.atom = mol.atom cell.basis = mol.basis cell.pseudo = pseudo cell.build() # These should match reasonably well (roughly with accuracy of normalization) print "Kinetic energy" tao = pbchf.get_t(cell) tao2 = mol.intor_symmetric('cint1e_kin_sph') print np.dot(np.ravel(tao), np.ravel(dm)) # 2.82793077196 print np.dot(np.ravel(tao2), np.ravel(dm)) # 2.82352636524 print "Overlap" sao = pbchf.get_ovlp(cell) print np.dot(np.ravel(sao), np.ravel(dm)) # 1.99981725342 print np.dot(np.ravel(m.get_ovlp()), np.ravel(dm)) # 2.0 # The next two entries should *not* match, since G=0 component is removed print "Coulomb (G!=0)" jao = pbchf.get_j(cell, dm) print np.dot(np.ravel(dm),np.ravel(jao)) # 4.03425518427 print np.dot(np.ravel(dm),np.ravel(m.get_j(dm))) # 4.22285177049 # The next two entries should *not* match, since G=0 component is removed print "Nuc-el (G!=0)" if cell.pseudo: vppao = pbchf.get_pp(cell) print np.dot(np.ravel(dm), np.ravel(vppao)) else: neao = pbchf.get_nuc(cell) print np.dot(np.ravel(dm), np.ravel(neao)) # -6.50203360062 vne = mol.intor_symmetric('cint1e_nuc_sph') print np.dot(np.ravel(dm), np.ravel(vne)) # -6.68702326551 print "Normalization" coords = gen_uniform_grids(cell) aoR = eval_ao(cell, coords) rhoR = eval_rho(cell, aoR, dm) print cell.vol/len(rhoR)*np.sum(rhoR) # 1.99981725342 (should be 2.0) print "(Hartree + vne) * DM" print np.dot(np.ravel(dm),np.ravel(m.get_j(dm)))+np.dot(np.ravel(dm), np.ravel(vne)) if cell.pseudo: print np.einsum("ij,ij", dm, vppao + jao + pbchf.get_jvloc_G0(cell)) else: print np.einsum("ij,ij", dm, neao + jao) ew_cut = (40,40,40) ew_eta = 0.05 for ew_eta in [0.1, 0.5, 1.]: ew = pbchf.ewald(cell, ew_eta, ew_cut) print "Ewald (eta, energy)", ew_eta, ew # should be same for all eta print "Ewald divergent terms summation", ew # These two should now match if the box is reasonably big to # remove images, and ngs is big. print "Total coulomb (analytic) ", print (.5*np.dot(np.ravel(dm), np.ravel(m.get_j(dm))) + np.dot(np.ravel(dm), np.ravel(vne)) ) # -4.57559738004 if not cell.pseudo: print "Total coulomb (fft coul + ewald)", print np.einsum("ij,ij", dm, neao + .5*jao) + ew # -4.57948259115 # Exc cell.ew_eta, cell.ew_cut = ew_eta, ew_cut mf = pbcdft.RKS(cell) mf.xc = 'LDA,VWN_RPA' rks.get_veff(mf, cell, dm) print "Exc", mf._exc # -1.05967570089
def ao_on_grid(cell): from pyscf.pbc.dft import gen_grid, numint coords = gen_grid.gen_uniform_grids(cell) aoR = numint.eval_ao(cell, coords) return aoR
def get_jk_kpts(mf, cell, dm_kpts, kpts, kpts_band=None): coords = gen_grid.gen_uniform_grids(cell) nkpts = len(kpts) ngs = len(coords) dm_kpts = np.asarray(dm_kpts) nao = dm_kpts.shape[-1] dms = dm_kpts.reshape(-1, nkpts, nao, nao) nset = dms.shape[0] ni = numint._KNumInt(kpts) aoR_kpts = ni.eval_ao(cell, coords, kpts) if kpts_band is not None: aoR_kband = numint.eval_ao(cell, coords, kpts_band) # J vjR = [get_vjR_kpts(cell, dms[i], aoR_kpts) for i in range(nset)] if kpts_band is not None: vj_kpts = [ cell.vol / ngs * lib.dot(aoR_kband.T.conj() * vjR[i], aoR_kband) for i in range(nset) ] else: vj_kpts = [] for i in range(nset): vj = [ cell.vol / ngs * lib.dot(aoR_k.T.conj() * vjR[i], aoR_k) for aoR_k in aoR_kpts ] vj_kpts.append(lib.asarray(vj)) vj_kpts = lib.asarray(vj_kpts) vjR = None # K weight = 1. / nkpts * (cell.vol / ngs) vk_kpts = np.zeros_like(vj_kpts) if kpts_band is not None: for k2, kpt2 in enumerate(kpts): aoR_dms = [lib.dot(aoR_kpts[k2], dms[i, k2]) for i in range(nset)] vkR_k1k2 = get_vkR(mf, cell, aoR_kband, aoR_kpts[k2], kpts_band, kpt2) #:vk_kpts = 1./nkpts * (cell.vol/ngs) * np.einsum('rs,Rp,Rqs,Rr->pq', #: dm_kpts[k2], aoR_kband.conj(), #: vkR_k1k2, aoR_kpts[k2]) for i in range(nset): tmp_Rq = np.einsum('Rqs,Rs->Rq', vkR_k1k2, aoR_dms[i]) vk_kpts[i] += weight * lib.dot(aoR_kband.T.conj(), tmp_Rq) vkR_k1k2 = None if dm_kpts.ndim == 3: vj_kpts = vj_kpts[0] vk_kpts = vk_kpts[0] return lib.asarray(vj_kpts), lib.asarray(vk_kpts) else: for k2, kpt2 in enumerate(kpts): aoR_dms = [lib.dot(aoR_kpts[k2], dms[i, k2]) for i in range(nset)] for k1, kpt1 in enumerate(kpts): vkR_k1k2 = get_vkR(mf, cell, aoR_kpts[k1], aoR_kpts[k2], kpt1, kpt2) for i in range(nset): tmp_Rq = np.einsum('Rqs,Rs->Rq', vkR_k1k2, aoR_dms[i]) vk_kpts[i, k1] += weight * lib.dot(aoR_kpts[k1].T.conj(), tmp_Rq) vkR_k1k2 = None return vj_kpts.reshape(dm_kpts.shape), vk_kpts.reshape(dm_kpts.shape)