def get_veff_elec_epc(self, mol, dm, dm_last=None, vhf_last=None, hermi=1): '''Add EPC contribution to electronic veff''' nao = mol.nao_nr() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() vmat = numpy.zeros((nao, nao)) grids = self.mf_elec.grids ni = self.mf_elec._numint aow = None for i in range(self.mol.nuc_num): ia = self.mol.nuc[i].atom_index if self.mol.atom_symbol(ia) == 'H': for ao, mask, weight, coords in ni.block_loop(mol, grids, nao): aow = numpy.ndarray(ao.shape, order='F', buffer=aow) ao_elec = eval_ao(mol, coords) if dm.ndim > 2: rho_elec = eval_rho(mol, ao_elec, dm[0] + dm[1]) else: rho_elec = eval_rho(mol, ao_elec, dm) ao_nuc = eval_ao(self.mol.nuc[i], coords) rho_nuc = eval_rho(self.mol.nuc[i], ao_nuc, self.dm_nuc[i]) vxc_i = eval_xc_elec(self.epc, rho_elec, rho_nuc) # times 0.5 because vmat + vmat.T aow = _scale_ao(ao_elec, 0.5 * weight * vxc_i, out=aow) vmat += _dot_ao_ao(mol, ao_elec, aow, mask, shls_slice, ao_loc) vmat += vmat.conj().T if dm.ndim > 2: veff = dft.uks.get_veff(self.mf_elec, mol, dm, dm_last, vhf_last, hermi) else: veff = dft.rks.get_veff(self.mf_elec, mol, dm, dm_last, vhf_last, hermi) vxc = lib.tag_array(veff + vmat, ecoul=veff.ecoul, exc=veff.exc, vj=veff.vj, vk=veff.vk) return vxc
def get_veff_nuc_epc(self, mol, dm, dm_last=None, vhf_last=None, hermi=1): '''Add EPC contribution to nuclear veff''' nao = mol.nao_nr() shls_slice = (0, mol.nbas) ao_loc = mol.ao_loc_nr() nnuc = 0 excsum = 0 vmat = numpy.zeros((nao, nao)) grids = self.mf_elec.grids ni = self.mf_elec._numint aow = None for ao, mask, weight, coords in ni.block_loop(mol, grids, nao): aow = numpy.ndarray(ao.shape, order='F', buffer=aow) ao_elec = eval_ao(self.mol.elec, coords) if self.dm_elec.ndim > 2: rho_elec = eval_rho(self.mol.elec, ao_elec, self.dm_elec[0] + self.dm_elec[1]) else: rho_elec = eval_rho(self.mol.elec, ao_elec, self.dm_elec) ao_nuc = eval_ao(mol, coords) rho_nuc = eval_rho(mol, ao_nuc, dm) exc, vxc = eval_xc_nuc(self.epc, rho_elec, rho_nuc) den = rho_nuc * weight nnuc += den.sum() excsum += numpy.dot(den, exc) # times 0.5 because vmat + vmat.T aow = _scale_ao(ao_nuc, 0.5 * weight * vxc, out=aow) vmat += _dot_ao_ao(mol, ao_nuc, aow, mask, shls_slice, ao_loc) logger.debug(self, 'The number of nuclei: %.5f', nnuc) vmat += vmat.conj().T # attach E_ep to vmat to retrieve later vmat = lib.tag_array(vmat, exc=excsum, ecoul=0, vj=0, vk=0) return vmat
def compute_nad_terms(mol0, mol1, dm0, dm1, emb_args): """Compute the non-additive potentials and energies. Parameters ---------- mol : PySCF gto.M Molecule objects. emb_args : dict Information of embedding calculation. """ # Create supersystem newatom = '\n'.join([mol0.atom, mol1.atom]) system = gto.M(atom=newatom, basis=mol0.basis) # Construct grid for complex grids = gen_grid.Grids(system) grids.level = 4 grids.build() ao_mol0 = eval_ao(mol0, grids.coords, deriv=0) ao_mol1 = eval_ao(mol1, grids.coords, deriv=0) # Make Complex DM ao_both = eval_ao(system, grids.coords, deriv=0) nao_mol0 = mol0.nao_nr() nao_mol1 = mol1.nao_nr() nao_tot = nao_mol0 + nao_mol1 dm_both = np.zeros((nao_tot, nao_tot)) dm_both[:nao_mol0, :nao_mol0] = dm0 dm_both[nao_mol0:, nao_mol0:] = dm1 # Compute DFT non-additive potential and energies rho_mol0 = eval_rho(mol0, ao_mol0, dm0, xctype='LDA') rho_mol1 = eval_rho(mol1, ao_mol1, dm1, xctype='LDA') rho_both = eval_rho(system, ao_both, dm_both, xctype='LDA') # Compute all densities on a grid xc_code = emb_args["xc_code"] t_code = emb_args["t_code"] excs, vxcs = get_dft_grid_stuff(xc_code, rho_both, rho_mol0, rho_mol1) ets, vts = get_dft_grid_stuff(t_code, rho_both, rho_mol0, rho_mol1) vxc_emb = vxcs[0][0] - vxcs[1][0] vt_emb = vts[0][0] - vts[1][0] # Energy functionals: exc_nad = get_nad_energy(grids, excs, rho_both, rho_mol0, rho_mol1) et_nad = get_nad_energy(grids, ets, rho_both, rho_mol0, rho_mol1) v_nad_xc = eval_mat(mol0, ao_mol0, grids.weights, rho_mol0, vxc_emb, xctype='LDA') v_nad_t = eval_mat(mol0, ao_mol0, grids.weights, rho_mol0, vt_emb, xctype='LDA') return (exc_nad, et_nad, v_nad_xc, v_nad_t)
def density_cut(mol, dm, nx=80, ny=80, z_value=0): from scipy.constants import physical_constants from pyscf import lib from pyscf.dft import gen_grid, numint nz = 1 coord = mol.atom_coords() box = np.max(coord,axis=0) - np.min(coord,axis=0) + 6 boxorig = np.min(coord,axis=0) - 3 xs = np.arange(nx) * (box[0]/nx) ys = np.arange(ny) * (box[1]/ny) zs = np.array([z_value]) #zs = np.arange(nz) * (box[2]/nz) coords = lib.cartesian_prod([xs,ys,zs]) coords = np.asarray(coords, order='C') - (-boxorig) ngrids = nx * ny * nz blksize = min(8000, ngrids) rho = np.empty(ngrids) ao = None for ip0, ip1 in gen_grid.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1], out=ao) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(nx,ny) # needed for conversion as x,y are in bohr for some reason a0 = physical_constants["Bohr radius"][0] return rho.T, (xs + boxorig[0]) * a0, (ys + boxorig[1]) * a0
def density_cut_old(mol, dm, nx=80, ny=80): """ Calculates the density in the x-y plane on a grid""" from pyscf import lib from pyscf.dft import gen_grid, numint coords = mol.atom_coords() coords[:, 2] = 0 # set z-coordinate 0 lower = np.min(coords, axis=0) upper = np.max(coords, axis=0) grid_x, grid_y = np.meshgrid( np.linspace(lower[0], upper[0], nx), np.linspace(lower[1], upper[1], ny) ) grid = np.array( [grid_x.flatten(), grid_y[:].flatten(), np.zeros(grid_x.shape).flatten()] ).T ao = numint.eval_ao(mol, grid) rho = numint.eval_rho(mol, ao, dm) return rho.reshape(nx, ny)
def test_mcol_mgga_vxc_mat(self): nao = mol.nao n2c = nao * 2 ao_loc = mol.ao_loc numpy.random.seed(12) dm = numpy.random.rand(n2c, n2c) * .01 dm += numpy.eye(n2c) dm = dm + dm.T ngrids = 8 coords = numpy.random.rand(ngrids, 3) weight = numpy.random.rand(ngrids) ao = numint.eval_ao(mol, coords, deriv=1) rho = numint2c.eval_rho(mol, ao, dm, xctype='MGGA', hermi=1, with_lapl=False) vxc = numpy.random.rand(4, 5, ngrids) mask = numpy.ones((100, mol.nbas), dtype=numpy.uint8) shls_slice = (0, mol.nbas) v0 = numint2c._mcol_mgga_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 0) v1 = numint2c._mcol_mgga_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 1) v1 = v1 + v1.conj().T self.assertAlmostEqual(abs(v0 - v1).max(), 0, 14) self.assertAlmostEqual(lib.fp(v0), 0.45641500123185696 - 0.11533144122332428j, 12)
def test_mcol_gga_vxc_mat(self): nao = mol.nao n2c = nao * 2 ao_loc = mol.ao_loc numpy.random.seed(12) dm = numpy.random.rand(n2c, n2c) * .01 dm += numpy.eye(n2c) dm = dm + dm.T ngrids = 8 coords = numpy.random.rand(ngrids, 3) weight = numpy.random.rand(ngrids) ao = numint.eval_ao(mol, coords, deriv=1) rho = numint2c.eval_rho(mol, ao, dm, xctype='GGA', hermi=1) vxc = numpy.random.rand(4, 4, ngrids) mask = numpy.ones((100, mol.nbas), dtype=numpy.uint8) shls_slice = (0, mol.nbas) v0 = numint2c._mcol_gga_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 0) v1 = numint2c._mcol_gga_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 1) v1 = v1 + v1.conj().T self.assertAlmostEqual(abs(v0 - v1).max(), 0, 14) self.assertAlmostEqual(lib.fp(v0), -0.889763561992794 - 0.013552640219244905j, 12)
def fo(mf, fod, s=0): """docstring for fo""" ksocc = np.where(mf.mo_occ[s] > 1e-6)[0][-1] + 1 #print("ksocc: {0}".format(ksocc)) #print np.where(self.mf.mo_occ[self.s] > 1e-6) mol = mf.mol ao = numint.eval_ao(mol, [fod]) # first index is nfod, second is orbital psi = ao.dot(mf.mo_coeff[s][:, :ksocc]) #print psi.shape #sys.exit() # get total spin density at point self.fpos sd = np.sqrt(np.sum(psi**2, axis=1)) #print sd.shape #print sd #sys.exit() # get value of each ks-orbital at point fpos _ks = mf.mo_coeff[s][:, 0:ksocc] #print _ks.shape #sys.exit() #print np.array_str(_ks, precision=4, max_line_width=120) _R = np.zeros((ksocc), dtype=_ks.dtype) _R = psi[0, :] / sd #_R = np.reshape(psi/sd, (ksocc)) fo = np.matmul(_R, _ks.transpose()) #print fo return fo
def density(mol, outfile, dm, nx=80, ny=80, nz=80): coord = mol.atom_coords() box = numpy.max(coord, axis=0) - numpy.min(coord, axis=0) + 4 boxorig = numpy.min(coord, axis=0) - 2 xs = numpy.arange(nx) * (box[0] / nx) ys = numpy.arange(ny) * (box[1] / ny) zs = numpy.arange(nz) * (box[2] / nz) coords = lib.cartesian_prod([xs, ys, zs]) coords = numpy.asarray(coords, order="C") - (-boxorig) nao = mol.nao_nr() ngrids = nx * ny * nz blksize = min(200, ngrids) rho = numpy.empty(ngrids) for ip0, ip1 in gen_grid.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(nx, ny, nz) with open(outfile, "w") as f: f.write("Density in real space\n") f.write("Comment line\n") f.write("%5d" % mol.natm) f.write(" %14.8f %14.8f %14.8f\n" % tuple(boxorig.tolist())) f.write("%5d %14.8f %14.8f %14.8f\n" % (nx, xs[1], 0, 0)) f.write("%5d %14.8f %14.8f %14.8f\n" % (ny, 0, ys[1], 0)) f.write("%5d %14.8f %14.8f %14.8f\n" % (nz, 0, 0, zs[1])) for ia in range(mol.natm): chg = mol.atom_charge(ia) f.write("%5d %f" % (chg, chg)) f.write(" %14.8f %14.8f %14.8f\n" % tuple(coord[ia])) fmt = " %14.8e" * nz + "\n" for ix in range(nx): for iy in range(ny): f.write(fmt % tuple(rho[ix, iy].tolist()))
def density(mol, outfile, dm, nx=80, ny=80, nz=80): coord = [mol.atom_coord(ia) for ia in range(mol.natm)] box = numpy.max(coord,axis=0) - numpy.min(coord,axis=0) + 4 boxorig = numpy.min(coord,axis=0) - 2 xs = numpy.arange(nx) * (box[0]/nx) ys = numpy.arange(ny) * (box[1]/ny) zs = numpy.arange(nz) * (box[2]/nz) coords = numpy.vstack(numpy.meshgrid(xs,ys,zs)).reshape(3,-1).T coords = numpy.asarray(coords, order='C') - (-boxorig) nao = mol.nao_nr() ngrids = nx * ny * nz blksize = min(200, ngrids) rho = numpy.empty(ngrids) for ip0, ip1 in numint.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(nx,ny,nz) with open(outfile, 'w') as f: f.write('Density in real space\n') f.write('Comment line\n') f.write('%5d' % mol.natm) f.write(' %14.8f %14.8f %14.8f\n' % tuple(boxorig.tolist())) f.write('%5d %14.8f %14.8f %14.8f\n' % (nx, xs[1], 0, 0)) f.write('%5d %14.8f %14.8f %14.8f\n' % (ny, 0, ys[1], 0)) f.write('%5d %14.8f %14.8f %14.8f\n' % (nz, 0, 0, zs[1])) for ia in range(mol.natm): chg = mol.atom_charge(ia) f.write('%5d %f' % (chg, chg)) f.write(' %14.8f %14.8f %14.8f\n' % tuple(mol.atom_coord(ia).tolist())) fmt = ' %14.8f' * nz + '\n' for ix in range(nx): for iy in range(ny): f.write(fmt % tuple(rho[ix,iy].tolist()))
def MO(mol, C, orbital, outfile='orbital', nx=80, ny=80, nz=80, resolution=None, save=True): """Calculates electron density and write out in cube format. Args: mol : Mole Molecule to calculate the electron density for. 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. Conflicts to keyword resolution. ny : int Number of grid point divisions in y direction. nz : int Number of grid point divisions in z direction. resolution: float Resolution of the mesh grid in the cube box. If resolution is given in the input, the input nx/ny/nz have no effects. The value of nx/ny/nz will be determined by the resolution and the cube box size. """ cc = Cube(mol, nx, ny, nz, resolution) # Compute density on the .cube grid coords = cc.get_coords() ngrids = cc.get_ngrids() #blksize = min(8000, ngrids) blksize = ngrids rho = np.empty(ngrids) for ip0, ip1 in lib.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) MO = np.array([i @ C[:, orbital] for i in ao]) MO = MO.reshape((nx, ny, nz)) if save: cc.write(MO, outfile, comment='Orbital ' + str(orbital) + ' in real space (e/Bohr^3)') x = (coords[:, 0].min(), coords[:, 0].max(), nx) y = (coords[:, 1].min(), coords[:, 1].max(), ny) z = (coords[:, 2].min(), coords[:, 2].max(), nz) return MO, np.array([y, x, z])
def make_h1_fc(mol, mo_coeff, mo_occ, atmlst): coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) mo = ao.dot(mo_coeff) orbo = mo[:,mo_occ> 0] orbv = mo[:,mo_occ==0] fac = 8*numpy.pi/3 *.5 # *.5 due to s = 1/2 * pauli-matrix h1 = [] for ia in atmlst: h1.append(fac * numpy.einsum('p,i->pi', orbv[ia], orbo[ia])) return h1
def make_h1_fc(mol, mo_coeff, mo_occ, atmlst): coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) mo = ao.dot(mo_coeff) orbo = mo[:, mo_occ > 0] orbv = mo[:, mo_occ == 0] fac = 8 * numpy.pi / 3 * .5 # *.5 due to s = 1/2 * pauli-matrix h1 = [] for ia in atmlst: h1.append(fac * numpy.einsum('p,i->pi', orbv[ia], orbo[ia])) return h1
def dia(gobj, mol, dm0, hfc_nuc=None, verbose=None): log = logger.new_logger(gobj, verbose) if hfc_nuc is None: hfc_nuc = range(mol.natm) if isinstance(dm0, numpy.ndarray) and dm0.ndim == 2: # RHF DM return numpy.zeros((3, 3)) dma, dmb = dm0 spindm = dma - dmb effspin = mol.spin * .5 mu_B = 1 # lib.param.BOHR_MAGNETON mu_N = lib.param.PROTON_MASS * mu_B fac = lib.param.ALPHA / 2 / effspin fac *= lib.param.G_ELECTRON * mu_B * mu_N coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) nao = dma.shape[0] dia = [] for i, atm_id in enumerate(hfc_nuc): Z = mole._charge(mol.atom_symbol(atm_id)) nuc_spin, g_nuc = parameters.ISOTOPE[Z][1:3] # g factor of other isotopes can be found in file nuclear_g_factor.dat gyromag = 1e-6 / ( 2 * numpy.pi) * parameters.g_factor_to_gyromagnetic_ratio(g_nuc) log.info( 'Atom %d %s nuc-spin %g nuc-g-factor %g gyromagnetic ratio %g (in MHz)', atm_id, mol.atom_symbol(atm_id), nuc_spin, g_nuc, gyromag) mol.set_rinv_origin(mol.atom_coord(atm_id)) # a01p[mu,sigma] the imaginary part of integral <vec{r}/r^3 cross p> # mu = gN * I * mu_N a01p = mol.intor('int1e_sa01sp', 12).reshape(3, 4, nao, nao) h11 = a01p[:, 1:] - a01p[:, 1:].transpose(0, 1, 3, 2) e11 = numpy.einsum('xyij,ji->xy', h11, spindm) e11 *= fac * gyromag # e11 includes fermi-contact and spin-dipolar contriutions and a rank-2 contact # term. We ignore the contribution of rank-2 contact term, view it as part of # SD contribution. See also TCA, 73, 173 fermi_contact = ( 4 * numpy.pi / 3 * fac * gyromag * numpy.einsum('i,j,ji', ao[atm_id], ao[atm_id], spindm)) dip = e11 - numpy.eye(3) * fermi_contact log.info('FC %s', fermi_contact) if gobj.verbose >= logger.INFO: _write(gobj, dip, 'SD') dia.append(e11) return numpy.asarray(dia)
def densdiff(x0): #print ig_fod #print(s) _x = np.reshape(x0, (-1, 3)) lfo = fo(mf, _x, s) mol = mf.mol ao1 = numint.eval_ao(mol, ongrid.coords) _fo = ao1.dot(lfo) dens_fo = np.conjugate(_fo) * _fo * ongrid.weights ##print dens_fo.shape ##print dens.shape diff = np.linalg.norm(dens_fo - dens) return diff
def fock_hook(self, mf, dm=None, h1e=None, vhf=None, cycle=-1, **envs): # cycle > 0 means it is doing scf iteration if 0 <= cycle < self.start_cycle: return 0 if self.grids.coords is None: self.grids.build() if self.ao_value is None: self.ao_value = numint.eval_ao(mf.mol, self.grids.coords, deriv=0) tic = (time.clock(), time.time()) rho_diff = numint.eval_rho(mf.mol, self.ao_value, dm - self.dm_t) v_p = numint.eval_mat(mf.mol, self.ao_value, self.grids.weights, rho_diff, rho_diff) # cycle < 0 means it is just checking, we only print here if cycle < 0 and mf.verbose >= 4: diff_norm = np.sum(np.abs(rho_diff) * self.grids.weights) logger.info(mf, f" Density Penalty: |diff| = {diff_norm}") logger.timer(mf, "dens_pnt", *tic) return self.strength * v_p
def orbital(mol, outfile, coeff, nx=80, ny=80, nz=80, resolution=RESOLUTION): """Calculate orbital value on real space grid and write out in cube format. Args: mol : Mole Molecule to calculate the electron density for. outfile : str Name of Cube file to be written. coeff : 1D array coeff coefficient. 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. Conflicts to keyword resolution. ny : int Number of grid point divisions in y direction. nz : int Number of grid point divisions in z direction. resolution: float Resolution of the mesh grid in the cube box. If resolution is given in the input, the input nx/ny/nz have no effects. The value of nx/ny/nz will be determined by the resolution and the cube box size. """ cc = Cube(mol, nx, ny, nz, resolution) # Compute density on the .cube grid coords = cc.get_coords() ngrids = cc.get_ngrids() blksize = min(8000, ngrids) orb_on_grid = numpy.empty(ngrids) for ip0, ip1 in lib.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) orb_on_grid[ip0:ip1] = numpy.dot(ao, coeff) orb_on_grid = orb_on_grid.reshape(cc.nx, cc.ny, cc.nz) # Write out orbital to the .cube file cc.write(orb_on_grid, outfile, comment='Orbital value in real space (1/Bohr^3)') return orb_on_grid
def make_h1_fc(mol, mo_coeff, mo_occ, atmlst): coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) moa = ao.dot(mo_coeff[0]) mob = ao.dot(mo_coeff[1]) orboa = moa[:,mo_occ[0]> 0] orbva = moa[:,mo_occ[0]==0] orbob = mob[:,mo_occ[1]> 0] orbvb = mob[:,mo_occ[1]==0] h1aa = [] h1ab = [] h1ba = [] h1bb = [] fac = 8*numpy.pi/3 *.5 # *.5 due to s = 1/2 * pauli-matrix h1aa = fac * numpy.einsum('zp,zi->zpi', orbva[atmlst], orboa[atmlst]) h1ab = fac * numpy.einsum('zp,zi->zpi', orbva[atmlst], orbob[atmlst]) h1ba = fac * numpy.einsum('zp,zi->zpi', orbvb[atmlst], orboa[atmlst]) h1bb =-fac * numpy.einsum('zp,zi->zpi', orbvb[atmlst], orbob[atmlst]) return h1aa, h1ab, h1ba, h1bb
def make_h1_fc(mol, mo_coeff, mo_occ, atmlst): coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) moa = ao.dot(mo_coeff[0]) mob = ao.dot(mo_coeff[1]) orboa = moa[:, mo_occ[0] > 0] orbva = moa[:, mo_occ[0] == 0] orbob = mob[:, mo_occ[1] > 0] orbvb = mob[:, mo_occ[1] == 0] h1aa = [] h1ab = [] h1ba = [] h1bb = [] fac = 8 * numpy.pi / 3 * .5 # *.5 due to s = 1/2 * pauli-matrix h1aa = fac * numpy.einsum('zp,zi->zpi', orbva[atmlst], orboa[atmlst]) h1ab = fac * numpy.einsum('zp,zi->zpi', orbva[atmlst], orbob[atmlst]) h1ba = fac * numpy.einsum('zp,zi->zpi', orbvb[atmlst], orboa[atmlst]) h1bb = -fac * numpy.einsum('zp,zi->zpi', orbvb[atmlst], orbob[atmlst]) return h1aa, h1ab, h1ba, h1bb
def get_com_fast(mf, p): ''' calculates COMS in mo_coeff space ''' ao1 = numint.eval_ao(mf.mol, mf.grids.coords) l_com = [] for s in range(p.nspin): s_com = [] occ = len(p.pycom_orb[s][mf.mo_occ[s] == 1]) for i in range(occ): phi = ao1.dot(p.pycom_orb[s][:, i]) dens = numpy.conjugate(phi) * phi * mf.grids.weights # COM x = numpy.sum(dens * mf.grids.coords[:, 0]) * Bohr y = numpy.sum(dens * mf.grids.coords[:, 1]) * Bohr z = numpy.sum(dens * mf.grids.coords[:, 2]) * Bohr print("{} COM: {} {} {}".format(p.pycom_loc, x, y, z)) s_com.append([x, y, z]) l_com.append(s_com) p.l_com = l_com return p
def AO(mol, C, outfile='AO_dir/AOs', nx=80, ny=80, nz=80, resolution=None, save=True): counter = 1 if not os.path.exists(outfile): os.makedirs(outfile) else: exists = True while exists: cache = outfile + '_' + str(counter) exists = os.path.exists(cache) counter += 1 outfile = cache os.makedirs(cache) cc = Cube(mol, nx, ny, nz, resolution) # Compute density on the .cube grid coords = cc.get_coords() ngrids = cc.get_ngrids() #blksize = min(8000, ngrids) blksize = ngrids rho = np.empty(ngrids) for ip0, ip1 in lib.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) x = (coords[:, 0].min(), coords[:, 0].max(), nx) y = (coords[:, 1].min(), coords[:, 1].max(), ny) z = (coords[:, 2].min(), coords[:, 2].max(), nz) if save: np.savetxt(outfile + '/AOs', ao) np.savetxt(outfile + '/C', C) np.savetxt(outfile + '/coords', np.array([y, x, z])) f = open(outfile + '/geom_basis', 'w') f.write(str(mol.atom) + '_') f.write(str(mol.basis)) f.close() #cc.write(np.array([]),outfile + '_geom',comment = 'Geometry') return ao, np.array([y, x, z])
def test_cube_c(self): """ Compute the density and store into a cube file """ # Initialize the class cube_c cc = Cube(mol, nx=20, ny=20, nz=20) # Compute density on the .cube grid coords = cc.get_coords() ngrids = cc.get_ngrids() blksize = min(8000, ngrids) rho = np.empty(ngrids) ao = None dm = mf.make_rdm1() for ip0, ip1 in gen_grid.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1], out=ao) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(cc.nx,cc.ny,cc.nz) # Write out density to the .cube file cc.write(rho, "h2o_den_cube_c.cube", comment='Electron density in real space (e/Bohr^3)')
def make_h1_fc(mol, mo_coeff, mo_occ, atmlst): coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) moa = ao.dot(mo_coeff[0]) mob = ao.dot(mo_coeff[1]) orboa = moa[:,mo_occ[0]> 0] orbva = moa[:,mo_occ[0]==0] orbob = mob[:,mo_occ[1]> 0] orbvb = mob[:,mo_occ[1]==0] h1aa = [] h1ab = [] h1ba = [] h1bb = [] fac = 8*numpy.pi/3 *.5 # *.5 due to s = 1/2 * pauli-matrix for ia in atmlst: h1aa.append(fac * numpy.einsum('p,i->pi', orbva[ia], orboa[ia])) h1ab.append(fac * numpy.einsum('p,i->pi', orbva[ia], orbob[ia])) h1ba.append(fac * numpy.einsum('p,i->pi', orbvb[ia], orboa[ia])) h1bb.append(fac * numpy.einsum('p,i->pi', orbvb[ia], orbob[ia])) return h1aa, h1ab, h1ba, h1bb
def test_mcol_lda_vxc_mat(self): nao = mol.nao n2c = nao * 2 ao_loc = mol.ao_loc numpy.random.seed(12) dm = numpy.random.rand(n2c, n2c) * .001 dm += numpy.eye(n2c) dm = dm + dm.T ngrids = 8 coords = numpy.random.rand(ngrids, 3) weight = numpy.random.rand(ngrids) ao = numint.eval_ao(mol, coords, deriv=0) rho = numint2c.eval_rho(mol, ao, dm, xctype='LDA', hermi=1) ni = numint2c.NumInt2C() vxc = ni.eval_xc_eff('lda,', rho, deriv=1)[1] mask = numpy.ones((100, mol.nbas), dtype=numpy.uint8) shls_slice = (0, mol.nbas) v0 = numint2c._ncol_lda_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 0) v1 = numint2c._ncol_lda_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 1) v1 = v1 + v1.conj().T ref = v0 self.assertAlmostEqual(abs(v0 - v1).max(), 0, 14) self.assertAlmostEqual(lib.fp(v0), 0.19683067215390423, 12) ni.collinear = 'mcol' eval_xc = ni.mcfun_eval_xc_adapter('lda,') vxc = eval_xc('lda,', rho, deriv=1)[1] mask = numpy.ones((100, mol.nbas), dtype=numpy.uint8) shls_slice = (0, mol.nbas) v0 = numint2c._mcol_lda_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 0) v1 = numint2c._mcol_lda_vxc_mat(mol, ao, weight, rho, vxc.copy(), mask, shls_slice, ao_loc, 1) v1 = v1 + v1.conj().T self.assertAlmostEqual(abs(v0 - ref).max(), 0, 3) self.assertAlmostEqual(abs(v0 - v1).max(), 0, 14)
def basis_values(mol, basis, coords, coeffs=None, positions=None): """ Calculate the orbital's value at a position in space Args: mol (moldesign.Molecule): Molecule to attach basis set to basis (moldesign.orbitals.BasisSet): set of basis functions coords (Array[length]): List of coordinates (with shape ``(len(coords), 3)``) coeffs (Vector): List of ao coefficients (optional; if not passed, all basis fn values are returned) Returns: Array[length]: if ``coeffs`` is not passed, an array of basis fn values at each coordinate. Otherwise, a list of orbital values at each coordinate """ # TODO: more than just create the basis by name ... pmol = mol_to_pyscf(mol, basis=basis.basisname, positions=positions) aovals = numint.eval_ao(pmol, np.ascontiguousarray(coords.value_in(u.bohr))) if coeffs is None: return aovals else: return aovals.dot(coeffs)
def basis_values(mol, basis, coords, coeffs=None, positions=None): """ Calculate the orbital's value at a position in space Args: mol (moldesign.Molecule): Molecule to attach basis set to basis (moldesign.orbitals.BasisSet): set of basis functions coords (Array[length]): List of coordinates (with shape ``(len(coords), 3)``) coeffs (Vector): List of ao coefficients (optional; if not passed, all basis fn values are returned) Returns: Array[length**(-1.5)]: if ``coeffs`` is not passed, an array of basis fn values at each coordinate. Otherwise, a list of orbital values at each coordinate """ from pyscf.dft import numint # TODO: more than just create the basis by name ... pmol = mol_to_pyscf(mol, basis=basis.basisname, positions=positions) aovals = numint.eval_ao(pmol, np.ascontiguousarray(coords.value_in(u.bohr))) * (u.a0**-1.5) if coeffs is None: return aovals else: return aovals.dot(coeffs.T)
def density(mol, outfile, dm, nx=80, ny=80, nz=80, resolution=RESOLUTION): """Calculates electron density and write out in cube format. Args: mol : Mole Molecule to calculate the electron density for. 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. """ cc = Cube(mol, nx, ny, nz, resolution) # Compute density on the .cube grid 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(mol, coords[ip0:ip1]) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(cc.nx, cc.ny, cc.nz) # Write out density to the .cube file cc.write(rho, outfile, comment='Electron density in real space (e/Bohr^3)')
def make_fcsd(hfcobj, dm0, hfc_nuc=None, verbose=None): log = logger.new_logger(hfcobj, verbose) mol = hfcobj.mol if hfc_nuc is None: hfc_nuc = range(mol.natm) if isinstance(dm0, numpy.ndarray) and dm0.ndim == 2: # RHF DM return numpy.zeros((3,3)) dma, dmb = dm0 spindm = dma - dmb effspin = mol.spin * .5 e_gyro = .5 * lib.param.G_ELECTRON nuc_mag = .5 * (lib.param.E_MASS/lib.param.PROTON_MASS) # e*hbar/2m au2MHz = lib.param.HARTREE2J / lib.param.PLANCK * 1e-6 fac = lib.param.ALPHA**2 / 2 / effspin * e_gyro * au2MHz coords = mol.atom_coords() ao = numint.eval_ao(mol, coords) nao = dma.shape[0] hfc = [] for i, atm_id in enumerate(hfc_nuc): nuc_gyro = get_nuc_g_factor(mol.atom_symbol(atm_id)) * nuc_mag mol.set_rinv_origin(mol.atom_coord(atm_id)) # a01p[mu,sigma] the imaginary part of integral <vec{r}/r^3 cross p> a01p = mol.intor('int1e_sa01sp', 12).reshape(3,4,nao,nao) h1 = -(a01p[:,:3] + a01p[:,:3].transpose(0,1,3,2)) fcsd = numpy.einsum('xyij,ji->xy', h1, spindm) fc = 8*numpy.pi/3 * numpy.einsum('i,j,ji', ao[atm_id], ao[atm_id], spindm) sd = fcsd - numpy.eye(3) * fc log.info('FC of atom %d %s (in MHz)', atm_id, fac * nuc_gyro * fc) if hfcobj.verbose >= logger.INFO: _write(hfcobj, align(fac*nuc_gyro*sd)[0], 'SD of atom %d (in MHz)' % atm_id) hfc.append(fac * nuc_gyro * fcsd) return numpy.asarray(hfc)
def density(mol, outfile, dm, nx=80, ny=80, nz=80, pad=4.0, gridspacing=None): """Calculates electron density. Args: mol (Mole): Molecule to calculate the electron density for. outfile (str): Name of Cube file to be written. dm (str): Density matrix of molecule. 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. pad (float): Amount of padding (in Angstrom) in all dimensions that will be applied in the automatic construction of the rectangular grid volume based on the geometry of the system. gridspacing (float): Distance, in Angstroms, between points in the grid, in all dimensions. This will override the nx,ny,nz the parameters. Note the following values: value/Angstroms points/Bohr Gaussian grid term 0.1763 3 Coarse 0.0882 6 Medium 0.0441 12 Fine """ grid = grid_utils.Grid(mol, nx, ny, nz, pad, gridspacing) ngrids = grid.coords.shape[0] blksize = min(8000, ngrids) rho = numpy.empty(ngrids) ao = None for ip0, ip1 in gen_grid.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, grid.coords[ip0:ip1], out=ao) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(grid.nx, grid.ny, grid.nz) grid_utils.write_formatted_cube_file( outfile, 'Electron density in real space (e/Bohr^3)', grid, rho)
def density(mol, outfile, dm, nx=80, ny=80, nz=80, resolution=RESOLUTION): """Calculates electron density and write out in cube format. Args: mol : Mole Molecule to calculate the electron density for. 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. """ cc = Cube(mol, nx, ny, nz, resolution) # Compute density on the .cube grid 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(mol, coords[ip0:ip1]) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(cc.nx,cc.ny,cc.nz) # Write out density to the .cube file cc.write(rho, outfile, comment='Electron density in real space (e/Bohr^3)')
def orbital(mol, outfile, coeff, nx=80, ny=80, nz=80, resolution=RESOLUTION): """Calculate orbital value on real space grid and write out in cube format. Args: mol : Mole Molecule to calculate the electron density for. outfile : str Name of Cube file to be written. coeff : 1D array coeff coefficient. 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. """ cc = Cube(mol, nx, ny, nz, resolution) # Compute density on the .cube grid coords = cc.get_coords() ngrids = cc.get_ngrids() blksize = min(8000, ngrids) orb_on_grid = numpy.empty(ngrids) for ip0, ip1 in lib.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) orb_on_grid[ip0:ip1] = numpy.dot(ao, coeff) orb_on_grid = orb_on_grid.reshape(cc.nx,cc.ny,cc.nz) # Write out orbital to the .cube file cc.write(orb_on_grid, outfile, comment='Orbital value in real space (1/Bohr^3)')
def density(mol, outfile, dm, nx=80, ny=80, nz=80): coord = mol.atom_coords() box = numpy.max(coord, axis=0) - numpy.min(coord, axis=0) + 6 boxorig = numpy.min(coord, axis=0) - 3 xs = numpy.arange(nx) * (box[0] / nx) ys = numpy.arange(ny) * (box[1] / ny) zs = numpy.arange(nz) * (box[2] / nz) coords = lib.cartesian_prod([xs, ys, zs]) coords = numpy.asarray(coords, order='C') - (-boxorig) nao = mol.nao_nr() ngrids = nx * ny * nz blksize = min(200, ngrids) rho = numpy.empty(ngrids) for ip0, ip1 in gen_grid.prange(0, ngrids, blksize): ao = numint.eval_ao(mol, coords[ip0:ip1]) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape(nx, ny, nz) with open(outfile, 'w') as f: f.write('Electron density in real space (e/Bohr^3)\n') f.write('PySCF Version: %s Date: %s\n' % (pyscf.__version__, time.ctime())) f.write('%5d' % mol.natm) f.write(' %14.8f %14.8f %14.8f\n' % tuple(boxorig.tolist())) f.write('%5d %14.8f %14.8f %14.8f\n' % (nx, xs[1], 0, 0)) f.write('%5d %14.8f %14.8f %14.8f\n' % (ny, 0, ys[1], 0)) f.write('%5d %14.8f %14.8f %14.8f\n' % (nz, 0, 0, zs[1])) for ia in range(mol.natm): chg = mol.atom_charge(ia) f.write('%5d %f' % (chg, chg)) f.write(' %14.8f %14.8f %14.8f\n' % tuple(coord[ia])) fmt = ' %14.8e' * nz + '\n' for ix in range(nx): for iy in range(ny): f.write(fmt % tuple(rho[ix, iy].tolist()))
mol = gto.M( verbose = 0, atom = ''' o 0 0. 0. h 0 -0.757 0.587 h 0 0.757 0.587''', basis = '6-31g') mf = dft.RKS(mol) mf.kernel() dm = mf.make_rdm1() # Use default mesh grids and weights coords = mf.grids.coords weights = mf.grids.weights ao_value = numint.eval_ao(mol, coords, isgga=True) # The first row of rho is electron density, the rest three rows are electron # density gradients which are needed for GGA functional rho = numint.eval_rho(mol, ao_value, dm, isgga=True) print(rho.shape) sigma = numpy.einsum('ip,ip->p', rho[1:], rho[1:]) # See pyscf/dft/vxc.py for the XC functional ID x_id = dft.XC_GGA_X_B88 c_id = dft.XC_GGA_C_P86 ex, vx, vx_sigma = numint.eval_x(x_id, rho[0], sigma) ec, vc, vc_sigma = numint.eval_c(c_id, rho[0], sigma) print('Exc = %.12f' % numpy.einsum('i,i,i->', ex+ec, rho[0], weights)) print('Vxc on each grid %s' % str(vx.shape)) print('Vxc_sigma on each grid %s' % str(vx.shape))
def lorb2fod(mf, lo_coeff, s=0, grid_level=7): """ lo_coeff[:] localized orbital """ from scipy import optimize # get estimate for FOD'position # by using the COM of the orbital density mol = mf.mol ao1 = numint.eval_ao(mol, mf.grids.coords) phi = ao1.dot(lo_coeff) #print(phi.shape) #print('lorb2fod: s={}'.format(s)) #print('lorb2fod: lo_coeff={}'.format(lo_coeff.sum())) #print(np.sum(phi**2*mf.grids.weights)) dens = np.conjugate(phi) * phi * mf.grids.weights # COM x = np.sum(dens * mf.grids.coords[:, 0]) y = np.sum(dens * mf.grids.coords[:, 1]) z = np.sum(dens * mf.grids.coords[:, 2]) #print x print(" -> COM: {0:7.5f} {1:7.5f} {2:7.5f}".format( x * units.Bohr, y * units.Bohr, z * units.Bohr)) ig_fod = np.array([x, y, z]) #if s==1: # sys.exit() ## build a new, smaller mesh for the density fitting # find nearest atom dists = np.linalg.norm((mol.atom_coords() - ig_fod), axis=1) didx = np.argsort(dists) #print dists #print didx nidx = -1 for i in range(mol.natm): if mol.atom_pure_symbol(i) == 'H': continue nidx = didx[i] break if nidx == -1: print("ERROR") sys.exit() #print nidx, mol.atom_pure_symbol(nidx) # build atom object (make sure to enter ccors in Angst) acoord = mol.atom_coords() atoms = Atoms() for na in range(mol.natm): aa = Atom(symbol=mol.atom_symbol(na), position=acoord[na] * units.Bohr) atoms.extend(aa) cutoffs = natural_cutoffs(atoms) ##print cutoffs nl = NL.NeighborList(cutoffs, self_interaction=False, bothways=True) nl.update(atoms) # generate a per-atom grid (include neigbours) neiatm = nl.get_neighbors(nidx)[0] mstr = '' for na in neiatm: sym = mol.atom_pure_symbol(na) pos = mol.atom_coord(na) * units.Bohr # in Angst #print sym, pos mstr += "{0} {1:0.12f} {2:0.12f} {3:0.12f};".format( sym, pos[0], pos[1], pos[2]) # also add the nearest Atom to the grid algorithm sym = mol.atom_pure_symbol(nidx) pos = mol.atom_coord(nidx) * units.Bohr # in Angst #print sym, pos mstr += "{0} {1:0.12f} {2:0.12f} {3:0.12f};".format( sym, pos[0], pos[1], pos[2]) #print ">>>" #print mstr # build a Mole object from subsystem b = mol.basis try: onmol = gto.M(atom=mstr, basis=b, verbose=0) except RuntimeError: onmol = gto.M(atom=mstr, basis=b, spin=1, verbose=0) _mdft = dft.UKS(onmol) _mdft.max_cycle = 0 _mdft.grids.level = grid_level _mdft.kernel() ongrid = copy.copy(_mdft.grids) #print("Original grid size: {0}".format(mf.grids.coords.shape[0])) #print(" building FO, grid size: {0}" # .format(ongrid.coords.shape[0])) ## re-calculate lo density on O(N) grid ao1 = numint.eval_ao(mol, ongrid.coords) phi = ao1.dot(lo_coeff) dens = np.conjugate(phi) * phi * ongrid.weights #sys.exit() # now build the corresponding fermi orbital #lfo = fo(mf, ig_fod, s) def densdiff(x0): #print ig_fod #print(s) _x = np.reshape(x0, (-1, 3)) lfo = fo(mf, _x, s) mol = mf.mol ao1 = numint.eval_ao(mol, ongrid.coords) _fo = ao1.dot(lfo) dens_fo = np.conjugate(_fo) * _fo * ongrid.weights ##print dens_fo.shape ##print dens.shape diff = np.linalg.norm(dens_fo - dens) return diff options = { 'disp': False, 'eps': 1e-05, 'gtol': 1e-05, 'maxiter': 299, } db = 1.5 if np.linalg.norm(mol.atom_coord(nidx) - ig_fod) < 0.5: db = 0.75 bounds = [(x - db, x + db), (y - db, y + db), (z - db, z + db)] res = optimize.minimize(densdiff, ig_fod.flatten(), method='L-BFGS-B', options=options, bounds=bounds) #print ">> done <<" #print res.x #print ig_fod #print ">> initial FOD moved by: {0:0.4f} [B]".format(np.linalg.norm(res.x-ig_fod)) #print ">> density fit quality : {0:0.4f}".format(res.fun) print(" -> a_i: {0:7.5f} {1:7.5f} {2:7.5f}"\ .format(res.x[0]*units.Bohr,res.x[1]*units.Bohr,res.x[2]*units.Bohr)) return res.x
mf = dft.RKS(mol) mf.xc = 'b3lyp' mf.kernel() dm = mf.make_rdm1() size = 18 # Use default mesh grids and weights grid = np.linspace(-size // 2, size // 2, int(size / 0.2 + 1)) coords = np.hstack((np.meshgrid(grid, grid, grid)[0].flatten().reshape( (int(size / 0.2 + 1)**3, 1)), np.meshgrid(grid, grid, grid)[1].flatten().reshape( (int(size / 0.2 + 1)**3, 1)), np.meshgrid(grid, grid, grid)[2].flatten().reshape( (int(size / 0.2 + 1)**3, 1)))) # weights = mf.grids.weights # weights_list.append(weights) ao_value = numint.eval_ao(mol, coords, deriv=1) # The first row of rho is electron density, the rest three rows are electron # density gradients which are needed for GGA functional rho = numint.eval_rho(mol, ao_value, dm, xctype='GGA') print(rho.shape) exc, vxc = dft.libxc.eval_xc('b3lyp', rho)[:2] print('Exc = %.12f' % np.einsum('i,i->', exc, rho[0] / 125.0)) Exc = np.einsum('i,i->', exc, rho[0] / 125.0) np.save(open("../rho_b3lyp.npy", "rb"), rho[0]) np.save(open("../vxc_b3lyp.npy", "rb"), vxc) np.save(open("../exc_b3lyp.npy", "rb"), exc) np.save(open("../Exc_b3lyp.npy", "rb"), Exc) # coords = mf.grids.coords # weights = mf.grids.weights # ao_value = numint.eval_ao(mol, coords, deriv=1)
def test_interpolate_helium(): """Check interpolation for He density.""" # define ta_object dic = os.getenv('FDETADATA') filetraj = os.path.join(dic, 'he_traj.txt') traj = TrajectoryAnalysis(filetraj) box_size = np.array([2, 2, 2]) grid_size = np.array([5, 5, 5]) # Use the mdinterface to create a cubic grid md = MDInterface(traj, box_size, grid_size) # print("Points: \n", md.points) # print(md.npoints*3) grid = np.zeros((md.npoints, 3)) grid = md.pbox.get_grid(grid, False) # Use PySCF to evaluate density from pyscf import gto, scf, dft from pyscf import lib from pyscf.dft.numint import eval_ao, eval_rho, eval_mat from pyscf.dft import gen_grid, libxc mol0 = gto.M(atom="""He 0.000 0.000 0.000""", basis='sto-3g') # Solve HF and get density scfres = scf.RHF(mol0) scfres.conv_tol = 1e-12 scfres.kernel() dm0 = scfres.make_rdm1() # Take only a plane in z=0 subgrid = grid[50:75] ao_mol0 = eval_ao(mol0, subgrid, deriv=0) rho_mol0 = eval_rho(mol0, ao_mol0, dm0, xctype='LDA') rho_plot = rho_mol0.reshape((5, 5)) # Check interpolation in PySCF grid from scipy import interpolate # whole grid ao_all = eval_ao(mol0, grid, deriv=0) rho_all = eval_rho(mol0, ao_all, dm0, xctype='LDA') xs = grid[:, 0] ys = grid[:, 1] zs = grid[:, 2] # print(rho_all.shape) grids = gen_grid.Grids(mol0) grids.level = 4 grids.build() # print(rho_all.shape) # print(grids.coords.shape) xdata = grids.coords[:, 0] ydata = grids.coords[:, 1] zdata = grids.coords[:, 2] # Real values real_ao = eval_ao(mol0, grids.coords, deriv=0) real_rho = eval_rho(mol0, real_ao, dm0, xctype='LDA') # Check with method is the best for Rbf interpolation functions = [ 'multiquadric', 'inverse', 'gaussian', 'linear', 'cubic', 'quintic', 'thin_plate' ] minmax = [] for function in functions: print(function) interpolator = interpolate.Rbf(xs, ys, zs, rho_all, function=function) new_rho = interpolator(xdata, ydata, zdata) minmax.append([ function, min(abs(new_rho - real_rho)), max(abs(new_rho - real_rho)) ]) # fig = plt.figure() # ax = fig.add_subplot(projection='3d') # ax.scatter3D(xdata, ydata, new_rho, c=new_rho, cmap='Greens') # ax.scatter3D(xdata, ydata, real_rho, c=real_rho) # plt.xlim(-1.0, 1.0) # plt.ylim(-1.0, 1.0) # plt.show() # print(minmax) mol1 = gto.M(atom="""He 0.000 0.000 2.500""", basis='sto-3g') # Solve HF and get density scfres1 = scf.RHF(mol1) scfres1.conv_tol = 1e-12 scfres1.kernel() dm1 = scfres1.make_rdm1() # whole grid ao_all1 = eval_ao(mol1, grid, deriv=0) rho_all1 = eval_rho(mol1, ao_all1, dm1, xctype='LDA') # Real values real_ao1 = eval_ao(mol1, grids.coords, deriv=0) real_rho1 = eval_rho(mol1, real_ao1, dm1, xctype='LDA') minmax1 = [] for function in functions: interpolator = interpolate.Rbf(xs, ys, zs, rho_all1, function=function) new_rho1 = interpolator(xdata, ydata, zdata) minmax1.append([ function, min(abs(new_rho1 - real_rho1)), max(abs(new_rho1 - real_rho1)) ]) p = np.where(abs(new_rho1 - real_rho1) == minmax1[-1][2])
mol = gto.M( verbose = 0, atom = ''' o 0 0. 0. h 0 -0.757 0.587 h 0 0.757 0.587''', basis = '6-31g') mf = dft.RKS(mol) mf.kernel() dm = mf.make_rdm1() # Use default mesh grids and weights coords = mf.grids.coords weights = mf.grids.weights ao_value = numint.eval_ao(mol, coords, deriv=1) # The first row of rho is electron density, the rest three rows are electron # density gradients which are needed for GGA functional rho = numint.eval_rho(mol, ao_value, dm, xctype='GGA') print(rho.shape) sigma = numpy.einsum('ip,ip->p', rho[1:], rho[1:]) # See pyscf/dft/vxc.py for the XC functional ID x_id = dft.XC_GGA_X_B88 c_id = dft.XC_GGA_C_P86 ex, vx, vx_sigma = numint.eval_x(x_id, rho[0], sigma) ec, vc, vc_sigma = numint.eval_c(c_id, rho[0], sigma) print('Exc = %.12f' % numpy.einsum('i,i,i->', ex+ec, rho[0], weights)) print('Vxc on each grid %s' % str(vx.shape)) print('Vxc_sigma on each grid %s' % str(vx.shape))
edft = eedft_1 + eedft_2 + enuc n = np.trace(s @ rdm1dft) print(' Number of electrons is {0} before diagonalization.'.format(n)) w = linalg.eig(s @ rdm1dft)[0] n = np.sum(w).real print(' Number of electrons is {0} after diagonalization.'.format(n)) # Now lets calculate densities in a grid #coords = np.random.random((100,3)) # 100 random points # Or we can generate an array #print(mol.atom_coords()) zz = np.linspace(-2, 4, 500) coords = [(0, 0, z) for z in zz] ao = numint.eval_ao( mol, coords, deriv=0 ) # we get the AO value for every point in space of coords, returns 2d array (N,nao) rho_dft = numint.eval_rho(mol, ao, rdm1dft, xctype='LDA', hermi=0) # we can evaluate rho at any point of space plt.plot(zz, rho_dft, label='DFT') plt.legend() plt.savefig('density_dft.png') # However if we need the derivatives of the density we need the derivatives of the aos # so we increase deriv # this returns (:,N,nao) where we get rho,rhox,rhoy,rhoz,drhodx... etc. ao = numint.eval_ao(mol, coords, deriv=1) # 1 for first derivatives # now we can evaluate \rho and first derivatives rho, dx_rho, dy_rho, dz_rho = numint.eval_rho(mol, ao,
def dm_on_grid(mol, dm, points): """ """ ao_mol = eval_ao(mol, points, deriv=0) rho = eval_rho(mol, ao_mol, dm, xctype="LDA") return rho