def get_pp_o1(cell, kpt=np.zeros(3)): '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. ''' coords = pyscf.pbc.dft.gen_grid.gen_uniform_grids(cell) aoR = pyscf.pbc.dft.numint.eval_ao(cell, coords, kpt) nao = cell.nao_nr() SI = cell.get_SI() vlocG = pseudo.get_vlocG(cell) vpplocG = -np.sum(SI * vlocG, axis=0) # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.gs) vpploc = np.dot(aoR.T.conj(), vpplocR.reshape(-1,1)*aoR) # vppnonloc evaluated in reciprocal space aokG = np.empty(aoR.shape, np.complex128) for i in range(nao): aokG[:,i] = tools.fftk(aoR[:,i], cell.gs, coords, kpt) 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) fakemol._env = np.zeros(5) fakemol._bas[0,pyscf.gto.NPRIM_OF ] = 1 fakemol._bas[0,pyscf.gto.NCTR_OF ] = 1 fakemol._bas[0,pyscf.gto.PTR_EXP ] = 3 fakemol._bas[0,pyscf.gto.PTR_COEFF] = 4 Gv = np.asarray(cell.Gv+kpt) G_rad = pyscf.lib.norm(Gv, axis=1) vppnl = np.zeros((nao,nao), dtype=np.complex128) for ia in range(cell.natm): pp = cell._pseudo[cell.atom_symbol(ia)] 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[3] = .5*rl**2 fakemol._env[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) 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_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(mydf, kpts=None): '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. ''' cell = mydf.cell if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) gs = mydf.gs SI = cell.get_SI() Gv = cell.get_Gv(gs) vpplocG = pseudo.get_vlocG(cell, Gv) vpplocG = -numpy.einsum('ij,ij->j', SI, vpplocG) vpplocG[0] = numpy.sum( pseudo.get_alphas(cell)) # from get_jvloc_G0 function ngs = len(vpplocG) # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.gs).real vpp = [ lib.dot(aoR.T.conj() * vpplocR, aoR) for k, aoR in mydf.aoR_loop(gs, kpts_lst) ] # vppnonloc evaluated in reciprocal space fakemol = gto.Mole() fakemol._atm = numpy.zeros((1, gto.ATM_SLOTS), dtype=numpy.int32) fakemol._bas = numpy.zeros((1, gto.BAS_SLOTS), dtype=numpy.int32) ptr = gto.PTR_ENV_START fakemol._env = numpy.zeros(ptr + 10) fakemol._bas[0, gto.NPRIM_OF] = 1 fakemol._bas[0, gto.NCTR_OF] = 1 fakemol._bas[0, gto.PTR_EXP] = ptr + 3 fakemol._bas[0, gto.PTR_COEFF] = ptr + 4 # buf for SPG_lmi upto l=0..3 and nl=3 buf = numpy.empty((48, ngs), dtype=numpy.complex128) def vppnl_by_k(kpt): Gk = Gv + kpt G_rad = lib.norm(Gk, axis=1) aokG = ft_ao.ft_ao(cell, Gv, kpt=kpt) * (ngs / cell.vol) vppnl = 0 for ia in range(cell.natm): symb = cell.atom_symbol(ia) if symb not in cell._pseudo: continue pp = cell._pseudo[symb] p1 = 0 for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: fakemol._bas[0, gto.ANG_OF] = l fakemol._env[ptr + 3] = .5 * rl**2 fakemol._env[ptr + 4] = rl**(l + 1.5) * numpy.pi**1.25 pYlm_part = dft.numint.eval_ao(fakemol, Gk, deriv=0) p0, p1 = p1, p1 + nl * (l * 2 + 1) # pYlm is real, SI[ia] is complex pYlm = numpy.ndarray((nl, l * 2 + 1, ngs), dtype=numpy.complex128, buffer=buf[p0:p1]) for k in range(nl): qkl = pseudo.pp._qli(G_rad * rl, l, k) pYlm[k] = pYlm_part.T * qkl #:SPG_lmi = numpy.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) #:SPG_lm_aoG = numpy.einsum('nmg,gp->nmp', SPG_lmi, aokG) #:tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG) #:vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) if p1 > 0: SPG_lmi = buf[:p1] SPG_lmi *= SI[ia].conj() SPG_lm_aoGs = lib.zdot(SPG_lmi, aokG) p1 = 0 for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: p0, p1 = p1, p1 + nl * (l * 2 + 1) hl = numpy.asarray(hl) SPG_lm_aoG = SPG_lm_aoGs[p0:p1].reshape( nl, l * 2 + 1, -1) tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG) vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) return vppnl * (1. / ngs**2) for k, kpt in enumerate(kpts_lst): vppnl = vppnl_by_k(kpt) if gamma_point(kpt): vpp[k] = vpp[k].real + vppnl.real else: vpp[k] += vppnl if kpts is None or numpy.shape(kpts) == (3, ): vpp = vpp[0] return numpy.asarray(vpp)
def get_pp(mydf, kpts=None): """Get the periodic pseudotential nuc-el AO matrix, with G=0 removed. """ cell = mydf.cell if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) gs = mydf.gs SI = cell.get_SI() Gv = cell.get_Gv(gs) vpplocG = pseudo.get_vlocG(cell, Gv) vpplocG = -numpy.einsum("ij,ij->j", SI, vpplocG) vpplocG[0] = numpy.sum(pseudo.get_alphas(cell)) # from get_jvloc_G0 function ngs = len(vpplocG) nao = cell.nao_nr() # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, cell.gs).real vpp = [lib.dot(aoR.T.conj() * vpplocR, aoR) for k, aoR in mydf.aoR_loop(gs, kpts_lst)] # vppnonloc evaluated in reciprocal space fakemol = gto.Mole() fakemol._atm = numpy.zeros((1, gto.ATM_SLOTS), dtype=numpy.int32) fakemol._bas = numpy.zeros((1, gto.BAS_SLOTS), dtype=numpy.int32) ptr = gto.PTR_ENV_START fakemol._env = numpy.zeros(ptr + 10) fakemol._bas[0, gto.NPRIM_OF] = 1 fakemol._bas[0, gto.NCTR_OF] = 1 fakemol._bas[0, gto.PTR_EXP] = ptr + 3 fakemol._bas[0, gto.PTR_COEFF] = ptr + 4 def vppnl_by_k(kpt): Gk = Gv + kpt G_rad = lib.norm(Gk, axis=1) aokG = ft_ao.ft_ao(cell, Gv, kpt=kpt) * (ngs / cell.vol) vppnl = 0 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 = numpy.asarray(hl) fakemol._bas[0, gto.ANG_OF] = l fakemol._env[ptr + 3] = 0.5 * rl ** 2 fakemol._env[ptr + 4] = rl ** (l + 1.5) * numpy.pi ** 1.25 pYlm_part = dft.numint.eval_ao(fakemol, Gk, deriv=0) pYlm = numpy.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 = numpy.einsum("g,nmg->nmg", SI[ia].conj(), pYlm) SPG_lm_aoG = numpy.einsum("nmg,gp->nmp", SPG_lmi, aokG) tmp = numpy.einsum("ij,jmp->imp", hl, SPG_lm_aoG) vppnl += numpy.einsum("imp,imq->pq", SPG_lm_aoG.conj(), tmp) return vppnl * (1.0 / ngs ** 2) for k, kpt in enumerate(kpts_lst): vppnl = vppnl_by_k(kpt) if abs(kpt).sum() < 1e-9: # gamma_point vpp[k] = vpp[k].real + vppnl.real else: vpp[k] += vppnl if kpts is None or numpy.shape(kpts) == (3,): vpp = vpp[0] return vpp
def get_pp(mydf, kpts=None): mydf = _sync_mydf(mydf) cell = mydf.cell if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) if abs(kpts_lst).sum() < 1e-9: dtype = numpy.float64 else: dtype = numpy.complex128 mesh = mydf.mesh SI = cell.get_SI() Gv = cell.get_Gv(mesh) vpplocG = pseudo.get_vlocG(cell, Gv) vpplocG = -numpy.einsum('ij,ij->j', SI, vpplocG) ngrids = len(vpplocG) nao = cell.nao_nr() nkpts = len(kpts_lst) # vpploc evaluated in real-space vpplocR = tools.ifft(vpplocG, mesh).real vpp = numpy.zeros((nkpts, nao, nao), dtype=dtype) for ao_ks_etc, p0, p1 in mydf.mpi_aoR_loop(mydf.grids, kpts_lst): ao_ks = ao_ks_etc[0] for k, ao in enumerate(ao_ks): vpp[k] += lib.dot(ao.T.conj() * vpplocR[p0:p1], ao) ao = ao_ks = None vpp = mpi.reduce(lib.asarray(vpp)) # vppnonloc evaluated in reciprocal space fakemol = gto.Mole() fakemol._atm = numpy.zeros((1, gto.ATM_SLOTS), dtype=numpy.int32) fakemol._bas = numpy.zeros((1, gto.BAS_SLOTS), dtype=numpy.int32) ptr = gto.PTR_ENV_START fakemol._env = numpy.zeros(ptr + 10) fakemol._bas[0, gto.NPRIM_OF] = 1 fakemol._bas[0, gto.NCTR_OF] = 1 fakemol._bas[0, gto.PTR_EXP] = ptr + 3 fakemol._bas[0, gto.PTR_COEFF] = ptr + 4 # buf for SPG_lmi upto l=0..3 and nl=3 buf = numpy.empty((48, ngrids), dtype=numpy.complex128) def vppnl_by_k(kpt): Gk = Gv + kpt G_rad = lib.norm(Gk, axis=1) aokG = ft_ao.ft_ao(cell, Gv, kpt=kpt) * (ngrids / cell.vol) vppnl = 0 for ia in range(cell.natm): symb = cell.atom_symbol(ia) if symb not in cell._pseudo: continue pp = cell._pseudo[symb] p1 = 0 for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: fakemol._bas[0, gto.ANG_OF] = l fakemol._env[ptr + 3] = .5 * rl**2 fakemol._env[ptr + 4] = rl**(l + 1.5) * numpy.pi**1.25 pYlm_part = dft.numint.eval_ao(fakemol, Gk, deriv=0) p0, p1 = p1, p1 + nl * (l * 2 + 1) # pYlm is real, SI[ia] is complex pYlm = numpy.ndarray((nl, l * 2 + 1, ngrids), dtype=numpy.complex128, buffer=buf[p0:p1]) for k in range(nl): qkl = pseudo.pp._qli(G_rad * rl, l, k) pYlm[k] = pYlm_part.T * qkl #:SPG_lmi = numpy.einsum('g,nmg->nmg', SI[ia].conj(), pYlm) #:SPG_lm_aoG = numpy.einsum('nmg,gp->nmp', SPG_lmi, aokG) #:tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG) #:vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) if p1 > 0: SPG_lmi = buf[:p1] SPG_lmi *= SI[ia].conj() SPG_lm_aoGs = lib.zdot(SPG_lmi, aokG) p1 = 0 for l, proj in enumerate(pp[5:]): rl, nl, hl = proj if nl > 0: p0, p1 = p1, p1 + nl * (l * 2 + 1) hl = numpy.asarray(hl) SPG_lm_aoG = SPG_lm_aoGs[p0:p1].reshape( nl, l * 2 + 1, -1) tmp = numpy.einsum('ij,jmp->imp', hl, SPG_lm_aoG) vppnl += numpy.einsum('imp,imq->pq', SPG_lm_aoG.conj(), tmp) return vppnl * (1. / ngrids**2) vppnl = [] for kpt in mpi.static_partition(kpts_lst): vppnl.append(vppnl_by_k(kpt)) vppnl = mpi.gather(lib.asarray(vppnl)) if rank == 0: for k in range(nkpts): if dtype == numpy.float64: vpp[k] += vppnl[k].real else: vpp[k] += vppnl[k] if kpts is None or numpy.shape(kpts) == (3, ): vpp = vpp[0] return vpp