def check_sanity(self): lib.StreamObject.check_sanity(self) cell = self.cell if cell.dimension < 3: raise RuntimeError( 'FFTDF method does not support low-dimension ' 'PBC system. DF, MDF or AFTDF methods should ' 'be used.\nSee also examples/pbc/31-low_dimensional_pbc.py') if not cell.has_ecp(): logger.warn( self, 'FFTDF integrals are found in all-electron ' 'calculation. It often causes huge error.\n' 'Recommended methods are DF or MDF. In SCF calculation, ' 'they can be initialized as\n' ' mf = mf.density_fit()\nor\n' ' mf = mf.mix_density_fit()') if cell.ke_cutoff is None: ke_cutoff = tools.gs_to_cutoff(cell.lattice_vectors(), self.gs).min() else: ke_cutoff = numpy.min(cell.ke_cutoff) ke_guess = estimate_ke_cutoff(cell, cell.precision) if ke_cutoff < ke_guess * .8: gs_guess = tools.cutoff_to_gs(cell.lattice_vectors(), ke_guess) logger.warn( self, 'ke_cutoff/gs (%g / %s) is not enough for FFTDF ' 'to get integral accuracy %g.\nCoulomb integral error ' 'is ~ %.2g Eh.\nRecomended ke_cutoff/gs are %g / %s.', ke_cutoff, self.gs, cell.precision, error_for_ke_cutoff(cell, ke_cutoff), ke_guess, gs_guess) return self
def __init__(self, cell, kpts=numpy.zeros((1, 3))): self.cell = cell self.stdout = cell.stdout self.verbose = cell.verbose self.max_memory = cell.max_memory self.kpts = kpts # default is gamma point self.kpts_band = None self.auxbasis = None if cell.dimension == 0: self.eta = 0.2 self.gs = cell.gs else: ke_cutoff = tools.gs_to_cutoff(cell.lattice_vectors(), cell.gs) ke_cutoff = ke_cutoff[:cell.dimension].min() self.eta = min( aft.estimate_eta_for_ke_cutoff(cell, ke_cutoff, cell.precision), estimate_eta(cell, cell.precision)) ke_cutoff = aft.estimate_ke_cutoff_for_eta(cell, self.eta, cell.precision) self.gs = tools.cutoff_to_gs(cell.lattice_vectors(), ke_cutoff) self.gs[cell.dimension:] = cell.gs[cell.dimension:] # Not input options self.exxdiv = None # to mimic KRHF/KUHF object in function get_coulG self.auxcell = None self.blockdim = 240 self.linear_dep_threshold = LINEAR_DEP_THR self._j_only = False # If _cderi_to_save is specified, the 3C-integral tensor will be saved in this file. self._cderi_to_save = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR) # If _cderi is specified, the 3C-integral tensor will be read from this file self._cderi = None self._keys = set(self.__dict__.keys())
def check_sanity(self): lib.StreamObject.check_sanity(self) cell = self.cell if not cell.has_ecp(): logger.warn( self, 'FFTDF integrals are found in all-electron ' 'calculation. It often causes huge error.\n' 'Recommended methods are DF or MDF. In SCF calculation, ' 'they can be initialized as\n' ' mf = mf.density_fit()\nor\n' ' mf = mf.mix_density_fit()') if cell.dimension > 0: if cell.ke_cutoff is None: ke_cutoff = tools.gs_to_cutoff(cell.lattice_vectors(), self.gs) ke_cutoff = ke_cutoff[:cell.dimension].min() else: ke_cutoff = numpy.min(cell.ke_cutoff) ke_guess = estimate_ke_cutoff(cell, cell.precision) if ke_cutoff < ke_guess * .8: gs_guess = tools.cutoff_to_gs(cell.lattice_vectors(), ke_guess) logger.warn( self, 'ke_cutoff/gs (%g / %s) is not enough for FFTDF ' 'to get integral accuracy %g.\nCoulomb integral error ' 'is ~ %.2g Eh.\nRecomended ke_cutoff/gs are %g / %s.', ke_cutoff, self.gs, cell.precision, error_for_ke_cutoff(cell, ke_cutoff), ke_guess, gs_guess) else: gs_guess = numpy.copy(self.gs) if cell.dimension < 3: err = numpy.exp(-0.87278467 * min(self.gs[cell.dimension:]) - 2.99944305) err *= cell.nelectron if err > cell.precision * 10: gz = numpy.log( cell.nelectron / cell.precision) / 0.8727847 - 3.4366358 gs_guess[cell.dimension:] = int(gz) logger.warn( self, 'gs %s of AFTDF may not be enough to get ' 'integral accuracy %g for %dD PBC system.\n' 'Coulomb integral error is ~ %.2g Eh.\n' 'Recomended gs is %s.', self.gs, cell.precision, cell.dimension, err, gs_guess) return self
def get_nuc(mydf, kpts=None): cell = mydf.cell if kpts is None: kpts_lst = numpy.zeros((1, 3)) else: kpts_lst = numpy.reshape(kpts, (-1, 3)) log = logger.Logger(mydf.stdout, mydf.verbose) t1 = (time.clock(), time.time()) nkpts = len(kpts_lst) nao = cell.nao_nr() nao_pair = nao * (nao + 1) // 2 Gv, Gvbase, kws = cell.get_Gv_weights(mydf.gs) kpt_allow = numpy.zeros(3) if mydf.eta == 0: vpplocG = pseudo.pp_int.get_gth_vlocG_part1(cell, Gv) vpplocG = -numpy.einsum('ij,ij->j', cell.get_SI(Gv), vpplocG) vpplocG *= kws vG = vpplocG vj = numpy.zeros((nkpts, nao_pair), dtype=numpy.complex128) else: if cell.dimension > 0: ke_guess = estimate_ke_cutoff_for_eta(cell, mydf.eta, cell.precision) gs_guess = tools.cutoff_to_gs(cell.lattice_vectors(), ke_guess) if numpy.any(mydf.gs < gs_guess * .8): logger.warn( mydf, 'gs %s is not enough for AFTDF.get_nuc function ' 'to get integral accuracy %g.\nRecomended gs is %s.', mydf.gs, cell.precision, gs_guess) nuccell = copy.copy(cell) half_sph_norm = .5 / numpy.sqrt(numpy.pi) norm = half_sph_norm / gto.mole._gaussian_int(2, mydf.eta) chg_env = [mydf.eta, norm] ptr_eta = cell._env.size ptr_norm = ptr_eta + 1 chg_bas = [[ia, 0, 1, 1, 0, ptr_eta, ptr_norm, 0] for ia in range(cell.natm)] nuccell._atm = cell._atm nuccell._bas = numpy.asarray(chg_bas, dtype=numpy.int32) nuccell._env = numpy.hstack((cell._env, chg_env)) # PP-loc part1 is handled by fakenuc in _int_nuc_vloc vj = lib.asarray(mydf._int_nuc_vloc(nuccell, kpts_lst)) t1 = log.timer_debug1('vnuc pass1: analytic int', *t1) charge = -cell.atom_charges() coulG = tools.get_coulG(cell, kpt_allow, gs=mydf.gs, Gv=Gv) coulG *= kws aoaux = ft_ao.ft_ao(nuccell, Gv) vG = numpy.einsum('i,xi->x', charge, aoaux) * coulG max_memory = max(2000, mydf.max_memory - lib.current_memory()[0]) for aoaoks, p0, p1 in mydf.ft_loop(mydf.gs, kpt_allow, kpts_lst, max_memory=max_memory, aosym='s2'): for k, aoao in enumerate(aoaoks): # rho_ij(G) nuc(-G) / G^2 # = [Re(rho_ij(G)) + Im(rho_ij(G))*1j] [Re(nuc(G)) - Im(nuc(G))*1j] / G^2 if gamma_point(kpts_lst[k]): vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].real, aoao.real) vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].imag, aoao.imag) else: vj[k] += numpy.einsum('k,kx->x', vG[p0:p1].conj(), aoao) t1 = log.timer_debug1('contracting Vnuc', *t1) vj_kpts = [] for k, kpt in enumerate(kpts_lst): if gamma_point(kpt): vj_kpts.append(lib.unpack_tril(vj[k].real.copy())) else: vj_kpts.append(lib.unpack_tril(vj[k])) if kpts is None or numpy.shape(kpts) == (3, ): vj_kpts = vj_kpts[0] return numpy.asarray(vj_kpts)