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 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 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(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 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 density(mol, outfile, dm, nx=80, ny=80, nz=80, resolution=RESOLUTION, margin=BOX_MARGIN): """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. """ from pyscf.pbc.gto import Cell cc = Cube(mol, nx, ny, nz, resolution, margin) GTOval = 'GTOval' if isinstance(mol, Cell): GTOval = 'PBC' + GTOval # 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 = mol.eval_gto(GTOval, 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)') return rho
def density(mol, dm, outfile='rho', 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]) rho[ip0:ip1] = numint.eval_rho(mol, ao, dm) rho = rho.reshape((nx, ny, nz)) if save: cc.write(rho, outfile, comment='Electron density 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 rho, np.array([y, x, z])
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 write_fields(self, filename): """Write voxel data of registered fields in `self.fields` to cube-file.""" blksize = min(self.ncoords, 8000) with open(filename, 'a') as f: # Loop over x,y,z coordinates first, then fields! for blk0, blk1 in lib.prange(0, self.ncoords, blksize): data = np.zeros((blk1 - blk0, self.nfields)) blk = np.s_[blk0:blk1] ao = self.cell.eval_gto('PBCGTOval', self.coords[blk]) for i, (field, ftype, _) in enumerate(self.fields): if ftype == 'orbital': data[:, i] = np.dot(ao, field) elif ftype == 'density': data[:, i] = numint.eval_rho(self.cell, ao, field) else: raise ValueError('Unknown field type: %s' % ftype) data = data.flatten() for d0, d1 in lib.prange(0, len(data), 6): f.write(((d1 - d0) * self.fmt + '\n') % tuple(data[d0:d1]))
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 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 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 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()))
def density(mol, outfile, dm, nx=80, ny=80, nz=80): """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. """ 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) ngrids = nx * ny * nz 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, coords[ip0:ip1], out=ao) 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('%12.6f%12.6f%12.6f\n' % tuple(boxorig.tolist())) f.write('%5d%12.6f%12.6f%12.6f\n' % (nx, xs[1], 0, 0)) f.write('%5d%12.6f%12.6f%12.6f\n' % (ny, 0, ys[1], 0)) f.write('%5d%12.6f%12.6f%12.6f\n' % (nz, 0, 0, zs[1])) for ia in range(mol.natm): chg = mol.atom_charge(ia) f.write('%5d%12.6f' % (chg, chg)) f.write('%12.6f%12.6f%12.6f\n' % tuple(coord[ia])) for ix in range(nx): for iy in range(ny): for iz in range(0, nz, 6): remainder = (nz - iz) if (remainder > 6): fmt = '%13.5E' * 6 + '\n' f.write(fmt % tuple(rho[ix, iy, iz:iz + 6].tolist())) else: fmt = '%13.5E' * remainder + '\n' f.write(fmt % tuple(rho[ix, iy, iz:iz + remainder].tolist())) break
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])
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) # # 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')
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
def run_co_h2o_pyscf(ibasis, return_matrices=False): # Run SCF in pyscf h2o = gto.M( atom=""" O -7.9563726699 1.4854060709 0.1167920007 H -6.9923165534 1.4211335985 0.1774706091 H -8.1058463545 2.4422204631 0.1115993752 """, basis=ibasis, ) co = gto.M( atom=""" C -3.6180905689 1.3768035675 -0.0207958979 O -4.7356838533 1.5255563000 0.1150239130 """, basis=ibasis, ) system = gto.M(atom=co.atom + h2o.atom, basis=ibasis) # Get initial densities from HF # H2O # TODO: make a wrapper and make sure DMs are correct scfres1 = scf.RHF(h2o) scfres1.conv_tol = 1e-12 scfres1.kernel() dmb = scfres1.make_rdm1() # CO scfres2 = scf.RHF(co) scfres2.conv_tol = 1e-12 scfres2.kernel() dma = scfres2.make_rdm1() # Construct grid for complex grids = gen_grid.Grids(system) grids.level = 4 grids.build() ao_h2o = eval_ao(h2o, grids.coords, deriv=0) ao_co = eval_ao(co, grids.coords, deriv=0) # Make Complex DM ao_both = eval_ao(system, grids.coords, deriv=0) nao_co = co.nao_nr() nao_h2o = h2o.nao_nr() nao_tot = nao_co + nao_h2o dm_both = np.zeros((nao_tot, nao_tot)) dm_both[:nao_co, :nao_co] = dma dm_both[nao_co:, nao_co:] = dmb # Compute DFT non-additive potential and energies rho_h2o = eval_rho(h2o, ao_h2o, dmb, xctype='LDA') rho_co = eval_rho(co, ao_co, dma, xctype='LDA') rho_both = eval_rho(system, ao_both, dm_both, xctype='LDA') # Compute all densities on a grid xc_code = 'LDA,VWN' # same as xc_code = 'XC_LDA_X + XC_LDA_C_VWN' t_code = 'XC_LDA_K_TF' excs, vxcs = get_dft_grid_stuff(xc_code, rho_both, rho_co, rho_h2o) ets, vts = get_dft_grid_stuff(t_code, rho_both, rho_co, rho_h2o) 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_co, rho_h2o) et_nad = get_nad_energy(grids, ets, rho_both, rho_co, rho_h2o) fock_emb_xc = eval_mat(co, ao_co, grids.weights, rho_co, vxc_emb, xctype='LDA') fock_emb_t = eval_mat(co, ao_co, grids.weights, rho_co, vt_emb, xctype='LDA') # Electrostatic part v_coulomb = get_coulomb(co, h2o, dmb) # Nuclear-electron integrals vAnucB, vBnucA = get_attraction_potential(co, h2o) # Perform the HF-in-HF embedding # Modify Fock matrix focka_ref = scfres2.get_hcore() focka = focka_ref.copy() focka += fock_emb_t + fock_emb_xc + v_coulomb + vAnucB scfres3 = scf.RHF(co) scfres3.conv_tol = 1e-12 scfres3.get_hcore = lambda *args: focka # Re-evaluate the energy scfres3.kernel() # Get density matrix, to only evaluate dma_final = scfres3.make_rdm1() int_ref_xc = np.einsum('ab,ba', fock_emb_xc, dma) int_ref_t = np.einsum('ab,ba', fock_emb_t, dma) rhoArhoB = np.einsum('ab,ba', v_coulomb, dma_final) nucArhoB = np.einsum('ab,ba', vAnucB, dma_final) nucBrhoA = np.einsum('ab,ba', vBnucA, dmb) # Linearization terms int_emb_xc = np.einsum('ab,ba', fock_emb_xc, dma_final) int_emb_t = np.einsum('ab,ba', fock_emb_t, dma_final) deltalin = (int_emb_xc - int_ref_xc) + (int_emb_t - int_ref_t) # Save terms in dictionary embdic = {} embdic['rhoArhoB'] = rhoArhoB embdic['nucArhoB'] = nucArhoB embdic['nucBrhoA'] = nucBrhoA embdic['exc_nad'] = exc_nad embdic['et_nad'] = et_nad embdic['int_ref_xc'] = int_ref_xc embdic['int_ref_t'] = int_ref_t embdic['int_emb_xc'] = int_emb_xc embdic['int_emb_t'] = int_emb_t embdic['deltalin'] = deltalin if return_matrices: matdic = {} matdic['dma'] = dma matdic['dmb'] = dmb matdic['dma_final'] = dma_final matdic['fock_emb_xc'] = fock_emb_xc matdic['fock_emb_t'] = fock_emb_t matdic['v_coulomb'] = v_coulomb matdic['vAnucB'] = vAnucB matdic['vBnucA'] = vBnucA return embdic, matdic else: return embdic
format(efci, ehf, abs(efci - ehf))) # total energies # The FCI rdm1 needs to be decontracted from the mo coeffs. rdm1_corrected = mf.mo_coeff @ rdm1 @ mf.mo_coeff.T # 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_fci = numint.eval_rho(mol, ao, rdm1_corrected, xctype='LDA', hermi=0) # we can evaluate rho at any point of space rho_hf = numint.eval_rho(mol, ao, rdm1hf, xctype='LDA', hermi=0) # we can evaluate rho at any point of space plt.plot(zz, rho_fci, label='FCI') plt.plot(zz, rho_hf, label='HF') plt.legend() plt.savefig('densities.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,
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, rdm1dft, xctype='GGA', hermi=0)
def isomep(mol, outfile, dm, electronic_iso=0.002, iso_tol=0.00003, nx=80, ny=80, nz=80, pad=4.0, gridspacing=None): """Calculates MEP on a specific electron density surface. 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) LOGGER.debug("grid coords shape: %s", grid.coords.shape) LOGGER.debug("grid coords first element shape: %s", grid.coords[0].shape) 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) LOGGER.note("Total number of density voxels: %d", len(rho)) is_surface_voxel = numpy.logical_and(rho > (electronic_iso - iso_tol), rho < (electronic_iso + iso_tol)) LOGGER.debug("Surface voxel count from logical_and: %d", numpy.count_nonzero(is_surface_voxel)) surface_voxel_grid_indices = numpy.nonzero(is_surface_voxel)[0] LOGGER.debug2("Surface voxel indices: %s", surface_voxel_grid_indices) LOGGER.debug2("Surface voxel indices shape: %s", surface_voxel_grid_indices.shape) # Number of voxels at the defined electronic_iso surface # Used for area # Voxels at surface #(num > (ISO - TOL) ) && (num < (ISO + TOL) ) surface_voxel_count = surface_voxel_grid_indices.shape[0] surface_voxel_coords = grid.coords[surface_voxel_grid_indices[0]] for i in range(1, surface_voxel_grid_indices.shape[0]): surface_voxel_coord = grid.coords[surface_voxel_grid_indices[i]] LOGGER.debug4("surface voxel coord shape: %s", surface_voxel_coord.shape) surface_voxel_coords = numpy.append(surface_voxel_coords, surface_voxel_coord, axis=0) LOGGER.debug("surface_voxel_coords shape: %s", surface_voxel_coords.shape) surface_voxel_coords = surface_voxel_coords.reshape( (surface_voxel_grid_indices.shape[0], 3)) LOGGER.debug("surface_voxel_coords shape: %s", surface_voxel_coords.shape) LOGGER.debug3("First coord from grid: %s", grid.coords[surface_voxel_grid_indices[0]]) LOGGER.debug3("First coord from surf voxel array: %s", surface_voxel_coords[0]) is_in_surface = numpy.greater(rho, electronic_iso) LOGGER.debug("Voxel count from numpy.greater: %d", numpy.count_nonzero(is_in_surface)) # Number of voxels *within* the defined electronic_iso surface # Used for volume inner_voxel_count = numpy.count_nonzero(is_in_surface) # This time, actually change LOGGER.debug("rho shape: %s", rho.shape) rho = rho.reshape(grid.nx, grid.ny, grid.nz) LOGGER.debug("rho shape: %s", rho.shape) LOGGER.note("surface voxels_found: %d", surface_voxel_count) voxel_area = gridspacing * gridspacing LOGGER.info("Each voxel area / A^2: %f", voxel_area) LOGGER.info("inner surface area / A^2: %f", surface_voxel_count * voxel_area) LOGGER.info("inner voxel count: %d", inner_voxel_count) voxel_volume = gridspacing * gridspacing * gridspacing LOGGER.info("Each voxel volume / A^3: %f", voxel_volume) inner_volume = inner_voxel_count * voxel_volume LOGGER.info("Total inner volume / A^3: %f", inner_volume) mep_values = mep_for_coords(mol, dm, surface_voxel_coords) LOGGER.debug("MEP values shape: %s", mep_values.shape) mep_values = mep_values.reshape((mep_values.shape[0], 1)) LOGGER.debug("MEP values shape: %s", mep_values.shape) #Add the potentials to the coordinates: each row describes one point. coords_with_mep_values = numpy.append(surface_voxel_coords, mep_values, axis=1) cube_information = "Molecular electrostatic potential in real space on {:.5f} isodensity surface. Volume: {:.6f}".format( electronic_iso, inner_volume) grid_utils.write_unformatted_cube_file(outfile, cube_information, grid, coords_with_mep_values)
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))
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 get_cubevals_from_dm( self, dmfile="", basfile="", g="", comment="Obtained from density matrix in file: \n {dmfile} \n"): """ Note ---- Allows to obtain values from a density matrix. Parameters ---------- dmfile: str or list density matrix file, list or "file1,file2" basfile: str or list basis .nwchem file, list or "file1.nwchem,file2.nwchem" g: str or geom obj, or [str,str] or [obj,obj] geometry or geometry file which overrides self.geom. Compulsory only for dual basis. For dual basis: "geomA.xyz, geomB.xyz", ["geomA.xyz"," geomB.xyz"], or [geomA, geomB] comment: str default writes dmfile, use empty string to leave self.cube Sets ---- self.values obtained from density matrix self.comment user-chosen, default is corresponding density matrix """ basfile = list(basfile) if type( basfile) == tuple else basfile # no tuples because immutable g = list(g) if type(g) == tuple else g # no tuples because immutable from pyscf import gto from pyscf.dft.numint import eval_ao, eval_rho import dmtools.dmtools as dmt if dmfile == "": dmfile = input( "You must specify the density matrix file. Can have header or not, can be alpha and beta or not. Please type the filename\n" ) #TODO check if it reads a single DM as 2*a or a. if basfile == "": import glob as gl files = gl.glob("*.nwchem") if len(files) == 0: raise FileNotFoundError( "no *.nwchem file! basis must be in .nwchem!") elif len(files) == 1: basfile = files[0] print( "basfile not specified, using {} as a single basis".format( basfile)) else: basfile = input( "Too many *.nwchem. For single basis, type the one to use. For dual basis, type '[basisA.nwchem],[basisB.nwchem]'\n" ) basfile = [ i.strip() for i in basfile.split(",") ] if "," in basfile else basfile # turn string to list if dual basis if type(basfile) == str: # then it is not dual basis if g != "": if type(g) == str: g = geom.from_xyz(g) self.geom = g self.geom.change_coord_unit("Angstrom") with open(basfile, "r") as f: ibasis = f.read() if type(basfile) == list: # then it is dual basis if g == "": g = input( "From basfile I deduce dualbasis, Please type 'geomfileA,geomfileB'\n" ) if type(g) == str: if len(g.split(",")) == 2: g = [i.strip() for i in g.split(",")] else: raise TypeError( "Cannot obtain two geometries from {}.\n From basfile I deduce dualbasis, so you must give geomA and geomB" .format(g)) for n in range(2): try: g[n] = geom.from_xyz(g[n], identifier=n) except: g[n].change_coord_unit("angstrom") g[n].change_identifier(n) self.geom = g[0] + g[1] ###create ibasis for n, i in enumerate(basfile): with open(i, "r") as f: basfile[n] = f.read() ibasis = { i + str(n): basfile[n] for n in range(2) for i in set(g[n].atoms) } geomstring = self.geom.__str__() mol = gto.M(atom=geomstring, basis=ibasis) dm_obj = dmt.DM.from_dmfile(dmfile) dm = dm_obj.get_dm_full() self.geom.change_coord_unit("au") points = self.get_coordlist() ao_mol = eval_ao(mol, points, deriv=0) cubevals = eval_rho(mol, ao_mol, dm, xctype='LDA') self.values = cubevals.reshape(*self.Np_vect) if "{dmfile}" in comment: comment = comment.format(dmfile=dmfile) self.comment = comment
def AOtorho(mol, ao, dm, nx, ny, nz): rho = np.zeros((ao.shape[0])) rho = numint.eval_rho(mol, ao, dm) rho = rho.reshape((nx, ny, nz)) return rho