def cholesky_eri(mol, auxbasis='weigend+etb', auxmol=None, int3c='int3c2e_sph', aosym='s2ij', int2c='int2c2e_sph', comp=1, verbose=0, fauxe2=aux_e2): ''' Returns: 2D array of (naux,nao*(nao+1)/2) in C-contiguous ''' assert(comp == 1) t0 = (time.clock(), time.time()) log = logger.new_logger(mol, verbose) if auxmol is None: auxmol = addons.make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) naux = j2c.shape[0] log.debug('size of aux basis %d', naux) t1 = log.timer('2c2e', *t0) try: low = scipy.linalg.cholesky(j2c, lower=True) except scipy.linalg.LinAlgError: j2c[numpy.diag_indices(j2c.shape[1])] += 1e-14 low = scipy.linalg.cholesky(j2c, lower=True) j2c = None t1 = log.timer('Cholesky 2c2e', *t1) j3c = fauxe2(mol, auxmol, intor=int3c, aosym=aosym).reshape(-1,naux) t1 = log.timer('3c2e', *t1) cderi = scipy.linalg.solve_triangular(low, j3c.T, lower=True, overwrite_b=True) j3c = None if cderi.flags.f_contiguous: cderi = lib.transpose(cderi.T) log.timer('cholesky_eri', *t0) return cderi
def build(self): log = logger.Logger(self.stdout, self.verbose) mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) n2c = mol.nao_2c() naux = auxmol.nao_nr() nao_pair = n2c * (n2c + 1) // 2 max_memory = (self.max_memory - lib.current_memory()[0]) * .8 mem_incore = nao_pair * naux * 3 * 16 / 1e6 * 2 mem_now = lib.current_memory()[0] if mem_incore < max_memory: self._cderi = (r_incore.cholesky_eri(mol, auxmol=auxmol, aosym='s1', int3c='int3c2e_spinor', verbose=log), r_incore.cholesky_eri(mol, auxmol=auxmol, aosym='s1', int3c='int3c2e_spsp1_spinor', verbose=log)) else: raise NotImplementedError("Outcore not available, requested :", mem_incore) return self
def loop(self, blksize=None): # direct blocksize mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) int3c = 'int3c2e' int3c = mol._add_suffix(int3c) int3c = gto.moleintor.ascint3(int3c) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] naoaux = ao_loc[-1] - nao # TODO: Libcint-3.14 and newer version support to compute int3c2e without # the opt for the 3rd index. #if '3c2e' in int3c: # cintopt = gto.moleintor.make_cintopt(atm, mol._bas, env, int3c) #else: # cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) if blksize is None: max_memory = (self.max_memory - lib.current_memory()[0]) * .8 blksize = min(int(max_memory * 1e6 / 48 / nao / (nao + 1)), 80) # print('blksize1',blksize,int(max_memory*1e6/48/nao/(nao+1)),max_memory,self.max_memory) comp = 1 aosym = 's2ij' for b0, b1 in self.prange(0, auxmol.nbas, blksize): shls_slice = (0, mol.nbas, 0, mol.nbas, mol.nbas + b0, mol.nbas + b1) buf = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt) eri1 = numpy.asarray(buf.T, order='C') yield eri1
def aux_e1(mol, auxmol_or_auxbasis, intor='int3c2e', aosym='s1', comp=None, out=None): '''3-center 2-electron AO integrals (L|ij), where L is the auxiliary basis. Note aux_e1 is basically analogous to aux_e2 function. It can be viewed as the version of transposed aux_e2 tensor: if comp == 1: aux_e1 = aux_e2().T else: aux_e1 = aux_e2().transpose(0,2,1) The same arguments as function aux_e2 can be input to aux_e1. ''' if isinstance(auxmol_or_auxbasis, gto.Mole): auxmol = auxmol_or_auxbasis else: auxbasis = auxmol_or_auxbasis auxmol = addons.make_auxmol(mol, auxbasis) out = aux_e2(mol, auxmol, intor, aosym, comp, out) if out.ndim == 2: # comp == 1, aosym == s2 out = out.T elif out.ndim == 3: # aosym == s1 assert aosym == 's1', '' out = out.transpose(1, 2, 0) else: # comp > 1 and aosym == s1 out = out.transpose(0, 2, 3, 1) return out
def aux_e2(mol, auxmol_or_auxbasis, intor='int3c2e', aosym='s1', comp=None, out=None, cintopt=None): '''3-center AO integrals (ij|L), where L is the auxiliary basis. Kwargs: cintopt : Libcint-3.14 and newer version support to compute int3c2e without the opt for the 3rd index. It can be precomputed to reduce the overhead of cintopt initialization repeatedly. cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, 'int3c2e') ''' if isinstance(auxmol_or_auxbasis, gto.Mole): auxmol = auxmol_or_auxbasis else: auxbasis = auxmol_or_auxbasis auxmol = addons.make_auxmol(mol, auxbasis) shls_slice = (0, mol.nbas, 0, mol.nbas, mol.nbas, mol.nbas+auxmol.nbas) # Extract the call of the two lines below # pmol = gto.mole.conc_mol(mol, auxmol) # return pmol.intor(intor, comp, aosym=aosym, shls_slice=shls_slice, out=out) intor = mol._add_suffix(intor) hermi = 0 ao_loc = None atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) return getints(intor, atm, bas, env, shls_slice, comp, hermi, aosym, ao_loc, cintopt, out)
def build(self): t0 = (logger.process_clock(), logger.perf_counter()) log = logger.Logger(self.stdout, self.verbose) self.check_sanity() self.dump_flags() mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) nao = mol.nao_nr() naux = auxmol.nao_nr() nao_pair = nao * (nao + 1) // 2 max_memory = self.max_memory - lib.current_memory()[0] int3c = mol._add_suffix('int3c2e') int2c = mol._add_suffix('int2c2e') if (nao_pair * naux * 8 / 1e6 < .9 * max_memory and not isinstance(self._cderi_to_save, str)): self._cderi = incore.cholesky_eri(mol, int3c=int3c, int2c=int2c, auxmol=auxmol, max_memory=max_memory, verbose=log) else: if isinstance(self._cderi_to_save, str): cderi = self._cderi_to_save else: cderi = self._cderi_to_save.name if isinstance(self._cderi, str): # If cderi needs to be saved in log.warn( 'Value of _cderi is ignored. DF integrals will be ' 'saved in file %s .', cderi) if self._compatible_format or isinstance(self._cderi_to_save, str): outcore.cholesky_eri(mol, cderi, dataname='j3c', int3c=int3c, int2c=int2c, auxmol=auxmol, max_memory=max_memory, verbose=log) else: # Store DF tensor in blocks. This is to reduce the # initiailzation overhead outcore.cholesky_eri_b(mol, cderi, dataname='j3c', int3c=int3c, int2c=int2c, auxmol=auxmol, max_memory=max_memory, verbose=log) self._cderi = cderi log.timer_debug1('Generate density fitting integrals', *t0) return self
def cholesky_eri(mol, erifile, auxbasis='weigend+etb', dataname='j3c', tmpdir=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, max_memory=MAX_MEMORY, auxmol=None, verbose=logger.NOTE): '''3-index density-fitting tensor. ''' assert(aosym in ('s1', 's2ij')) assert(comp == 1) log = logger.new_logger(mol, verbose) time0 = (time.clock(), time.time()) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, max_memory, auxmol, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('generate (ij|L) 1 pass', *time0) # Cannot let naoaux = auxmol.nao_nr() if auxbasis has linear dependence nao = mol.nao_nr() if aosym == 's1': nao_pair = nao * nao else: nao_pair = nao * (nao+1) // 2 feri = _create_h5file(erifile, dataname) if comp == 1: naoaux = fswap['%s/0'%dataname].shape[0] h5d_eri = feri.create_dataset(dataname, (naoaux,nao_pair), 'f8') else: naoaux = fswap['%s/0'%dataname].shape[1] h5d_eri = feri.create_dataset(dataname, (comp,naoaux,nao_pair), 'f8') iolen = min(max(int(max_memory*.45e6/8/nao_pair), 28), naoaux) totstep = (naoaux+iolen-1)//iolen def load(row_slice): row0, row1 = row_slice return _load_from_h5g(fswap[dataname], row0, row1) ti0 = time1 slices = list(lib.prange(0, naoaux, iolen)) for istep, dat in enumerate(lib.map_with_prefetch(load, slices)): row0, row1 = slices[istep] nrow = row1 - row0 if comp == 1: h5d_eri[row0:row1] = dat else: h5d_eri[:,row0:row1] = dat dat = None ti0 = log.timer('step 2 [%d/%d], [%d:%d], row = %d'% (istep+1, totstep, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('cholesky_eri', *time0) return erifile
def fill_2c2e(mol, auxmol_or_auxbasis, intor='int2c2e', comp=None, hermi=1, out=None): '''2-center 2-electron AO integrals for auxiliary basis (auxmol) ''' if isinstance(auxmol_or_auxbasis, gto.Mole): auxmol = auxmol_or_auxbasis else: auxbasis = auxmol_or_auxbasis auxmol = addons.make_auxmol(mol, auxbasis) return auxmol.intor(intor, comp=comp, hermi=hermi, out=out)
def loop(self, blksize=None): # direct blocksize mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) int3c='int3c2e' int3c = mol._add_suffix(int3c) int3c = gto.moleintor.ascint3(int3c) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] naoaux = ao_loc[-1] - nao # TODO: Libcint-3.14 and newer version support to compute int3c2e without # the opt for the 3rd index. #if '3c2e' in int3c: # cintopt = gto.moleintor.make_cintopt(atm, mol._bas, env, int3c) #else: # cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) comp = 1 aosym = 's2ij' segsize = (naoaux+mpi.pool.size-1) // mpi.pool.size global pauxz,paux aa = 0 while naoaux-aa > segsize-1: aa = 0 j = 0 b1 = [] pauxz = [] paux = [] for i in range(auxmol.nbas+1): if ao_loc[mol.nbas+i]-nao-aa > segsize and j < mpi.pool.size-1: paux.append(ao_loc[mol.nbas+i-1]-nao-aa) aa = ao_loc[mol.nbas+i-1]-nao pauxz.append(aa) b1.append(i-1) j += 1 if naoaux-aa <= segsize: b1.append(auxmol.nbas) paux.append(naoaux-aa) pauxz.append(ao_loc[-1]) segsize += 1 stop = b1[rank] if rank ==0: start = 0 else: start = b1[rank-1] shls_slice = (0, mol.nbas, 0, mol.nbas, mol.nbas+start, mol.nbas+stop) buf = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt) global eri1 eri1 = numpy.asarray(buf.T, order='C') yield eri1
def make_modrho_basis(cell, auxbasis=None, drop_eta=None): auxcell = addons.make_auxmol(cell, auxbasis) # Note libcint library will multiply the norm of the integration over spheric # part sqrt(4pi) to the basis. half_sph_norm = numpy.sqrt(.25 / numpy.pi) steep_shls = [] ndrop = 0 rcut = [] _env = auxcell._env.copy() for ib in range(len(auxcell._bas)): l = auxcell.bas_angular(ib) np = auxcell.bas_nprim(ib) nc = auxcell.bas_nctr(ib) es = auxcell.bas_exp(ib) ptr = auxcell._bas[ib, gto.PTR_COEFF] cs = auxcell._env[ptr:ptr + np * nc].reshape(nc, np).T if drop_eta is not None and numpy.any(es < drop_eta): cs = cs[es >= drop_eta] es = es[es >= drop_eta] np, ndrop = len(es), ndrop + np - len(es) if np > 0: pe = auxcell._bas[ib, gto.PTR_EXP] auxcell._bas[ib, gto.NPRIM_OF] = np _env[pe:pe + np] = es # int1 is the multipole value. l*2+2 is due to the radial part integral # \int (r^l e^{-ar^2} * Y_{lm}) (r^l Y_{lm}) r^2 dr d\Omega int1 = gto.gaussian_int(l * 2 + 2, es) s = numpy.einsum('pi,p->i', cs, int1) # The auxiliary basis normalization factor is not a must for density expansion. # half_sph_norm here to normalize the monopole (charge). This convention can # simplify the formulism of \int \bar{\rho}, see function auxbar. cs = numpy.einsum('pi,i->pi', cs, half_sph_norm / s) _env[ptr:ptr + np * nc] = cs.T.reshape(-1) steep_shls.append(ib) r = _estimate_rcut(es, l, abs(cs).max(axis=1), cell.precision) rcut.append(r.max()) auxcell._env = _env auxcell.rcut = max(rcut) auxcell._bas = numpy.asarray(auxcell._bas[steep_shls], order='C') logger.info(cell, 'Drop %d primitive fitting functions', ndrop) logger.info(cell, 'make aux basis, num shells = %d, num cGTOs = %d', auxcell.nbas, auxcell.nao_nr()) logger.info(cell, 'auxcell.rcut %s', auxcell.rcut) return auxcell
def make_modrho_basis(cell, auxbasis=None, drop_eta=None): auxcell = addons.make_auxmol(cell, auxbasis) # Note libcint library will multiply the norm of the integration over spheric # part sqrt(4pi) to the basis. half_sph_norm = numpy.sqrt(.25/numpy.pi) steep_shls = [] ndrop = 0 rcut = [] for ib in range(len(auxcell._bas)): l = auxcell.bas_angular(ib) np = auxcell.bas_nprim(ib) nc = auxcell.bas_nctr(ib) es = auxcell.bas_exp(ib) ptr = auxcell._bas[ib,gto.PTR_COEFF] cs = auxcell._env[ptr:ptr+np*nc].reshape(nc,np).T if drop_eta is not None and numpy.any(es < drop_eta): cs = cs[es>=drop_eta] es = es[es>=drop_eta] np, ndrop = len(es), ndrop+np-len(es) if np > 0: pe = auxcell._bas[ib,gto.PTR_EXP] auxcell._bas[ib,gto.NPRIM_OF] = np auxcell._env[pe:pe+np] = es # int1 is the multipole value. l*2+2 is due to the radial part integral # \int (r^l e^{-ar^2} * Y_{lm}) (r^l Y_{lm}) r^2 dr d\Omega int1 = gto.gaussian_int(l*2+2, es) s = numpy.einsum('pi,p->i', cs, int1) # The auxiliary basis normalization factor is not a must for density expansion. # half_sph_norm here to normalize the monopole (charge). This convention can # simplify the formulism of \int \bar{\rho}, see function auxbar. cs = numpy.einsum('pi,i->pi', cs, half_sph_norm/s) auxcell._env[ptr:ptr+np*nc] = cs.T.reshape(-1) steep_shls.append(ib) r = _estimate_rcut(es, l, abs(cs).max(axis=1), cell.precision) rcut.append(r.max()) auxcell.rcut = max(rcut) auxcell._bas = numpy.asarray(auxcell._bas[steep_shls], order='C') logger.info(cell, 'Drop %d primitive fitting functions', ndrop) logger.info(cell, 'make aux basis, num shells = %d, num cGTOs = %d', auxcell.nbas, auxcell.nao_nr()) logger.info(cell, 'auxcell.rcut %s', auxcell.rcut) return auxcell
def build(self): t0 = (time.clock(), time.time()) log = logger.Logger(self.stdout, self.verbose) self.check_sanity() self.dump_flags() mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) nao = mol.nao_nr() naux = auxmol.nao_nr() nao_pair = nao * (nao + 1) // 2 max_memory = (self.max_memory - lib.current_memory()[0]) * .8 int3c = mol._add_suffix('int3c2e') int2c = mol._add_suffix('int2c2e') if (nao_pair * naux * 3 * 8 / 1e6 < max_memory and not isinstance(self._cderi_to_save, str)): self._cderi = incore.cholesky_eri(mol, int3c=int3c, int2c=int2c, auxmol=auxmol, verbose=log) else: if isinstance(self._cderi_to_save, str): cderi = self._cderi_to_save else: cderi = self._cderi_to_save.name if isinstance(self._cderi, str): log.warn( 'Value of _cderi is ignored. DF integrals will be ' 'saved in file %s .', cderi) outcore.cholesky_eri(mol, cderi, dataname='j3c', int3c=int3c, int2c=int2c, auxmol=auxmol, max_memory=max_memory, verbose=log) if nao_pair * naux * 8 / 1e6 < max_memory: with addons.load(cderi, 'j3c') as feri: cderi = numpy.asarray(feri) self._cderi = cderi log.timer_debug1('Generate density fitting integrals', *t0) return self
def build(self): log = logger.Logger(self.stdout, self.verbose) mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) n2c = mol.nao_2c() naux = auxmol.nao_nr() nao_pair = n2c*(n2c+1)//2 max_memory = (self.max_memory - lib.current_memory()[0]) * .8 if nao_pair*naux*3*16/1e6*2 < max_memory: self._cderi =(r_incore.cholesky_eri(mol, auxmol=auxmol, aosym='s2', int3c='int3c2e_spinor', verbose=log), r_incore.cholesky_eri(mol, auxmol=auxmol, aosym='s2', int3c='int3c2e_spsp1_spinor', verbose=log)) else: raise NotImplementedError return self
def cholesky_eri(mol, auxbasis='weigend+etb', auxmol=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, verbose=0, fauxe2=aux_e2): ''' Returns: 2D array of (naux,nao*(nao+1)/2) in C-contiguous ''' assert(comp == 1) t0 = (time.clock(), time.time()) log = logger.new_logger(mol, verbose) if auxmol is None: auxmol = addons.make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) naux = j2c.shape[0] log.debug('size of aux basis %d', naux) t1 = log.timer('2c2e', *t0) j3c = fauxe2(mol, auxmol, intor=int3c, aosym=aosym).reshape(-1,naux) t1 = log.timer('3c2e', *t1) try: low = scipy.linalg.cholesky(j2c, lower=True) j2c = None t1 = log.timer('Cholesky 2c2e', *t1) cderi = scipy.linalg.solve_triangular(low, j3c.T, lower=True, overwrite_b=True) except scipy.linalg.LinAlgError: w, v = scipy.linalg.eigh(j2c) idx = w > LINEAR_DEP_THR v = (v[:,idx] / numpy.sqrt(w[idx])) cderi = lib.dot(v.T, j3c.T) j3c = None if cderi.flags.f_contiguous: cderi = lib.transpose(cderi.T) log.timer('cholesky_eri', *t0) return cderi
def cholesky_eri_debug(mol, auxbasis='weigend+etb', auxmol=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, verbose=0, fauxe2=aux_e2): ''' Returns: 2D array of (naux,nao*(nao+1)/2) in C-contiguous ''' assert(comp == 1) t0 = (logger.process_clock(), logger.perf_counter()) log = logger.new_logger(mol, verbose) if auxmol is None: auxmol = addons.make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) naux = j2c.shape[0] log.debug('size of aux basis %d', naux) t1 = log.timer('2c2e', *t0) j3c = fauxe2(mol, auxmol, intor=int3c, aosym=aosym).reshape(-1,naux) t1 = log.timer('3c2e', *t1) try: low = scipy.linalg.cholesky(j2c, lower=True) j2c = None t1 = log.timer('Cholesky 2c2e', *t1) cderi = scipy.linalg.solve_triangular(low, j3c.T, lower=True, overwrite_b=True) except scipy.linalg.LinAlgError: w, v = scipy.linalg.eigh(j2c) idx = w > LINEAR_DEP_THR v = (v[:,idx] / numpy.sqrt(w[idx])) cderi = lib.dot(v.T, j3c.T) j3c = None if cderi.flags.f_contiguous: cderi = lib.transpose(cderi.T) log.timer('cholesky_eri', *t0) return cderi
def build(self): t0 = (time.clock(), time.time()) log = logger.Logger(self.stdout, self.verbose) self.check_sanity() self.dump_flags() mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) nao = mol.nao_nr() naux = auxmol.nao_nr() nao_pair = nao*(nao+1)//2 max_memory = (self.max_memory - lib.current_memory()[0]) * .8 int3c = mol._add_suffix('int3c2e') int2c = mol._add_suffix('int2c2e') if (nao_pair*naux*3*8/1e6 < max_memory and not isinstance(self._cderi_to_save, str)): self._cderi = incore.cholesky_eri(mol, int3c=int3c, int2c=int2c, auxmol=auxmol, verbose=log) else: if isinstance(self._cderi_to_save, str): cderi = self._cderi_to_save else: cderi = self._cderi_to_save.name if isinstance(self._cderi, str): log.warn('Value of _cderi is ignored. DF integrals will be ' 'saved in file %s .', cderi) outcore.cholesky_eri(mol, cderi, dataname='j3c', int3c=int3c, int2c=int2c, auxmol=auxmol, max_memory=max_memory, verbose=log) if nao_pair*naux*8/1e6 < max_memory: with addons.load(cderi, 'j3c') as feri: cderi = numpy.asarray(feri) self._cderi = cderi log.timer_debug1('Generate density fitting integrals', *t0) return self
def cholesky_eri(mol, erifile, auxbasis='weigend+etb', dataname='j3c', tmpdir=None, int3c='int3c2e_sph', aosym='s2ij', int2c='int2c2e_sph', comp=1, max_memory=MAX_MEMORY, ioblk_size=IOBLK_SIZE, auxmol=None, verbose=logger.NOTE): '''3-center 2-electron AO integrals ''' assert (aosym in ('s1', 's2ij')) assert (comp == 1) log = logger.new_logger(mol, verbose) time0 = (time.clock(), time.time()) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, ioblk_size, auxmol, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('generate (ij|L) 1 pass', *time0) nao = mol.nao_nr() # Cannot let naoaux = auxmol.nao_nr() if auxbasis has linear dependence naoaux = fswap['%s/0/0' % dataname].shape[0] if aosym == 's1': nao_pair = nao * nao else: nao_pair = nao * (nao + 1) // 2 feri = _create_h5file(erifile, dataname) if comp == 1: chunks = (min(int(16e3 / nao), naoaux), nao) # 128K h5d_eri = feri.create_dataset(dataname, (naoaux, nao_pair), 'f8', chunks=chunks) else: chunks = (1, min(int(16e3 / nao), naoaux), nao) # 128K h5d_eri = feri.create_dataset(dataname, (comp, naoaux, nao_pair), 'f8', chunks=chunks) aopairblks = len(fswap[dataname + '/0']) ioblk_size = max(max_memory * .1, ioblk_size) iolen = min(max(int(ioblk_size * 1e6 / 8 / nao_pair), 28), naoaux) totstep = (naoaux + iolen - 1) // iolen * comp buf = numpy.empty((iolen, nao_pair)) ti0 = time1 for icomp in range(comp): istep = 0 for row0, row1 in lib.prange(0, naoaux, iolen): nrow = row1 - row0 istep += 1 col0 = 0 for ic in range(aopairblks): dat = fswap['%s/%d/%d' % (dataname, icomp, ic)] col1 = col0 + dat.shape[1] buf[:nrow, col0:col1] = dat[row0:row1] col0 = col1 if comp == 1: h5d_eri[row0:row1] = buf[:nrow] else: h5d_eri[icomp, row0:row1] = buf[:nrow] ti0 = log.timer( 'step 2 [%d/%d], [%d,%d:%d], row = %d' % (istep, totstep, icomp, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('cholesky_eri', *time0) return erifile
def cholesky_eri_b(mol, erifile, auxbasis='weigend+etb', dataname='j3c', int3c='int3c2e_sph', aosym='s2ij', int2c='int2c2e_sph', comp=1, ioblk_size=IOBLK_SIZE, auxmol=None, verbose=logger.NOTE): '''3-center 2-electron AO integrals ''' assert (aosym in ('s1', 's2ij')) log = logger.new_logger(mol, verbose) time0 = (time.clock(), time.time()) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) log.debug('size of aux basis %d', j2c.shape[0]) time1 = log.timer('2c2e', *time0) try: low = scipy.linalg.cholesky(j2c, lower=True) tag = 'cd' except scipy.linalg.LinAlgError: w, v = scipy.linalg.eigh(j2c) idx = w > LINEAR_DEP_THR low = (v[:, idx] / numpy.sqrt(w[idx])) v = None tag = 'eig' j2c = None naux = low.shape[0] time1 = log.timer('Cholesky 2c2e', *time1) feri = _create_h5file(erifile, dataname) for icomp in range(comp): feri.create_group('%s/%d' % (dataname, icomp)) # for h5py old version def store(b, label): if b.ndim == 3 and b.flags.f_contiguous: b = lib.transpose(b.T, axes=(0, 2, 1)).reshape(naux, -1) else: b = b.reshape((-1, naux)).T if tag == 'cd': cderi = scipy.linalg.solve_triangular(low, b, lower=True, overwrite_b=True) else: cderi = lib.dot(low.T, b) feri[label] = cderi int3c = gto.moleintor.ascint3(int3c) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] naoaux = ao_loc[-1] - nao if aosym == 's1': nao_pair = nao * nao buflen = min(max(int(ioblk_size * 1e6 / 8 / naoaux / comp), 1), nao_pair) shranges = _guess_shell_ranges(mol, buflen, 's1') else: nao_pair = nao * (nao + 1) // 2 buflen = min(max(int(ioblk_size * 1e6 / 8 / naoaux / comp), 1), nao_pair) shranges = _guess_shell_ranges(mol, buflen, 's2ij') log.debug('erifile %.8g MB, IO buf size %.8g MB', naoaux * nao_pair * 8 / 1e6, comp * buflen * naoaux * 8 / 1e6) if log.verbose >= logger.DEBUG1: log.debug1('shranges = %s', shranges) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) bufs1 = numpy.empty((comp * max([x[2] for x in shranges]), naoaux)) for istep, sh_range in enumerate(shranges): log.debug('int3c2e [%d/%d], AO [%d:%d], nrow = %d', \ istep+1, len(shranges), *sh_range) bstart, bend, nrow = sh_range shls_slice = (bstart, bend, 0, mol.nbas, mol.nbas, mol.nbas + auxmol.nbas) buf = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt, out=bufs1) if comp == 1: store(buf, '%s/0/%d' % (dataname, istep)) else: for icomp in range(comp): store(buf[icomp], '%s/%d/%d' % (dataname, icomp, istep)) time1 = log.timer('gen CD eri [%d/%d]' % (istep + 1, len(shranges)), *time1) buf = bufs1 = None feri.close() return erifile
def general(mol, mo_coeffs, erifile, auxbasis='weigend+etb', dataname='eri_mo', tmpdir=None, int3c='int3c2e_sph', aosym='s2ij', int2c='int2c2e_sph', comp=1, max_memory=MAX_MEMORY, ioblk_size=IOBLK_SIZE, verbose=0, compact=True): ''' Transform ij of (ij|L) to MOs. ''' assert (aosym in ('s1', 's2ij')) time0 = (time.clock(), time.time()) log = logger.new_logger(mol, verbose) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, ioblk_size, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('AO->MO eri transformation 1 pass', *time0) nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] nao = mo_coeffs[0].shape[0] auxmol = make_auxmol(mol, auxbasis) naoaux = auxmol.nao_nr() if aosym == 's1': nao_pair = nao * nao aosym_as_nr_e2 = 's1' else: nao_pair = nao * (nao + 1) // 2 aosym_as_nr_e2 = 's2kl' ijmosym, nij_pair, moij, ijshape = \ ao2mo.incore._conc_mos(mo_coeffs[0], mo_coeffs[1], compact and aosym != 's1') feri = _create_h5file(erifile, dataname) if comp == 1: chunks = (min(int(64e3 / nmoj), naoaux), nmoj) # 512K h5d_eri = feri.create_dataset(dataname, (naoaux, nij_pair), 'f8', chunks=chunks) else: chunks = (1, min(int(64e3 / nmoj), naoaux), nmoj) # 512K h5d_eri = feri.create_dataset(dataname, (comp, naoaux, nij_pair), 'f8', chunks=chunks) aopairblks = len(fswap[dataname + '/0']) iolen = min(int(ioblk_size * 1e6 / 8 / (nao_pair + nij_pair)), naoaux) totstep = (naoaux + iolen - 1) // iolen * comp buf = numpy.empty((iolen, nao_pair)) ti0 = time1 for icomp in range(comp): istep = 0 for row0, row1 in lib.prange(0, naoaux, iolen): nrow = row1 - row0 istep += 1 log.debug('step 2 [%d/%d], [%d,%d:%d], row = %d', istep, totstep, icomp, row0, row1, nrow) col0 = 0 for ic in range(aopairblks): dat = fswap['%s/%d/%d' % (dataname, icomp, ic)] col1 = col0 + dat.shape[1] buf[:nrow, col0:col1] = dat[row0:row1] col0 = col1 buf1 = _ao2mo.nr_e2(buf[:nrow], moij, ijshape, aosym_as_nr_e2, ijmosym) if comp == 1: h5d_eri[row0:row1] = buf1 else: h5d_eri[icomp, row0:row1] = buf1 ti0 = log.timer( 'step 2 [%d/%d], [%d,%d:%d], row = %d' % (istep, totstep, icomp, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('AO->MO CD eri transformation 2 pass', *time1) log.timer('AO->MO CD eri transformation', *time0) return erifile
def cholesky_eri_b(mol, erifile, auxbasis='weigend+etb', dataname='j3c', int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, max_memory=MAX_MEMORY, auxmol=None, verbose=logger.NOTE): '''3-center 2-electron DF tensor. Similar to cholesky_eri while this function stores DF tensor in blocks. ''' assert (aosym in ('s1', 's2ij')) log = logger.new_logger(mol, verbose) time0 = (time.clock(), time.time()) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) log.debug('size of aux basis %d', j2c.shape[0]) time1 = log.timer('2c2e', *time0) try: low = scipy.linalg.cholesky(j2c, lower=True) tag = 'cd' except scipy.linalg.LinAlgError: w, v = scipy.linalg.eigh(j2c) idx = w > LINEAR_DEP_THR low = (v[:, idx] / numpy.sqrt(w[idx])) v = None tag = 'eig' j2c = None naoaux, naux = low.shape time1 = log.timer('Cholesky 2c2e', *time1) int3c = gto.moleintor.ascint3(mol._add_suffix(int3c)) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] naoaux = ao_loc[-1] - nao if aosym == 's1': nao_pair = nao * nao buflen = min(max(int(max_memory * .24e6 / 8 / naoaux / comp), 1), nao_pair) shranges = _guess_shell_ranges(mol, buflen, 's1') else: nao_pair = nao * (nao + 1) // 2 buflen = min(max(int(max_memory * .24e6 / 8 / naoaux / comp), 1), nao_pair) shranges = _guess_shell_ranges(mol, buflen, 's2ij') log.debug('erifile %.8g MB, IO buf size %.8g MB', naoaux * nao_pair * 8 / 1e6, comp * buflen * naoaux * 8 / 1e6) log.debug1('shranges = %s', shranges) # TODO: Libcint-3.14 and newer version support to compute int3c2e without # the opt for the 3rd index. #if '3c2e' in int3c: # cintopt = gto.moleintor.make_cintopt(atm, mol._bas, env, int3c) #else: # cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) bufs1 = numpy.empty((comp * max([x[2] for x in shranges]), naoaux)) feri = _create_h5file(erifile, dataname) def store(buf, label): if comp == 1: feri[label] = buf else: shape = (len(buf), ) + buf[0].shape fdat = feri.create_dataset(label, shape, buf[0].dtype.char) for i, b in enumerate(buf): fdat[i] = b def transform(b): if b.ndim == 3 and b.flags.f_contiguous: b = lib.transpose(b.T, axes=(0, 2, 1)).reshape(naoaux, -1) else: b = b.reshape((-1, naoaux)).T if tag == 'cd': if b.flags.c_contiguous: b = lib.transpose(b).T return scipy.linalg.solve_triangular(low, b, lower=True, overwrite_b=True, check_finite=False) else: return lib.dot(low.T, b) with lib.call_in_background(store) as bstore: for istep, sh_range in enumerate(shranges): log.debug('int3c2e [%d/%d], AO [%d:%d], nrow = %d', \ istep+1, len(shranges), *sh_range) bstart, bend, nrow = sh_range shls_slice = (bstart, bend, 0, mol.nbas, mol.nbas, mol.nbas + auxmol.nbas) ints = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt, out=bufs1) if comp == 1: buf = transform(ints) else: buf = [transform(x) for x in ints] bstore(buf, '%s/%d' % (dataname, istep)) buf = ints = None time1 = log.timer( 'gen CD eri [%d/%d]' % (istep + 1, len(shranges)), *time1) bufs1 = None feri.close() return erifile
def cholesky_eri(mol, erifile, auxbasis='weigend+etb', dataname='eri_mo', tmpdir=None, int3c='int3c2e_sph', aosym='s2ij', int2c='int2c2e_sph', comp=1, max_memory=2000, ioblk_size=256, auxmol=None, verbose=0): '''3-center 2-electron AO integrals ''' assert(aosym in ('s1', 's2ij')) assert(comp == 1) time0 = (time.clock(), time.time()) if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(mol.stdout, verbose) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, ioblk_size, auxmol, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('generate (ij|L) 1 pass', *time0) nao = mol.nao_nr() naoaux = auxmol.nao_nr() aosym = _stand_sym_code(aosym) if aosym == 's1': nao_pair = nao * nao else: nao_pair = nao * (nao+1) // 2 if h5py.is_hdf5(erifile): feri = h5py.File(erifile) if dataname in feri: del(feri[dataname]) else: feri = h5py.File(erifile, 'w') if comp == 1: chunks = (min(int(16e3/nao),naoaux), nao) # 128K h5d_eri = feri.create_dataset(dataname, (naoaux,nao_pair), 'f8', chunks=chunks) else: chunks = (1, min(int(16e3/nao),naoaux), nao) # 128K h5d_eri = feri.create_dataset(dataname, (comp,naoaux,nao_pair), 'f8', chunks=chunks) aopairblks = len(fswap[dataname+'/0']) ioblk_size = max(max_memory*.1, ioblk_size) iolen = min(max(int(ioblk_size*1e6/8/nao_pair), 28), naoaux) totstep = (naoaux+iolen-1)//iolen * comp buf = numpy.empty((iolen, nao_pair)) ti0 = time1 for icomp in range(comp): istep = 0 for row0, row1 in prange(0, naoaux, iolen): nrow = row1 - row0 istep += 1 col0 = 0 for ic in range(aopairblks): dat = fswap['%s/%d/%d'%(dataname,icomp,ic)] col1 = col0 + dat.shape[1] buf[:nrow,col0:col1] = dat[row0:row1] col0 = col1 if comp == 1: h5d_eri[row0:row1] = buf[:nrow] else: h5d_eri[icomp,row0:row1] = buf[:nrow] ti0 = log.timer('step 2 [%d/%d], [%d,%d:%d], row = %d'% (istep, totstep, icomp, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('cholesky_eri', *time0) return erifile
def cholesky_eri_b(mol, erifile, auxbasis='weigend+etb', dataname='j3c', int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, ioblk_size=IOBLK_SIZE, auxmol=None, verbose=logger.NOTE): '''3-center 2-electron AO integrals ''' assert(aosym in ('s1', 's2ij')) log = logger.new_logger(mol, verbose) time0 = (time.clock(), time.time()) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) log.debug('size of aux basis %d', j2c.shape[0]) time1 = log.timer('2c2e', *time0) try: low = scipy.linalg.cholesky(j2c, lower=True) tag = 'cd' except scipy.linalg.LinAlgError: w, v = scipy.linalg.eigh(j2c) idx = w > LINEAR_DEP_THR low = (v[:,idx] / numpy.sqrt(w[idx])) v = None tag = 'eig' j2c = None naux = low.shape[0] time1 = log.timer('Cholesky 2c2e', *time1) feri = _create_h5file(erifile, dataname) for icomp in range(comp): feri.create_group('%s/%d'%(dataname,icomp)) # for h5py old version def store(b, label): if b.ndim == 3 and b.flags.f_contiguous: b = lib.transpose(b.T, axes=(0,2,1)).reshape(naux,-1) else: b = b.reshape((-1,naux)).T if tag == 'cd': cderi = scipy.linalg.solve_triangular(low, b, lower=True, overwrite_b=True) else: cderi = lib.dot(low.T, b) feri[label] = cderi int3c = mol._add_suffix(int3c) int3c = gto.moleintor.ascint3(int3c) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] naoaux = ao_loc[-1] - nao if aosym == 's1': nao_pair = nao * nao buflen = min(max(int(ioblk_size*1e6/8/naoaux/comp), 1), nao_pair) shranges = _guess_shell_ranges(mol, buflen, 's1') else: nao_pair = nao * (nao+1) // 2 buflen = min(max(int(ioblk_size*1e6/8/naoaux/comp), 1), nao_pair) shranges = _guess_shell_ranges(mol, buflen, 's2ij') log.debug('erifile %.8g MB, IO buf size %.8g MB', naoaux*nao_pair*8/1e6, comp*buflen*naoaux*8/1e6) if log.verbose >= logger.DEBUG1: log.debug1('shranges = %s', shranges) # TODO: Libcint-3.14 and newer version support to compute int3c2e without # the opt for the 3rd index. #if '3c2e' in int3c: # cintopt = gto.moleintor.make_cintopt(atm, mol._bas, env, int3c) #else: # cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) bufs1 = numpy.empty((comp*max([x[2] for x in shranges]),naoaux)) for istep, sh_range in enumerate(shranges): log.debug('int3c2e [%d/%d], AO [%d:%d], nrow = %d', \ istep+1, len(shranges), *sh_range) bstart, bend, nrow = sh_range shls_slice = (bstart, bend, 0, mol.nbas, mol.nbas, mol.nbas+auxmol.nbas) buf = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt, out=bufs1) if comp == 1: store(buf, '%s/0/%d'%(dataname,istep)) else: for icomp in range(comp): store(buf[icomp], '%s/%d/%d'%(dataname,icomp,istep)) time1 = log.timer('gen CD eri [%d/%d]' % (istep+1,len(shranges)), *time1) buf = bufs1 = None feri.close() return erifile
def get_j(dfobj, dm, hermi=1, direct_scf_tol=1e-13): from pyscf.scf import _vhf from pyscf.scf import jk from pyscf.df import addons t0 = t1 = (time.clock(), time.time()) mol = dfobj.mol if dfobj._vjopt is None: dfobj.auxmol = auxmol = addons.make_auxmol(mol, dfobj.auxbasis) opt = _vhf.VHFOpt(mol, 'int3c2e', 'CVHFnr3c2e_schwarz_cond') opt.direct_scf_tol = direct_scf_tol # q_cond part 1: the regular int2e (ij|ij) for mol's basis opt.init_cvhf_direct(mol, 'int2e', 'CVHFsetnr_direct_scf') mol_q_cond = lib.frompointer(opt._this.contents.q_cond, mol.nbas**2) # Update q_cond to include the 2e-integrals (auxmol|auxmol) j2c = auxmol.intor('int2c2e', hermi=1) j2c_diag = numpy.sqrt(abs(j2c.diagonal())) aux_loc = auxmol.ao_loc aux_q_cond = [ j2c_diag[i0:i1].max() for i0, i1 in zip(aux_loc[:-1], aux_loc[1:]) ] q_cond = numpy.hstack((mol_q_cond, aux_q_cond)) fsetqcond = _vhf.libcvhf.CVHFset_q_cond fsetqcond(opt._this, q_cond.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(q_cond.size)) try: opt.j2c = j2c = scipy.linalg.cho_factor(j2c, lower=True) opt.j2c_type = 'cd' except scipy.linalg.LinAlgError: opt.j2c = j2c opt.j2c_type = 'regular' # jk.get_jk function supports 4-index integrals. Use bas_placeholder # (l=0, nctr=1, 1 function) to hold the last index. bas_placeholder = numpy.array([0, 0, 1, 1, 0, 0, 0, 0], dtype=numpy.int32) fakemol = mol + auxmol fakemol._bas = numpy.vstack((fakemol._bas, bas_placeholder)) opt.fakemol = fakemol dfobj._vjopt = opt t1 = logger.timer_debug1(dfobj, 'df-vj init_direct_scf', *t1) opt = dfobj._vjopt fakemol = opt.fakemol dm = numpy.asarray(dm, order='C') dm_shape = dm.shape nao = dm_shape[-1] dm = dm.reshape(-1, nao, nao) n_dm = dm.shape[0] # First compute the density in auxiliary basis # j3c = fauxe2(mol, auxmol) # jaux = numpy.einsum('ijk,ji->k', j3c, dm) # rho = numpy.linalg.solve(auxmol.intor('int2c2e'), jaux) nbas = mol.nbas nbas1 = mol.nbas + dfobj.auxmol.nbas shls_slice = (0, nbas, 0, nbas, nbas, nbas1, nbas1, nbas1 + 1) with lib.temporary_env(opt, prescreen='CVHFnr3c2e_vj_pass1_prescreen', _dmcondname='CVHFsetnr_direct_scf_dm'): jaux = jk.get_jk(fakemol, dm, ['ijkl,ji->kl'] * n_dm, 'int3c2e', aosym='s2ij', hermi=0, shls_slice=shls_slice, vhfopt=opt) # remove the index corresponding to bas_placeholder jaux = numpy.array(jaux)[:, :, 0] t1 = logger.timer_debug1(dfobj, 'df-vj pass 1', *t1) if opt.j2c_type == 'cd': rho = scipy.linalg.cho_solve(opt.j2c, jaux.T) else: rho = scipy.linalg.solve(opt.j2c, jaux.T) # transform rho to shape (:,1,naux), to adapt to 3c2e integrals (ij|k) rho = rho.T[:, numpy.newaxis, :] t1 = logger.timer_debug1(dfobj, 'df-vj solve ', *t1) # Next compute the Coulomb matrix # j3c = fauxe2(mol, auxmol) # vj = numpy.einsum('ijk,k->ij', j3c, rho) with lib.temporary_env(opt, prescreen='CVHFnr3c2e_vj_pass2_prescreen', _dmcondname=None): # CVHFnr3c2e_vj_pass2_prescreen requires custom dm_cond aux_loc = dfobj.auxmol.ao_loc dm_cond = [ abs(rho[:, :, i0:i1]).max() for i0, i1 in zip(aux_loc[:-1], aux_loc[1:]) ] dm_cond = numpy.array(dm_cond) fsetcond = _vhf.libcvhf.CVHFset_dm_cond fsetcond(opt._this, dm_cond.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(dm_cond.size)) vj = jk.get_jk(fakemol, rho, ['ijkl,lk->ij'] * n_dm, 'int3c2e', aosym='s2ij', hermi=1, shls_slice=shls_slice, vhfopt=opt) t1 = logger.timer_debug1(dfobj, 'df-vj pass 2', *t1) logger.timer(dfobj, 'df-vj', *t0) return numpy.asarray(vj).reshape(dm_shape)
def general(mol, mo_coeffs, erifile, auxbasis='weigend+etb', dataname='eri_mo', tmpdir=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, max_memory=MAX_MEMORY, ioblk_size=IOBLK_SIZE, verbose=0, compact=True): ''' Transform ij of (ij|L) to MOs. ''' assert(aosym in ('s1', 's2ij')) time0 = (time.clock(), time.time()) log = logger.new_logger(mol, verbose) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, ioblk_size, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('AO->MO eri transformation 1 pass', *time0) nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] nao = mo_coeffs[0].shape[0] auxmol = make_auxmol(mol, auxbasis) naoaux = auxmol.nao_nr() if aosym == 's1': nao_pair = nao * nao aosym_as_nr_e2 = 's1' else: nao_pair = nao * (nao+1) // 2 aosym_as_nr_e2 = 's2kl' ijmosym, nij_pair, moij, ijshape = \ ao2mo.incore._conc_mos(mo_coeffs[0], mo_coeffs[1], compact and aosym != 's1') feri = _create_h5file(erifile, dataname) if comp == 1: chunks = (min(int(64e3/nmoj),naoaux), nmoj) # 512K h5d_eri = feri.create_dataset(dataname, (naoaux,nij_pair), 'f8', chunks=chunks) else: chunks = (1, min(int(64e3/nmoj),naoaux), nmoj) # 512K h5d_eri = feri.create_dataset(dataname, (comp,naoaux,nij_pair), 'f8', chunks=chunks) aopairblks = len(fswap[dataname+'/0']) iolen = min(int(ioblk_size*1e6/8/(nao_pair+nij_pair)), naoaux) totstep = (naoaux+iolen-1)//iolen * comp buf = numpy.empty((iolen, nao_pair)) ti0 = time1 for icomp in range(comp): istep = 0 for row0, row1 in lib.prange(0, naoaux, iolen): nrow = row1 - row0 istep += 1 log.debug('step 2 [%d/%d], [%d,%d:%d], row = %d', istep, totstep, icomp, row0, row1, nrow) col0 = 0 for ic in range(aopairblks): dat = fswap['%s/%d/%d'%(dataname,icomp,ic)] col1 = col0 + dat.shape[1] buf[:nrow,col0:col1] = dat[row0:row1] col0 = col1 buf1 = _ao2mo.nr_e2(buf[:nrow], moij, ijshape, aosym_as_nr_e2, ijmosym) if comp == 1: h5d_eri[row0:row1] = buf1 else: h5d_eri[icomp,row0:row1] = buf1 ti0 = log.timer('step 2 [%d/%d], [%d,%d:%d], row = %d'% (istep, totstep, icomp, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('AO->MO CD eri transformation 2 pass', *time1) log.timer('AO->MO CD eri transformation', *time0) return erifile
def cholesky_eri(mol, erifile, auxbasis='weigend+etb', dataname='j3c', tmpdir=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, max_memory=MAX_MEMORY, ioblk_size=IOBLK_SIZE, auxmol=None, verbose=logger.NOTE): '''3-center 2-electron AO integrals ''' assert(aosym in ('s1', 's2ij')) assert(comp == 1) log = logger.new_logger(mol, verbose) time0 = (time.clock(), time.time()) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, ioblk_size, auxmol, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('generate (ij|L) 1 pass', *time0) nao = mol.nao_nr() # Cannot let naoaux = auxmol.nao_nr() if auxbasis has linear dependence naoaux = fswap['%s/0/0'%dataname].shape[0] if aosym == 's1': nao_pair = nao * nao else: nao_pair = nao * (nao+1) // 2 feri = _create_h5file(erifile, dataname) if comp == 1: chunks = (min(int(16e3/nao),naoaux), nao) # 128K h5d_eri = feri.create_dataset(dataname, (naoaux,nao_pair), 'f8', chunks=chunks) else: chunks = (1, min(int(16e3/nao),naoaux), nao) # 128K h5d_eri = feri.create_dataset(dataname, (comp,naoaux,nao_pair), 'f8', chunks=chunks) aopairblks = len(fswap[dataname+'/0']) ioblk_size = max(max_memory*.1, ioblk_size) iolen = min(max(int(ioblk_size*1e6/8/nao_pair), 28), naoaux) totstep = (naoaux+iolen-1)//iolen * comp buf = numpy.empty((iolen, nao_pair)) ti0 = time1 for icomp in range(comp): istep = 0 for row0, row1 in lib.prange(0, naoaux, iolen): nrow = row1 - row0 istep += 1 col0 = 0 for ic in range(aopairblks): dat = fswap['%s/%d/%d'%(dataname,icomp,ic)] col1 = col0 + dat.shape[1] buf[:nrow,col0:col1] = dat[row0:row1] col0 = col1 if comp == 1: h5d_eri[row0:row1] = buf[:nrow] else: h5d_eri[icomp,row0:row1] = buf[:nrow] ti0 = log.timer('step 2 [%d/%d], [%d,%d:%d], row = %d'% (istep, totstep, icomp, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('cholesky_eri', *time0) return erifile
def general(mol, mo_coeffs, erifile, auxbasis='weigend+etb', dataname='eri_mo', tmpdir=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, max_memory=MAX_MEMORY, verbose=0, compact=True): ''' Transform ij of (ij|L) to MOs. ''' assert (aosym in ('s1', 's2ij')) time0 = (time.clock(), time.time()) log = logger.new_logger(mol, verbose) if tmpdir is None: tmpdir = lib.param.TMPDIR swapfile = tempfile.NamedTemporaryFile(dir=tmpdir) cholesky_eri_b(mol, swapfile.name, auxbasis, dataname, int3c, aosym, int2c, comp, max_memory, verbose=log) fswap = h5py.File(swapfile.name, 'r') time1 = log.timer('AO->MO eri transformation 1 pass', *time0) nmoi = mo_coeffs[0].shape[1] nmoj = mo_coeffs[1].shape[1] nao = mo_coeffs[0].shape[0] auxmol = make_auxmol(mol, auxbasis) if aosym == 's1': nao_pair = nao * nao aosym_as_nr_e2 = 's1' else: nao_pair = nao * (nao + 1) // 2 aosym_as_nr_e2 = 's2kl' ijmosym, nij_pair, moij, ijshape = \ ao2mo.incore._conc_mos(mo_coeffs[0], mo_coeffs[1], compact and aosym != 's1') naoaux = fswap['%s/0' % dataname].shape[-2] feri = _create_h5file(erifile, dataname) if comp == 1: h5d_eri = feri.create_dataset(dataname, (naoaux, nij_pair), 'f8') else: h5d_eri = feri.create_dataset(dataname, (comp, naoaux, nij_pair), 'f8') def save(row0, row1, buf): if comp == 1: h5d_eri[row0:row1] = buf else: h5d_eri[:, row0:row1] = buf iolen = min(max(int(max_memory * .45e6 / 8 / (nao_pair + nij_pair)), 28), naoaux) totstep = (naoaux + iolen - 1) // iolen ti0 = time1 with lib.call_in_background(save) as bsave: for istep, (row0, row1) in enumerate(lib.prange(0, naoaux, iolen)): nrow = row1 - row0 log.debug('step 2 [%d/%d], [%d:%d], row = %d', istep + 1, totstep, row0, row1, nrow) buf = _load_from_h5g(fswap[dataname], row0, row1) if comp == 1: buf = _ao2mo.nr_e2(buf, moij, ijshape, aosym_as_nr_e2, ijmosym) bsave(row0, row1, buf) else: buf = _ao2mo.nr_e2(buf.reshape(comp * nrow, nao_pair), moij, ijshape, aosym_as_nr_e2, ijmosym) bsave(row0, row1, buf.reshape(comp, nrow, nij_pair)) buf = None ti0 = log.timer( 'step 2 [%d/%d], [%d:%d], row = %d' % (istep + 1, totstep, row0, row1, nrow), *ti0) fswap.close() feri.close() log.timer('AO->MO CD eri transformation 2 pass', *time1) log.timer('AO->MO CD eri transformation', *time0) return erifile
def format_aux_basis(mol, auxbasis='weigend+etb'): '''See also pyscf.df.addons.make_auxmol. This funciton is defined for backward compatibility. ''' return addons.make_auxmol(mol, auxbasis)
def loop(self): # direct blocksize mol = self.mol auxmol = self.auxmol = addons.make_auxmol(self.mol, self.auxbasis) if auxmol is None: auxmol = make_auxmol(mol, auxbasis) int3c='int3c2e' int3c = mol._add_suffix(int3c) int3c = gto.moleintor.ascint3(int3c) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] naoaux = ao_loc[-1] - nao # TODO: Libcint-3.14 and newer version support to compute int3c2e without # the opt for the 3rd index. #if '3c2e' in int3c: # cintopt = gto.moleintor.make_cintopt(atm, mol._bas, env, int3c) #else: # cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) comp = 1 aosym = 's2ij' # banlence the auxbasis by splitting shells segsize = (naoaux+mpi.pool.size-1) // mpi.pool.size global paux aa = 0 while naoaux-aa > segsize-1: aa = 0 j = 0 b1 = [] paux = [] for i in range(auxmol.nbas+1): if ao_loc[mol.nbas+i]-nao-aa > segsize and j < mpi.pool.size-1: paux.append(ao_loc[mol.nbas+i-1]-nao-aa) aa = ao_loc[mol.nbas+i-1]-nao b1.append(i-1) j += 1 if naoaux-aa <= segsize: b1.append(auxmol.nbas) paux.append(naoaux-aa) # average the last two to two+losted if len(b1) != mpi.pool.size: nb1 = len(b1) nbl2 = b1[nb1-1] - b1[nb1-3] vb0 = b1[nb1-3] b1 = b1[:nb1-2] paux = paux[:nb1-2] segs = nbl2 // (mpi.pool.size - nb1 +2) for i in range(mpi.pool.size - nb1 +1): vb1 = b1[nb1-3] + segs * (i+1) b1.append(vb1) paux.append(ao_loc[mol.nbas+vb1] - ao_loc[mol.nbas+vb0]) vb0 = vb1 vb1 = b1[mpi.pool.size-2] + nbl2 - (mpi.pool.size - nb1 +1)*segs b1.append(vb1) paux.append(ao_loc[mol.nbas+vb1] - ao_loc[mol.nbas+b1[mpi.pool.size-2]]) segsize += 1 stop = b1[rank] if rank ==0: start = 0 else: start = b1[rank-1] if start == stop: print('rank=',rank, '!!!!!- no shell in this rank, need less threads -!!!!!') print('aux basis',paux) print('aux shell',b1) ### use 1/10 of the block to adapt memory BLKSIZE = min(80, (stop-start)//10+1) for p0, p1 in lib.prange(start,stop, BLKSIZE): shls_slice = (0, mol.nbas, 0, mol.nbas, mol.nbas+p0, mol.nbas+p1) buf = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt) eri1 = numpy.asarray(buf.T, order='C') yield eri1
def cholesky_eri(mol, auxbasis='weigend+etb', auxmol=None, int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1, max_memory=MAX_MEMORY, verbose=0, fauxe2=aux_e2): ''' Returns: 2D array of (naux,nao*(nao+1)/2) in C-contiguous ''' from pyscf.df.outcore import _guess_shell_ranges assert (comp == 1) t0 = (time.clock(), time.time()) log = logger.new_logger(mol, verbose) if auxmol is None: auxmol = addons.make_auxmol(mol, auxbasis) j2c = auxmol.intor(int2c, hermi=1) try: low = scipy.linalg.cholesky(j2c, lower=True) tag = 'cd' except scipy.linalg.LinAlgError: w, v = scipy.linalg.eigh(j2c) idx = w > LINEAR_DEP_THR low = (v[:, idx] / numpy.sqrt(w[idx])) v = None tag = 'eig' j2c = None naoaux, naux = low.shape log.debug('size of aux basis %d', naux) t1 = log.timer_debug1('2c2e', *t0) int3c = gto.moleintor.ascint3(mol._add_suffix(int3c)) atm, bas, env = gto.mole.conc_env(mol._atm, mol._bas, mol._env, auxmol._atm, auxmol._bas, auxmol._env) ao_loc = gto.moleintor.make_loc(bas, int3c) nao = ao_loc[mol.nbas] if aosym == 's1': nao_pair = nao * nao else: nao_pair = nao * (nao + 1) // 2 cderi = numpy.empty((naux, nao_pair)) max_words = max_memory * .98e6 / 8 - low.size - cderi.size # Divide by 3 because scipy.linalg.solve may create a temporary copy for # ints and return another copy for results buflen = min(max(int(max_words / naoaux / comp / 3), 8), nao_pair) shranges = _guess_shell_ranges(mol, buflen, aosym) log.debug1('shranges = %s', shranges) cintopt = gto.moleintor.make_cintopt(atm, bas, env, int3c) bufs1 = numpy.empty((comp * max([x[2] for x in shranges]), naoaux)) bufs2 = numpy.empty_like(bufs1) p1 = 0 for istep, sh_range in enumerate(shranges): log.debug('int3c2e [%d/%d], AO [%d:%d], nrow = %d', istep + 1, len(shranges), *sh_range) bstart, bend, nrow = sh_range shls_slice = (bstart, bend, 0, mol.nbas, mol.nbas, mol.nbas + auxmol.nbas) ints = gto.moleintor.getints3c(int3c, atm, bas, env, shls_slice, comp, aosym, ao_loc, cintopt, out=bufs1) if ints.ndim == 3 and ints.flags.f_contiguous: ints = lib.transpose(ints.T, axes=(0, 2, 1), out=bufs2).reshape(naoaux, -1) bufs1, bufs2 = bufs2, bufs1 else: ints = ints.reshape((-1, naoaux)).T p0, p1 = p1, p1 + nrow if tag == 'cd': if ints.flags.c_contiguous: ints = lib.transpose(ints, out=bufs2).T bufs1, bufs2 = bufs2, bufs1 dat = scipy.linalg.solve_triangular(low, ints, lower=True, overwrite_b=True, check_finite=False) if dat.flags.f_contiguous: dat = lib.transpose(dat.T, out=bufs2) cderi[:, p0:p1] = dat else: dat = numpy.ndarray((naux, ints.shape[1]), buffer=bufs2) cderi[:, p0:p1] = lib.dot(low.T, ints, c=dat) dat = ints = None log.timer('cholesky_eri', *t0) return cderi
def _rs_build(self): log = logger.Logger(self.stdout, self.verbose) # find kmax kpts = self.kpts if self.kpts_band is None else np.vstack( [self.kpts, self.kpts_band]) b = self.cell.reciprocal_vectors() scaled_kpts = np.linalg.solve(b.T, kpts.T).T scaled_kpts[scaled_kpts > 0.49999999] -= 1 kpts = np.dot(scaled_kpts, b) kmax = np.linalg.norm(kpts, axis=-1).max() scaled_kpts = kpts = None if kmax < 1.e-3: kmax = (0.75 / np.pi / self.cell.vol)**0.33333333 * 2 * np.pi # If omega is not given, estimate it from npw_max r2o = True if self.omega is None: self.omega, self.ke_cutoff, mesh_compact = \ rsdf_helper.estimate_omega_for_npw( self.cell, self.npw_max, self.precision_G, kmax=kmax, round2odd=r2o) # if omega from npw_max is too small, use omega_min if self.omega < self._omega_min: self.omega = self._omega_min self.ke_cutoff, mesh_compact = \ rsdf_helper.estimate_mesh_for_omega( self.cell, self.omega, self.precision_G, kmax=kmax, round2odd=r2o) # Use the thus determined mesh_compact only if not p[rovided if self.mesh_compact is None: self.mesh_compact = mesh_compact # If omega is provded but mesh_compact is not elif self.mesh_compact is None: self.ke_cutoff, self.mesh_compact = \ rsdf_helper.estimate_mesh_for_omega( self.cell, self.omega, self.precision_G, kmax=kmax, round2odd=r2o) # build auxcell from pyscf.df.addons import make_auxmol auxcell = make_auxmol(self.cell, self.auxbasis) # drop exponents drop_eta = self.exp_to_discard if drop_eta is not None and drop_eta > 0: log.info("Drop primitive fitting functions with exponent < %s", drop_eta) auxbasis = rsdf_helper.remove_exp_basis(auxcell._basis, amin=drop_eta) auxcellnew = make_auxmol(self.cell, auxbasis) auxcell = auxcellnew # determine mesh for computing j2c auxcell.precision = self.precision_j2c auxcell.rcut = max([ auxcell.bas_rcut(ib, auxcell.precision) for ib in range(auxcell.nbas) ]) if self.mesh_j2c is None: self.mesh_j2c = rsdf_helper.estimate_mesh_for_omega( auxcell, self.omega_j2c, round2odd=True)[1] self.auxcell = auxcell