def test_eval_rho(self): cell, grids = make_grids([61]*3) numpy.random.seed(10) nao = 10 ngrids = 500 dm = numpy.random.random((nao,nao)) dm = dm + dm.T ao =(numpy.random.random((10,ngrids,nao)) + numpy.random.random((10,ngrids,nao))*1j) ao = ao.transpose(0,2,1).copy().transpose(0,2,1) rho0 = numpy.zeros((6,ngrids), dtype=numpy.complex128) rho0[0] = numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[0].conj()) rho0[1] = numpy.einsum('pi,ij,pj->p', ao[1], dm, ao[0].conj()) + numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[1].conj()) rho0[2] = numpy.einsum('pi,ij,pj->p', ao[2], dm, ao[0].conj()) + numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[2].conj()) rho0[3] = numpy.einsum('pi,ij,pj->p', ao[3], dm, ao[0].conj()) + numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[3].conj()) rho0[4]+= numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[4].conj()) + numpy.einsum('pi,ij,pj->p', ao[4], dm, ao[0].conj()) rho0[4]+= numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[7].conj()) + numpy.einsum('pi,ij,pj->p', ao[7], dm, ao[0].conj()) rho0[4]+= numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[9].conj()) + numpy.einsum('pi,ij,pj->p', ao[9], dm, ao[0].conj()) rho0[5]+= numpy.einsum('pi,ij,pj->p', ao[1], dm, ao[1].conj()) rho0[5]+= numpy.einsum('pi,ij,pj->p', ao[2], dm, ao[2].conj()) rho0[5]+= numpy.einsum('pi,ij,pj->p', ao[3], dm, ao[3].conj()) rho0[4]+= rho0[5]*2 rho0[5] *= .5 rho1 = numint.eval_rho(cell, ao, dm, xctype='MGGA') self.assertTrue(numpy.allclose(rho0, rho1)) rho1 = numint.eval_rho(cell, ao, dm, xctype='GGA') self.assertAlmostEqual(finger(rho1), -255.45150185669198, 7) rho1 = numint.eval_rho(cell, ao[0], dm, xctype='LDA') self.assertAlmostEqual(finger(rho1), -17.198879910245601, 7)
def test_eval_rho(self): cell, grids = make_grids(30) numpy.random.seed(10) nao = 10 ngrids = 500 dm = numpy.random.random((nao,nao)) dm = dm + dm.T ao =(numpy.random.random((10,ngrids,nao)) + numpy.random.random((10,ngrids,nao))*1j) rho0 = numpy.zeros((6,ngrids), dtype=numpy.complex128) rho0[0] = numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[0].conj()) rho0[1] = numpy.einsum('pi,ij,pj->p', ao[1], dm, ao[0].conj()) + numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[1].conj()) rho0[2] = numpy.einsum('pi,ij,pj->p', ao[2], dm, ao[0].conj()) + numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[2].conj()) rho0[3] = numpy.einsum('pi,ij,pj->p', ao[3], dm, ao[0].conj()) + numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[3].conj()) rho0[4]+= numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[4].conj()) + numpy.einsum('pi,ij,pj->p', ao[4], dm, ao[0].conj()) rho0[4]+= numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[7].conj()) + numpy.einsum('pi,ij,pj->p', ao[7], dm, ao[0].conj()) rho0[4]+= numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[9].conj()) + numpy.einsum('pi,ij,pj->p', ao[9], dm, ao[0].conj()) rho0[5]+= numpy.einsum('pi,ij,pj->p', ao[1], dm, ao[1].conj()) rho0[5]+= numpy.einsum('pi,ij,pj->p', ao[2], dm, ao[2].conj()) rho0[5]+= numpy.einsum('pi,ij,pj->p', ao[3], dm, ao[3].conj()) rho0[4]+= rho0[5]*2 rho0[5] *= .5 rho1 = numint.eval_rho(cell, ao, dm, xctype='MGGA') self.assertTrue(numpy.allclose(rho0, rho1))
def get_j_kpts(mydf, dm_kpts, hermi=1, kpts=np.zeros((1, 3)), kpts_band=None): '''Get the Coulomb (J) AO matrix at sampled k-points. Args: dm_kpts : (nkpts, nao, nao) ndarray or a list of (nkpts,nao,nao) ndarray Density matrix at each k-point. If a list of k-point DMs, eg, UHF alpha and beta DM, the alpha and beta DMs are contracted separately. kpts : (nkpts, 3) ndarray Kwargs: 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 or list of vj if the input dm_kpts is a list of DMs ''' cell = mydf.cell mesh = mydf.mesh low_dim_ft_type = mydf.low_dim_ft_type dm_kpts = lib.asarray(dm_kpts, order='C') dms = _format_dms(dm_kpts, kpts) nset, nkpts, nao = dms.shape[:3] coulG = tools.get_coulG(cell, mesh=mesh, low_dim_ft_type=low_dim_ft_type) ngrids = len(coulG) vR = rhoR = np.zeros((nset, ngrids)) for ao_ks_etc, p0, p1 in mydf.aoR_loop(mydf.grids, kpts): ao_ks = ao_ks_etc[0] for k, ao in enumerate(ao_ks): for i in range(nset): rhoR[i, p0:p1] += numint.eval_rho(cell, ao, dms[i, k]) ao = ao_ks = None for i in range(nset): rhoR[i] *= 1. / nkpts rhoG = tools.fft(rhoR[i], mesh) vG = coulG * rhoG vR[i] = tools.ifft(vG, mesh).real kpts_band, input_band = _format_kpts_band(kpts_band, kpts), kpts_band nband = len(kpts_band) weight = cell.vol / ngrids vR *= weight if gamma_point(kpts_band): vj_kpts = np.zeros((nset, nband, nao, nao)) else: vj_kpts = np.zeros((nset, nband, nao, nao), dtype=np.complex128) for ao_ks_etc, p0, p1 in mydf.aoR_loop(mydf.grids, kpts_band): ao_ks = ao_ks_etc[0] for k, ao in enumerate(ao_ks): for i in range(nset): vj_kpts[i, k] += lib.dot(ao.T.conj() * vR[i, p0:p1], ao) return _format_jks(vj_kpts, dm_kpts, input_band, kpts)
def get_vjR(cell, dm, aoR): coulG = tools.get_coulG(cell) rhoR = numint.eval_rho(cell, aoR, dm) rhoG = tools.fft(rhoR, cell.gs) vG = coulG * rhoG vR = tools.ifft(vG, cell.gs) if rhoR.dtype == np.double: vR = vR.real return vR
def get_j_kpts(mydf, dm_kpts, hermi=1, kpts=np.zeros((1,3)), kpt_band=None): '''Get the Coulomb (J) AO matrix at sampled k-points. Args: dm_kpts : (nkpts, nao, nao) ndarray or a list of (nkpts,nao,nao) ndarray Density matrix at each k-point. If a list of k-point DMs, eg, UHF alpha and beta DM, the alpha and beta DMs are contracted separately. kpts : (nkpts, 3) ndarray Kwargs: kpt_band : (3,) ndarray An arbitrary "band" k-point at which to evalute the matrix. Returns: vj : (nkpts, nao, nao) ndarray or list of vj if the input dm_kpts is a list of DMs ''' cell = mydf.cell gs = mydf.gs dm_kpts = lib.asarray(dm_kpts, order='C') dms = _format_dms(dm_kpts, kpts) nset, nkpts, nao = dms.shape[:3] coulG = tools.get_coulG(cell, gs=gs) ngs = len(coulG) vR = rhoR = np.zeros((nset,ngs)) for k, aoR in mydf.aoR_loop(gs, kpts): for i in range(nset): rhoR[i] += numint.eval_rho(cell, aoR, dms[i,k]) for i in range(nset): rhoR[i] *= 1./nkpts rhoG = tools.fft(rhoR[i], gs) vG = coulG * rhoG vR[i] = tools.ifft(vG, gs).real if kpt_band is not None: for k, aoR_kband in mydf.aoR_loop(gs, kpts, kpt_band): pass vj_kpts = [cell.vol/ngs * lib.dot(aoR_kband.T.conj()*vR[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 = [] weight = cell.vol / ngs for k, aoR in mydf.aoR_loop(gs, kpts): for i in range(nset): vj_kpts.append(weight * lib.dot(aoR.T.conj()*vR[i], aoR)) vj_kpts = lib.asarray(vj_kpts).reshape(nkpts,nset,nao,nao) return vj_kpts.transpose(1,0,2,3).reshape(dm_kpts.shape)
def get_vjR(cell, dm, aoR): coulG = tools.get_coulG(cell) rhoR = numint.eval_rho(cell, aoR, dm) rhoG = tools.fft(rhoR, cell.gs) vG = coulG*rhoG vR = tools.ifft(vG, cell.gs) if rhoR.dtype == np.double: vR = vR.real return vR
def get_j_kpts(mydf, dm_kpts, hermi=1, kpts=np.zeros((1, 3)), kpt_band=None): """Get the Coulomb (J) AO matrix at sampled k-points. Args: dm_kpts : (nkpts, nao, nao) ndarray or a list of (nkpts,nao,nao) ndarray Density matrix at each k-point. If a list of k-point DMs, eg, UHF alpha and beta DM, the alpha and beta DMs are contracted separately. kpts : (nkpts, 3) ndarray Kwargs: kpt_band : (3,) ndarray An arbitrary "band" k-point at which to evalute the matrix. Returns: vj : (nkpts, nao, nao) ndarray or list of vj if the input dm_kpts is a list of DMs """ cell = mydf.cell gs = mydf.gs dm_kpts = lib.asarray(dm_kpts, order="C") dms = _format_dms(dm_kpts, kpts) nset, nkpts, nao = dms.shape[:3] coulG = tools.get_coulG(cell, gs=gs) ngs = len(coulG) vR = rhoR = np.zeros((nset, ngs)) for k, aoR in mydf.aoR_loop(gs, kpts): for i in range(nset): rhoR[i] += numint.eval_rho(cell, aoR, dms[i, k]) for i in range(nset): rhoR[i] *= 1.0 / nkpts rhoG = tools.fft(rhoR[i], gs) vG = coulG * rhoG vR[i] = tools.ifft(vG, gs).real if kpt_band is not None: for k, aoR_kband in mydf.aoR_loop(gs, kpts, kpt_band): pass vj_kpts = [cell.vol / ngs * lib.dot(aoR_kband.T.conj() * vR[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 = [] weight = cell.vol / ngs for k, aoR in mydf.aoR_loop(gs, kpts): for i in range(nset): vj_kpts.append(weight * lib.dot(aoR.T.conj() * vR[i], aoR)) vj_kpts = lib.asarray(vj_kpts).reshape(nkpts, nset, nao, nao) return vj_kpts.transpose(1, 0, 2, 3).reshape(dm_kpts.shape)
def density(cell, outfile, dm, nx=60, ny=60, nz=60, moN=-1, fileFormat="cube"): '''Calculates electron density and write out in CHGCAR format. Args: cell : Cell pbc Cell outfile : str Name of Cube file to be written. dm : ndarray Density matrix of molecule. Kwargs: nx : int Number of grid point divisions in x direction. Note this is function of the molecule's size; a larger molecule will have a coarser representation than a smaller one for the same value. ny : int Number of grid point divisions in y direction. nz : int Number of grid point divisions in z direction. Returns: No return value. This function outputs a VASP chgcarlike file (with phase if desired)...it can be opened in VESTA or VMD or many other softwares Examples: >>> # generates the first MO from the list of mo_coefficents >>> from pyscf.pbc import gto, scf >>> from pyscf.tools import chgcar >>> cell = gto.M(atom='H 0 0 0; H 0 0 1', a=numpy.eye(3)*3) >>> mf = scf.RHF(cell).run() >>> chgcar.density(cell, 'h2.CHGCAR', mf.make_rdm1()) ''' assert (isinstance(cell, pbcgto.Cell)) cc = CHGCAR(cell, nx=nx, ny=ny, nz=nz) coords = cc.get_coords() ngrids = cc.get_ngrids() blksize = min(8000, ngrids) rho = numpy.empty(ngrids) for ip0, ip1 in lib.prange(0, ngrids, blksize): ao = numint.eval_ao(cell, coords[ip0:ip1]) rho[ip0:ip1] = numint.eval_rho(cell, ao, dm) rho = rho.reshape(nx, ny, nz) cc.write(rho, outfile)
def get_j_kpts(mydf, dm_kpts, hermi=1, kpts=np.zeros((1, 3)), kpts_band=None): '''Get the Coulomb (J) AO matrix at sampled k-points. Args: dm_kpts : (nkpts, nao, nao) ndarray or a list of (nkpts,nao,nao) ndarray Density matrix at each k-point. If a list of k-point DMs, eg, UHF alpha and beta DM, the alpha and beta DMs are contracted separately. kpts : (nkpts, 3) ndarray Kwargs: 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 or list of vj if the input dm_kpts is a list of DMs ''' cell = mydf.cell gs = mydf.gs dm_kpts = lib.asarray(dm_kpts, order='C') dms = _format_dms(dm_kpts, kpts) nset, nkpts, nao = dms.shape[:3] coulG = tools.get_coulG(cell, gs=gs) ngs = len(coulG) vR = rhoR = np.zeros((nset, ngs)) for k, aoR in mydf.aoR_loop(gs, kpts): for i in range(nset): rhoR[i] += numint.eval_rho(cell, aoR, dms[i, k]) for i in range(nset): rhoR[i] *= 1. / nkpts rhoG = tools.fft(rhoR[i], gs) vG = coulG * rhoG vR[i] = tools.ifft(vG, gs).real kpts_band, single_kpt_band = _format_kpts_band(kpts_band, kpts) nband = len(kpts_band) vj_kpts = [] weight = cell.vol / ngs if gamma_point(kpts_band): vj_kpts = np.empty((nset, nband, nao, nao)) else: vj_kpts = np.empty((nset, nband, nao, nao), dtype=np.complex128) for k, aoR in mydf.aoR_loop(gs, kpts_band): for i in range(nset): vj_kpts[i, k] = weight * lib.dot(aoR.T.conj() * vR[i], aoR) return _format_jks(vj_kpts, dm_kpts, kpts_band, kpts, single_kpt_band)
def get_vjR_kpts(cell, dm_kpts, aoR_kpts): nkpts = len(aoR_kpts) coulG = tools.get_coulG(cell) rhoR = 0 for k in range(nkpts): rhoR += 1. / nkpts * numint.eval_rho(cell, aoR_kpts[k], dm_kpts[k]) rhoG = tools.fft(rhoR, cell.gs) vG = coulG * rhoG vR = tools.ifft(vG, cell.gs) if rhoR.dtype == np.double: vR = vR.real return vR
def get_vjR_kpts(cell, dm_kpts, aoR_kpts): nkpts = len(aoR_kpts) coulG = tools.get_coulG(cell) rhoR = 0 for k in range(nkpts): rhoR += 1./nkpts*numint.eval_rho(cell, aoR_kpts[k], dm_kpts[k]) rhoG = tools.fft(rhoR, cell.gs) vG = coulG*rhoG vR = tools.ifft(vG, cell.gs) if rhoR.dtype == np.double: vR = vR.real return vR
def get_j_kpts(mydf, dm_kpts, hermi=1, kpts=numpy.zeros((1,3)), kpts_band=None): mydf = _sync_mydf(mydf) cell = mydf.cell mesh = mydf.mesh dm_kpts = lib.asarray(dm_kpts, order='C') dms = _format_dms(dm_kpts, kpts) nset, nkpts, nao = dms.shape[:3] coulG = tools.get_coulG(cell, mesh=mesh) ngrids = len(coulG) vR = rhoR = numpy.zeros((nset,ngrids)) for ao_ks_etc, p0, p1 in mydf.mpi_aoR_loop(mydf.grids, kpts): ao_ks = ao_ks_etc[0] for k, ao in enumerate(ao_ks): for i in range(nset): rhoR[i,p0:p1] += numint.eval_rho(cell, ao, dms[i,k]) ao = ao_ks = None rhoR = mpi.allreduce(rhoR) for i in range(nset): rhoR[i] *= 1./nkpts rhoG = tools.fft(rhoR[i], mesh) vG = coulG * rhoG vR[i] = tools.ifft(vG, mesh).real kpts_band, input_band = _format_kpts_band(kpts_band, kpts), kpts_band nband = len(kpts_band) weight = cell.vol / ngrids vR *= weight if gamma_point(kpts_band): vj_kpts = numpy.zeros((nset,nband,nao,nao)) else: vj_kpts = numpy.zeros((nset,nband,nao,nao), dtype=numpy.complex128) for ao_ks_etc, p0, p1 in mydf.mpi_aoR_loop(mydf.grids, kpts_band): ao_ks = ao_ks_etc[0] for k, ao in enumerate(ao_ks): for i in range(nset): vj_kpts[i,k] += lib.dot(ao.T.conj()*vR[i,p0:p1], ao) vj_kpts = mpi.reduce(vj_kpts) if gamma_point(kpts_band): vj_kpts = vj_kpts.real return _format_jks(vj_kpts, dm_kpts, input_band, kpts)
def test_eval_rho(self): cell, grids = make_grids(30) numpy.random.seed(10) nao = 10 ngrids = 500 dm = numpy.random.random((nao, nao)) dm = dm + dm.T ao = (numpy.random.random((10, ngrids, nao)) + numpy.random.random( (10, ngrids, nao)) * 1j) rho0 = numpy.zeros((6, ngrids), dtype=numpy.complex128) rho0[0] = numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[0].conj()) rho0[1] = numpy.einsum('pi,ij,pj->p', ao[1], dm, ao[0].conj()) + numpy.einsum( 'pi,ij,pj->p', ao[0], dm, ao[1].conj()) rho0[2] = numpy.einsum('pi,ij,pj->p', ao[2], dm, ao[0].conj()) + numpy.einsum( 'pi,ij,pj->p', ao[0], dm, ao[2].conj()) rho0[3] = numpy.einsum('pi,ij,pj->p', ao[3], dm, ao[0].conj()) + numpy.einsum( 'pi,ij,pj->p', ao[0], dm, ao[3].conj()) rho0[4] += numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[4].conj()) + numpy.einsum( 'pi,ij,pj->p', ao[4], dm, ao[0].conj()) rho0[4] += numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[7].conj()) + numpy.einsum( 'pi,ij,pj->p', ao[7], dm, ao[0].conj()) rho0[4] += numpy.einsum('pi,ij,pj->p', ao[0], dm, ao[9].conj()) + numpy.einsum( 'pi,ij,pj->p', ao[9], dm, ao[0].conj()) rho0[5] += numpy.einsum('pi,ij,pj->p', ao[1], dm, ao[1].conj()) rho0[5] += numpy.einsum('pi,ij,pj->p', ao[2], dm, ao[2].conj()) rho0[5] += numpy.einsum('pi,ij,pj->p', ao[3], dm, ao[3].conj()) rho0[4] += rho0[5] * 2 rho0[5] *= .5 rho1 = numint.eval_rho(cell, ao, dm, xctype='MGGA') self.assertTrue(numpy.allclose(rho0, rho1))
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 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 _eval_rhoG(mydf, dm_kpts, hermi=1, kpts=numpy.zeros((1, 3)), deriv=0): log = lib.logger.Logger(mydf.stdout, mydf.verbose) cell = mydf.cell dm_kpts = lib.asarray(dm_kpts, order='C') dms = _format_dms(dm_kpts, kpts) nset, nkpts, nao = dms.shape[:3] tasks = getattr(mydf, 'tasks', None) if tasks is None: mydf.tasks = tasks = multi_grids_tasks(cell, log) log.debug('Multigrid ntasks %s', len(tasks)) assert (deriv <= 2) if abs(dms - dms.transpose(0, 1, 3, 2).conj()).max() < 1e-9: def dot_bra(bra, aodm): rho = numpy.einsum('pi,pi->p', bra.real, aodm.real) if aodm.dtype == numpy.complex: rho += numpy.einsum('pi,pi->p', bra.imag, aodm.imag) return rho if deriv == 0: xctype = 'LDA' rhodim = 1 def make_rho(ao_l, ao_h, dm_lh, dm_hl): c0 = lib.dot(ao_l, dm_lh) rho = dot_bra(ao_h, c0) return rho * 2 elif deriv == 1: xctype = 'GGA' rhodim = 4 def make_rho(ao_l, ao_h, dm_lh, dm_hl): ngrids = ao_l[0].shape[0] rho = numpy.empty((4, ngrids)) c0 = lib.dot(ao_l[0], dm_lh) rho[0] = dot_bra(ao_h[0], c0) for i in range(1, 4): rho[i] = dot_bra(ao_h[i], c0) c0 = lib.dot(ao_h[0], dm_hl) for i in range(1, 4): rho[i] += dot_bra(ao_l[i], c0) return rho * 2 # *2 for dm_lh+dm_hl.T elif deriv == 2: xctype = 'MGGA' rhodim = 6 def make_rho(ao_l, ao_h, dm_lh, dm_hl): ngrids = ao_l[0].shape[0] rho = numpy.empty((6, ngrids)) c = [lib.dot(ao_l[i], dm_lh) for i in range(4)] rho[0] = dot_bra(ao_h[0], c[0]) rho[5] = 0 for i in range(1, 4): rho[i] = dot_bra(ao_h[i], c[0]) rho[i] += dot_bra(ao_h[0], c[i]) rho[5] += dot_bra(ao_h[i], c[i]) * 2 XX, YY, ZZ = 4, 7, 9 ao2 = ao_h[XX] + ao_h[YY] + ao_h[ZZ] rho[4] = dot_bra(ao2, c[0]) ao2 = lib.dot(ao_l[XX] + ao_l[YY] + ao_l[ZZ], dm_lh) rho[4] += dot_bra(ao2, ao_h[0]) rho[4] += rho[5] * 2 rho[5] *= .5 return rho * 2 # *2 for dm_lh+dm_hl.T else: raise NotImplementedError('Non-hermitian density matrices') ni = mydf._numint nx, ny, nz = cell.mesh rhoG = numpy.zeros((nset * rhodim, nx, ny, nz), dtype=numpy.complex) for grids_high, grids_low in tasks: cell_high = grids_high.cell mesh = grids_high.mesh coords_idx = grids_high.coords_idx ngrids0 = numpy.prod(mesh) ngrids1 = grids_high.coords.shape[0] log.debug('mesh %s, ngrids %s/%s', mesh, ngrids1, ngrids0) idx_h = grids_high.ao_idx dms_hh = numpy.asarray(dms[:, :, idx_h[:, None], idx_h], order='C') if grids_low is not None: idx_l = grids_low.ao_idx dms_hl = numpy.asarray(dms[:, :, idx_h[:, None], idx_l], order='C') dms_lh = numpy.asarray(dms[:, :, idx_l[:, None], idx_h], order='C') rho = numpy.zeros((nset, rhodim, ngrids1)) if grids_low is None: for ao_h_etc, p0, p1 in mydf.aoR_loop(grids_high, kpts, deriv): ao_h, mask = ao_h_etc[0], ao_h_etc[2] for k in range(nkpts): for i in range(nset): rho_sub = numint.eval_rho(cell_high, ao_h[k], dms_hh[i, k], mask, xctype, hermi) rho[i, :, p0:p1] += rho_sub.real ao_h = ao_h_etc = None else: for ao_h_etc, ao_l_etc in zip( mydf.aoR_loop(grids_high, kpts, deriv), mydf.aoR_loop(grids_low, kpts, deriv)): p0, p1 = ao_h_etc[1:3] ao_h, mask = ao_h_etc[0][0], ao_h_etc[0][2] ao_l = ao_l_etc[0][0] for k in range(nkpts): for i in range(nset): rho_sub = numint.eval_rho(cell_high, ao_h[k], dms_hh[i, k], mask, xctype, hermi) rho[i, :, p0:p1] += rho_sub.real rho_sub = make_rho(ao_l[k], ao_h[k], dms_lh[i, k], dms_hl[i, k]) rho[i, :, p0:p1] += rho_sub.real ao_h = ao_l = ao_h_etc = ao_l_etc = None rho *= 1. / nkpts rhoR = numpy.zeros((nset * rhodim, ngrids0)) rhoR[:, coords_idx] = rho.reshape(nset * rhodim, ngrids1) gx = numpy.fft.fftfreq(mesh[0], 1. / mesh[0]).astype(int) gy = numpy.fft.fftfreq(mesh[1], 1. / mesh[1]).astype(int) gz = numpy.fft.fftfreq(mesh[2], 1. / mesh[2]).astype(int) rho_freq = tools.fft(rhoR, mesh) * cell.vol / ngrids0 for i in range(nset * rhodim): rhoG[i, gx[:, None, None], gy[:, None], gz] += rho_freq[i].reshape(mesh) return rhoG.reshape(nset, rhodim, ngrids0)