def make_modchg_basis(auxcell, smooth_eta, l_max=3): # * chgcell defines smooth gaussian functions for each angular momentum for # auxcell. The smooth functions may be used to carry the charge chgcell = copy.copy( auxcell) # smooth model density for coulomb integral to carry charge half_sph_norm = .5 / numpy.sqrt(numpy.pi) chg_bas = [] chg_env = [smooth_eta] ptr_eta = auxcell._env.size ptr = ptr_eta + 1 for ia in range(auxcell.natm): for l in set(auxcell._bas[auxcell._bas[:, gto.ATOM_OF] == ia, gto.ANG_OF]): if l <= l_max: norm = half_sph_norm / gto.mole._gaussian_int( l * 2 + 2, smooth_eta) chg_bas.append([ia, l, 1, 1, 0, ptr_eta, ptr, 0]) chg_env.append(norm) ptr += 1 chgcell._atm = auxcell._atm chgcell._bas = numpy.asarray(chg_bas, dtype=numpy.int32).reshape(-1, gto.BAS_SLOTS) chgcell._env = numpy.hstack((auxcell._env, chg_env)) chgcell._built = True logger.debug1(auxcell, 'make smooth basis, num shells = %d, num cGTOs = %d', chgcell.nbas, chgcell.nao_nr()) return chgcell
def dump_flags(self): log = logger.Logger(self.stdout, self.verbose) logger.info(self, '\n') logger.info(self, '******** %s flags ********', self.__class__) logger.info(self, 'gs = %s', self.gs) logger.info(self, 'len(kpts) = %d', len(self.kpts)) logger.debug1(self, ' kpts = %s', self.kpts)
def update(self, s, d, f, *args, **kwargs): errvec = get_err_vec(s, d, f) logger.debug1(self, 'diis-norm(errvec)=%g', numpy.linalg.norm(errvec)) xnew = lib.diis.DIIS.update(self, f, xerr=errvec) if self.rollback > 0 and len(self._bookkeep) == self.space: self._bookkeep = self._bookkeep[-self.rollback:] return xnew
def unpackE4_BLOCK(self, fname, norb): # The 4RDMs written by "Fourpdm_container::save_spatial_npdm_binary" in BLOCK # are written as E4[i1,j2,k3,l4,m4,n3,o2,p1] # and are stored here as E4[i1,j2,k3,l4,p1,o2,n3,m4] # This is done with SQA in mind. E4 = numpy.zeros((norb, norb, norb, norb, norb, norb, norb, norb), order='F') fil = open(fname, "rb") logger.debug1( self, "[fil.seek(not_really_understood)]: HOW DANGEROUS IS THAT ???!?!?!?" ) fil.seek(109) # HOW DANGEROUS IS THAT ???!?!?!? for a in range(norb): for b in range(norb): for c in range(norb): for d in range(norb): for e in range(norb): for f in range(norb): for g in range(norb): for h in range(norb): (value, ) = struct.unpack( 'd', fil.read(8)) E4[a, b, c, d, h, g, f, e] = value try: (value, ) = struct.unpack('c', fil.read(1)) logger.warn(self, "MORE bytes TO READ!") except: logger.warn(self, "AT LEAST, NO MORE bytes TO READ!") #exit(0) fil.close() return E4
def make_modchg_basis(auxcell, smooth_eta): # * chgcell defines smooth gaussian functions for each angular momentum for # auxcell. The smooth functions may be used to carry the charge chgcell = copy.copy(auxcell) # smooth model density for coulomb integral to carry charge half_sph_norm = .5/numpy.sqrt(numpy.pi) chg_bas = [] chg_env = [smooth_eta] ptr_eta = auxcell._env.size ptr = ptr_eta + 1 l_max = auxcell._bas[:,gto.ANG_OF].max() # gaussian_int(l*2+2) for multipole integral: # \int (r^l e^{-ar^2} * Y_{lm}) (r^l Y_{lm}) r^2 dr d\Omega norms = [half_sph_norm/gto.gaussian_int(l*2+2, smooth_eta) for l in range(l_max+1)] for ia in range(auxcell.natm): for l in set(auxcell._bas[auxcell._bas[:,gto.ATOM_OF]==ia, gto.ANG_OF]): chg_bas.append([ia, l, 1, 1, 0, ptr_eta, ptr, 0]) chg_env.append(norms[l]) ptr += 1 chgcell._atm = auxcell._atm chgcell._bas = numpy.asarray(chg_bas, dtype=numpy.int32).reshape(-1,gto.BAS_SLOTS) chgcell._env = numpy.hstack((auxcell._env, chg_env)) chgcell.rcut = _estimate_rcut(smooth_eta, l_max, 1., auxcell.precision) logger.debug1(auxcell, 'make compensating basis, num shells = %d, num cGTOs = %d', chgcell.nbas, chgcell.nao_nr()) logger.debug1(auxcell, 'chgcell.rcut %s', chgcell.rcut) return chgcell
def jk_method(self, J='FFTDF', K=None): ''' Set up the schemes to evaluate Coulomb and exchange matrix FFTDF: planewave density fitting using Fast Fourier Transform AFTDF: planewave density fitting using analytic Fourier Transform GDF: Gaussian density fitting MDF: Gaussian and planewave mix density fitting RS: range-separation JK builder RSDF: range-separation density fitting ''' if K is None: K = J if J != K: raise NotImplementedError('J != K') if 'DF' in J or 'DF' in K: if 'DF' in J and 'DF' in K: assert J == K else: df_method = J if 'DF' in J else K self.with_df = getattr(df, df_method)(self.cell, self.kpts) if 'RS' in J or 'RS' in K: self.rsjk = RangeSeparationJKBuilder(self.cell, self.kpts) self.rsjk.verbose = self.verbose # For nuclear attraction if J == 'RS' and K == 'RS' and not isinstance(self.with_df, df.GDF): self.with_df = df.GDF(self.cell, self.kpts) nuc = self.with_df.__class__.__name__ logger.debug1(self, 'Apply %s for J, %s for K, %s for nuc', J, K, nuc) return self
def unpackE3_BLOCK(self, fname, norb): # The 3RDMs written by "Threepdm_container::save_spatial_npdm_binary" in BLOCK # are written as E3[i1,j2,k3,l3,m2,n1] # and are stored here as E3[i1,j2,k3,n1,m2,l3] # This is done with SQA in mind. E3 = numpy.zeros((norb, norb, norb, norb, norb, norb), order='F') fil = open(fname, "rb") logger.debug1( self, "[fil.seek(not_really_understood)]: HOW DANGEROUS IS THAT ???!?!?!?" ) #fil.seek(93) # HOW DANGEROUS IS THAT ???!?!?!? fil.seek(53) # HOW DANGEROUS IS THAT ???!?!?!? for a in range(norb): for b in range(norb): for c in range(norb): for d in range(norb): for e in range(norb): for f in range(norb): (value, ) = struct.unpack('d', fil.read(8)) E3[a, b, c, f, e, d] = value try: (value, ) = struct.unpack('c', fil.read(1)) logger.warn(self, "MORE bytes TO READ!") except: logger.warn(self, "AT LEAST, NO MORE bytes TO READ!") #exit(0) fil.close() return E3
def get_occ(mf, mo_energy=None, mo_coeff=None): '''Label the occupancies for each orbital. NOTE the occupancies are not assigned based on the orbital energy ordering. The first N orbitals are assigned to be occupied orbitals. Examples: >>> mol = gto.M(atom='H 0 0 0; O 0 0 1.1', spin=1) >>> mf = scf.hf.SCF(mol) >>> energy = numpy.array([-10., -1., 1, -2., 0, -3]) >>> mf.get_occ(energy) array([2, 2, 2, 2, 1, 0]) ''' if mo_energy is None: mo_energy = mf.mo_energy if getattr(mo_energy, 'mo_ea', None) is not None: mo_ea = mo_energy.mo_ea mo_eb = mo_energy.mo_eb else: mo_ea = mo_eb = mo_energy nmo = mo_ea.size mo_occ = numpy.zeros(nmo) if getattr(mf, 'nelec', None) is None: nelec = mf.mol.nelec else: nelec = mf.nelec ncore = nelec[1] nocc = nelec[0] nopen = abs(nocc - ncore) mo_occ = _fill_rohf_occ(mo_energy, mo_ea, mo_eb, ncore, nopen) if mf.verbose >= logger.INFO and nocc < nmo and ncore > 0: ehomo = max(mo_energy[mo_occ> 0]) elumo = min(mo_energy[mo_occ==0]) if ehomo+1e-3 > elumo: logger.warn(mf, 'H**O %.15g >= LUMO %.15g', ehomo, elumo) else: logger.info(mf, ' H**O = %.15g LUMO = %.15g', ehomo, elumo) if nopen > 0 and mf.verbose >= logger.DEBUG: core_idx = mo_occ == 2 open_idx = mo_occ == 1 vir_idx = mo_occ == 0 logger.debug(mf, ' Roothaan | alpha | beta') logger.debug(mf, ' Highest 2-occ = %18.15g | %18.15g | %18.15g', max(mo_energy[core_idx]), max(mo_ea[core_idx]), max(mo_eb[core_idx])) logger.debug(mf, ' Lowest 0-occ = %18.15g | %18.15g | %18.15g', min(mo_energy[vir_idx]), min(mo_ea[vir_idx]), min(mo_eb[vir_idx])) for i in numpy.where(open_idx)[0]: logger.debug(mf, ' 1-occ = %18.15g | %18.15g | %18.15g', mo_energy[i], mo_ea[i], mo_eb[i]) if mf.verbose >= logger.DEBUG: numpy.set_printoptions(threshold=nmo) logger.debug(mf, ' Roothaan mo_energy =\n%s', mo_energy) logger.debug1(mf, ' alpha mo_energy =\n%s', mo_ea) logger.debug1(mf, ' beta mo_energy =\n%s', mo_eb) numpy.set_printoptions(threshold=1000) return mo_occ
def dump_flags(self): log = logger.Logger(self.stdout, self.verbose) logger.info(self, "\n") logger.info(self, "******** %s flags ********", self.__class__) logger.info(self, "gs = %s", self.gs) logger.info(self, "len(kpts) = %d", len(self.kpts)) logger.debug1(self, " kpts = %s", self.kpts)
def init_guess_by_atom(mol): '''Generate initial guess density matrix from superposition of atomic HF density matrix. The atomic HF is occupancy averaged RHF Returns: Density matrix, 2D ndarray ''' from pyscf.scf import atom_hf atm_scf = atom_hf.get_atm_nrhf(mol) nbf = mol.nao_nr() dm = numpy.zeros((nbf, nbf)) p0 = 0 for ia in range(mol.natm): symb = mol.atom_symbol(ia) if symb in atm_scf: e_hf, mo_e, mo_c, mo_occ = atm_scf[symb] else: symb = mol.atom_pure_symbol(ia) e_hf, mo_e, mo_c, mo_occ = atm_scf[symb] p1 = p0 + mo_e.__len__() dm[p0:p1,p0:p1] = numpy.dot(mo_c*mo_occ, mo_c.T.conj()) p0 = p1 for k, v in atm_scf.items(): logger.debug1(mol, 'Atom %s, E = %.12g', k, v[0]) return dm
def _symmetrize_canonicalization_(mf, mo_energy, mo_coeff, s): '''Restore symmetry for canonicalized orbitals ''' def search_for_degeneracy(mo_energy): idx = numpy.where(abs(mo_energy[1:] - mo_energy[:-1]) < 1e-6)[0] return numpy.unique(numpy.hstack((idx, idx + 1))) mol = mf.mol degidx = search_for_degeneracy(mo_energy) logger.debug1(mf, 'degidx %s', degidx) if degidx.size > 0: esub = mo_energy[degidx] csub = mo_coeff[:, degidx] scsub = numpy.dot(s, csub) emin = abs(esub).min() * .5 es = [] cs = [] for i, ir in enumerate(mol.irrep_id): so = mol.symm_orb[i] sosc = numpy.dot(so.T, scsub) s_ir = reduce(numpy.dot, (so.T, s, so)) fock_ir = numpy.dot(sosc * esub, sosc.T) mo_energy, u = mf._eigh(fock_ir, s_ir) idx = abs(mo_energy) > emin es.append(mo_energy[idx]) cs.append(numpy.dot(mol.symm_orb[i], u[:, idx])) es = numpy.hstack(es).round(7) idx = numpy.argsort(es, kind='mergesort') assert (numpy.allclose(es[idx], esub.round(7))) mo_coeff[:, degidx] = numpy.hstack(cs)[:, idx] return mo_coeff
def get_init_guess(self, mol=None, key='minao'): if mol is None: mol = self.mol if callable(key): dm = key(mol) elif key.lower() == '1e': dm = self.init_guess_by_1e(mol) elif getattr(mol, 'natm', 0) == 0: logger.info(self, 'No atom found in mol. Use 1e initial guess') dm = self.init_guess_by_1e(mol) elif key.lower() == 'atom': dm = self.init_guess_by_atom(mol) elif key.lower() == 'chkfile': try: dm = self.init_guess_by_chkfile() except (IOError, KeyError): logger.warn(self, 'Fail in reading %s. Use MINAO initial guess', self.chkfile) dm = self.init_guess_by_minao(mol) else: dm = self.init_guess_by_minao(mol) if self.verbose >= logger.DEBUG1: logger.debug1(self, 'Nelec from initial guess = %g', (dm * self.get_ovlp()).sum().real) return dm
def _symmetrize_canonicalization_(mol, mo_energy, mo_coeff, s): '''Restore symmetry for canonicalized orbitals ''' def search_for_degeneracy(mo_energy): idx = numpy.where(abs(mo_energy[1:] - mo_energy[:-1]) < 1e-6)[0] return numpy.unique(numpy.hstack((idx, idx+1))) degidx = search_for_degeneracy(mo_energy) logger.debug1(mol, 'degidx %s', degidx) if degidx.size > 0: esub = mo_energy[degidx] csub = mo_coeff[:,degidx] scsub = numpy.dot(s, csub) emin = abs(esub).min() * .5 es = [] cs = [] for i,ir in enumerate(mol.irrep_id): so = mol.symm_orb[i] sosc = numpy.dot(so.T, scsub) s_ir = reduce(numpy.dot, (so.T, s, so)) fock_ir = numpy.dot(sosc*esub, sosc.T) mo_energy, u = scipy.linalg.eigh(fock_ir, s_ir) idx = abs(mo_energy) > emin es.append(mo_energy[idx]) cs.append(numpy.dot(mol.symm_orb[i], u[:,idx])) es = numpy.hstack(es).round(9) idx = numpy.argsort(es) assert(numpy.allclose(es[idx], esub)) mo_coeff[:,degidx] = numpy.hstack(cs)[:,idx] return mo_coeff
def init_guess_by_atom(mol): '''Generate initial guess density matrix from superposition of atomic HF density matrix. The atomic HF is occupancy averaged RHF Returns: Density matrix, 2D ndarray ''' import copy from pyscf.scf import atom_hf from pyscf.scf import addons atm_scf = atom_hf.get_atm_nrhf(mol) mo = [] mo_occ = [] for ia in range(mol.natm): symb = mol.atom_symbol(ia) if symb != 'GHOST': if symb in atm_scf: e_hf, e, c, occ = atm_scf[symb] else: symb = mol.atom_pure_symbol(ia) e_hf, e, c, occ = atm_scf[symb] mo.append(c) mo_occ.append(occ) mo = scipy.linalg.block_diag(*mo) mo_occ = numpy.hstack(mo_occ) pmol = copy.copy(mol) pmol.cart = False c = addons.project_mo_nr2nr(pmol, mo, mol) dm = numpy.dot(c * mo_occ, c.T) for k, v in atm_scf.items(): logger.debug1(mol, 'Atom %s, E = %.12g', k, v[0]) return dm
def dump_flags(self, verbose=None): logger.info(self, '\n') logger.info(self, '******** %s ********', self.__class__) logger.info(self, 'mesh = %s (%d PWs)', self.mesh, numpy.prod(self.mesh)) logger.info(self, 'len(kpts) = %d', len(self.kpts)) logger.debug1(self, ' kpts = %s', self.kpts) return self
def get_init_guess(self, mol=None, key='minao'): if mol is None: mol = self.mol if callable(key): dm = key(mol) elif key.lower() == '1e': dm = self.init_guess_by_1e(mol) elif getattr(mol, 'natm', 0) == 0: logger.info(self, 'No atom found in mol. Use 1e initial guess') dm = self.init_guess_by_1e(mol) elif key.lower() == 'atom': dm = self.init_guess_by_atom(mol) elif key.lower().startswith('chk'): try: dm = self.init_guess_by_chkfile() except (IOError, KeyError): logger.warn(self, 'Fail in reading %s. Use MINAO initial guess', self.chkfile) dm = self.init_guess_by_minao(mol) else: dm = self.init_guess_by_minao(mol) if self.verbose >= logger.DEBUG1: s = self.get_ovlp() if isinstance(dm, numpy.ndarray) and dm.ndim == 2: nelec = (dm.T * s).sum() else: # UHF nelec = (dm[0].T * s).sum() + (dm[1].T * s).sum() logger.debug1(self, 'Nelec from initial guess = %g', nelec.real) return dm
def extrapolate(self, nd=None): if nd is None: nd = self.get_num_vec() if nd == 0: raise RuntimeError('No vector found in DIIS object.') h = self._H[:nd + 1, :nd + 1] g = numpy.zeros(nd + 1, h.dtype) g[0] = 1 w, v = scipy.linalg.eigh(h) if numpy.any(abs(w) < 1e-14): logger.debug(self, 'Linear dependence found in DIIS error vectors.') idx = abs(w) > 1e-14 c = numpy.dot(v[:, idx] * (1. / w[idx]), numpy.dot(v[:, idx].T.conj(), g)) else: try: c = numpy.linalg.solve(h, g) except numpy.linalg.linalg.LinAlgError as e: logger.warn(self, ' diis singular, eigh(h) %s', w) raise e logger.debug1(self, 'diis-c %s', c) xnew = None for i, ci in enumerate(c[1:]): xi = self.get_vec(i) if xnew is None: xnew = numpy.zeros(xi.size, c.dtype) for p0, p1 in misc.prange(0, xi.size, BLOCK_SIZE): xnew[p0:p1] += xi[p0:p1] * ci return xnew
def eig(self, f, s): mol = self.mol ao_ang = _angular_momentum_for_each_ao(mol) nao = mol.nao mo_coeff = [] mo_energy = [] for l in range(param.L_MAX): degen = 2 * l + 1 idx = numpy.where(ao_ang == l)[0] nao_l = len(idx) if nao_l > 0: nsh = nao_l // degen f_l = f[idx[:, None], idx].reshape(nsh, degen, nsh, degen) s_l = s[idx[:, None], idx].reshape(nsh, degen, nsh, degen) # Average over angular parts f_l = numpy.einsum('piqi->pq', f_l) / degen s_l = numpy.einsum('piqi->pq', s_l) / degen e, c = self._eigh(f_l, s_l) for i, ei in enumerate(e): logger.debug1(self, 'l = %d e_%d = %.9g', l, i, ei) mo_energy.append(numpy.repeat(e, degen)) mo = numpy.zeros((nao, nsh, degen)) for i in range(degen): mo[idx[i::degen], :, i] = c mo_coeff.append(mo.reshape(nao, nao_l)) return numpy.hstack(mo_energy), numpy.hstack(mo_coeff)
def nelec(self, mu): logger.debug1(self.__log__, "| requested mu={:.3e}".format( mu, )) result = [] total = 0 for ind, (i, c) in enumerate(zip(self.solvers, self.factors)): n = i.__hcore__.shape[0] // 2 i.__hcore__[:n, :n] -= numpy.eye(n) * mu i.kernel() i.__hcore__[:n, :n] += numpy.eye(n) * mu dm = i.make_rdm1() result.append(numpy.diag(dm)[:n].sum()) total += c*result[-1] logger.debug2(self.__log__, "| solver {:d} E={:.8f}".format( ind, i.e_tot, )) logger.debug1(self.__log__, "| occupations {} = {:.3e}".format( "+".join("{:.1f}*{:.3f}".format(i, j) for i, j in zip(self.factors, result)), total, )) return total-self.target
def get_occ(self, mo_energy=None, mo_coeff=None): '''spherically averaged fractional occupancy''' mol = self.mol symb = mol.atom_symbol(0) nelec_ecp = mol.atom_nelec_core(0) coreshl = gto.ecp.core_configuration(nelec_ecp) occ = [] for l in range(param.L_MAX): n2occ, frac = frac_occ(symb, l, self.atomic_configuration) degen = 2 * l + 1 idx = mol._bas[:, gto.ANG_OF] == l nbas_l = mol._bas[idx, gto.NCTR_OF].sum() if l < 4: n2occ -= coreshl[l] assert n2occ <= nbas_l logger.debug1(self, 'l = %d occ = %d + %.4g', l, n2occ, frac) occ_l = numpy.zeros(nbas_l) occ_l[:n2occ] = 2 if frac > 0: occ_l[n2occ] = frac occ.append(numpy.repeat(occ_l, degen)) else: occ.append(numpy.zeros(nbas_l * degen)) return numpy.hstack(occ)
def get_occ(self, mo_energy=None, mo_coeff=None): if mo_energy is None: mo_energy = self.mo_energy mol = self.mol c = lib.param.LIGHT_SPEED n4c = len(mo_energy) n2c = n4c // 2 mo_occ = numpy.zeros(n2c * 2) nocc = mol.nelectron if mo_energy[n2c] > -1.999 * c**2: mo_occ[n2c:n2c + nocc] = 1 else: logger.warn(self, 'Variational collapse. PES mo_energy %g < -2c^2', mo_energy[n2c]) lumo = mo_energy[mo_energy > -1.999 * c**2][nocc] mo_occ[mo_energy > -1.999 * c**2] = 1 mo_occ[mo_energy >= lumo] = 0 if self.verbose >= logger.INFO: if mo_energy[n2c + nocc - 1] + 1e-3 > mo_energy[n2c + nocc]: logger.warn(self, 'H**O %.15g == LUMO %.15g', mo_energy[n2c + nocc - 1], mo_energy[n2c + nocc]) else: logger.info(self, 'H**O %d = %.12g LUMO %d = %.12g', nocc, mo_energy[n2c + nocc - 1], nocc + 1, mo_energy[n2c + nocc]) logger.debug1(self, 'NES mo_energy = %s', mo_energy[:n2c]) logger.debug(self, 'PES mo_energy = %s', mo_energy[n2c:]) return mo_occ
def get_occ(mo_energy_kpts=None, mo_coeff=None): if mo_energy_kpts is None: mo_energy_kpts = mf.mo_energy mo_energy_kpts = numpy.asarray(mo_energy_kpts) mo_occ_kpts = numpy.zeros_like(mo_energy_kpts) logger.debug1(mf, "mo_occ_kpts.shape", mo_occ_kpts.shape) nkpts = len(mo_energy_kpts[0]) h**o = [-1e8, -1e8] lumo = [1e8, 1e8] for k in range(nkpts): for s in [0, 1]: e_idx = numpy.argsort(mo_energy_kpts[s, k]) e_sort = mo_energy_kpts[s, k][e_idx] n = mf.nelec[s] mo_occ_kpts[s, k, e_idx[:n]] = 1 h**o[s] = max(h**o[s], e_sort[n - 1]) lumo[s] = min(lumo[s], e_sort[n]) for nm, s in zip(['alpha', 'beta'], [0, 1]): logger.info(mf, nm + ' H**O = %.12g LUMO = %.12g', h**o[s], lumo[s]) if h**o[s] > lumo[s]: logger.warn( mf, "WARNING! H**O is greater than LUMO! This may result in errors with canonical occupation." ) return mo_occ_kpts
def get_init_guess(self, mol=None, key='minao'): if mol is None: mol = self.mol if callable(key): dm = key(mol) elif key.lower() == '1e': dm = self.init_guess_by_1e(mol) elif getattr(mol, 'natm', 0) == 0: logger.info(self, 'No atom found in mol. Use 1e initial guess') dm = self.init_guess_by_1e(mol) elif key.lower() == 'atom': dm = self.init_guess_by_atom(mol) elif key.lower() == 'chkfile': try: dm = self.init_guess_by_chkfile() except (IOError, KeyError): logger.warn(self, 'Fail in reading %s. Use MINAO initial guess', self.chkfile) dm = self.init_guess_by_minao(mol) else: dm = self.init_guess_by_minao(mol) if self.verbose >= logger.DEBUG1: logger.debug1(self, 'Nelec from initial guess = %g', (dm*self.get_ovlp()).sum().real) return dm
def get_veff(ks_grad, mol=None, dm=None): '''Coulomb + XC functional ''' if mol is None: mol = ks_grad.mol if dm is None: dm = ks_grad.base.make_rdm1() t0 = (time.clock(), time.time()) mf = ks_grad.base ni = mf._numint if ks_grad.grids is not None: grids = ks_grad.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) if mf.nlc != '': raise NotImplementedError #enabling range-separated hybrids omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin) mem_now = lib.current_memory()[0] max_memory = max(2000, ks_grad.max_memory*.9-mem_now) if ks_grad.grid_response: exc, vxc = rks_grad.get_vxc_full_response( ni, mol, grids, mf.xc, dm, max_memory=max_memory, verbose=ks_grad.verbose) logger.debug1(ks_grad, 'sum(grids response) %s', exc.sum(axis=0)) else: exc, vxc = rks_grad.get_vxc( ni, mol, grids, mf.xc, dm, max_memory=max_memory, verbose=ks_grad.verbose) t0 = logger.timer(ks_grad, 'vxc', *t0) if abs(hyb) < 1e-10 and abs(alpha) < 1e-10: vj = ks_grad.get_j(mol, dm) vxc += vj if ks_grad.auxbasis_response: e1_aux = vj.aux else: vj, vk = ks_grad.get_jk(mol, dm) if ks_grad.auxbasis_response: vk_aux = vk.aux * hyb vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb operator raise NotImplementedError vk_lr = ks_grad.get_k(mol, dm, omega=omega) vk += vk_lr * (alpha - hyb) if ks_grad.auxbasis_response: vk_aux += vk_lr.aux * (alpha - hyb) vxc += vj - vk * .5 if ks_grad.auxbasis_response: e1_aux = vj.aux - vk_aux * .5 if ks_grad.auxbasis_response: logger.debug1(ks_grad, 'sum(auxbasis response) %s', e1_aux.sum(axis=0)) vxc = lib.tag_array(vxc, exc1_grid=exc, aux=e1_aux) else: vxc = lib.tag_array(vxc, exc1_grid=exc) return vxc
def aux_e2(cell, auxcell, intor): '''3-center AO integrals (ij|L), where L is the auxiliary basis. Implements double summation over lattice vectors: \sum_{lm} (i[l]j[m]|L[0]). ''' # sum over largest number of images in either cell or auxcell nimgs = numpy.max((cell.nimgs, auxcell.nimgs), axis=0) Ls = tools.pbc.get_lattice_Ls(cell, nimgs) logger.debug1(cell, "Images summed over in DFT %s", nimgs) logger.debug2(cell, "Ls = %s", Ls) nao = cell.nao_nr() nao_pair = nao*(nao+1) // 2 nao_pair = nao*nao naoaux = auxcell.nao_nr() cellL = cell.copy() cellR = cell.copy() _envL = cellL._env _envR = cellR._env ptr_coord = cellL._atm[:,pyscf.gto.PTR_COORD] buf = numpy.zeros((nao_pair,naoaux)) for l, L1 in enumerate(Ls): _envL[ptr_coord+0] = cell._env[ptr_coord+0] + L1[0] _envL[ptr_coord+1] = cell._env[ptr_coord+1] + L1[1] _envL[ptr_coord+2] = cell._env[ptr_coord+2] + L1[2] for m in range(l): _envR[ptr_coord+0] = cell._env[ptr_coord+0] + Ls[m][0] _envR[ptr_coord+1] = cell._env[ptr_coord+1] + Ls[m][1] _envR[ptr_coord+2] = cell._env[ptr_coord+2] + Ls[m][2] buf += pyscf.df.incore.aux_e2(cellL, auxcell, intor, mol1=cellR) buf += .5 * pyscf.df.incore.aux_e2(cellL, auxcell, intor, mol1=cellL) eri = buf.reshape(nao,nao,-1) return eri + eri.transpose(1,0,2)
def kernel(self, h1e, eri, norb, nelec, ci0=None, ecore=0, restart=None, **kwargs): if restart is None: restart = self.restart state_id = min(self.config['eps_vars']) if restart or ci0 is not None: if self.verbose >= logger.DEBUG1: logger.debug1( self, 'restart was set. wf is read from wf_eps* file.') self.cleanup(remove_wf=False) wfn_file = get_wfn_file(self, state_id) if os.path.isfile(wfn_file): shutil.move(wfn_file, get_wfn_file(self, state_id * 2)) else: self.cleanup(remove_wf=True) if 'orbsym' in kwargs: self.orbsym = kwargs['orbsym'] writeIntegralFile(self, h1e, eri, norb, nelec, ecore) conf = {} if 'tol' in kwargs: conf['tol'] = kwargs['tol'] write_config(self, nelec, conf) if self.dryrun: logger.info(self, 'Only write integrals and config') if self.nroots == 1: calc_e = 0.0 roots = '' else: calc_e = [0.0] * self.nroots roots = [''] * self.nroots return calc_e, roots if self.nroots != 1: raise NotImplementedError execute_shci(self) if self.verbose >= logger.DEBUG1: with open(os.path.join(self.runtimedir, self.outputfile), 'r') as f: self.stdout.write(f.read()) calc_e = read_energy(self) # Each eps_vars is associated to one approximate wfn. roots = state_id = min(self.config['eps_vars']) if not os.path.isfile(get_wfn_file(self, state_id)): raise RuntimeError('Eigenstate %s not found' % get_wfn_file(self, state_id)) return calc_e, roots
def get_veff(self, mol=None, dm=None): vj, vk = self.get_jk(mol, dm) vhf = vj - vk*.5 if self.auxbasis_response: e1_aux = vj.aux - vk.aux*.5 logger.debug1(self, 'sum(auxbasis response) %s', e1_aux.sum(axis=0)) vhf = lib.tag_array(vhf, aux=e1_aux) return vhf
def dump_flags(self): logger.info(self, '\n') logger.info(self, '******** %s flags ********', self.__class__) logger.info(self, 'gs = %s', self.gs) logger.info(self, 'eta = %s', self.eta) logger.info(self, 'len(kpts) = %d', len(self.kpts)) logger.debug1(self, ' kpts = %s', self.kpts) return self
def dump_flags(self): logger.info(self, '\n') logger.info(self, '******** %s ********', self.__class__) logger.info(self, 'mesh = %s (%d PWs)', self.mesh, numpy.prod(self.mesh)) logger.info(self, 'eta = %s', self.eta) logger.info(self, 'len(kpts) = %d', len(self.kpts)) logger.debug1(self, ' kpts = %s', self.kpts) return self
def dump_flags(self): grad_class.dump_flags(self) logger.info(self, '** Add background charges for %s **', grad_class) if self.verbose >= logger.DEBUG1: logger.debug1(self, 'Charge Location') for i, z in enumerate(charges): logger.debug1(self, '%.9g %s', z, coords[i]) return self
def get_jk(agf2, eri, rdm1, with_j=True, with_k=True): ''' Get the J/K matrices. Args: eri : ndarray or H5 dataset Electronic repulsion integrals (NOT as _ChemistsERIs) rdm1 : 2D array Reduced density matrix Kwargs: with_j : bool Whether to compute J. Default value is True with_k : bool Whether to compute K. Default value is True Returns: tuple of ndarrays corresponding to J and K, if either are not requested then they are set to None. ''' if isinstance(eri, np.ndarray): vj, vk = _vhf.incore(eri, rdm1, with_j=with_j, with_k=with_k) else: nmo = rdm1.shape[0] npair = nmo * (nmo + 1) // 2 vj = vk = None if with_j: rdm1_tril = lib.pack_tril(rdm1 + np.tril(rdm1, k=-1)) vj = np.zeros_like(rdm1_tril) if with_k: vk = np.zeros_like(rdm1) blksize = _agf2.get_blksize(agf2.max_memory, (nmo * npair, nmo**3)) blksize = min(1, max(BLKMIN, blksize)) logger.debug1(agf2, 'blksize (ragf2.get_jk) = %d' % blksize) tril2sq = lib.square_mat_in_trilu_indices(nmo) for p0, p1 in lib.prange(0, nmo, blksize): idx = list(np.concatenate(tril2sq[p0:p1])) eri0 = eri[idx] # vj built in tril layout with scaled rdm1_tril if with_j: vj[idx] = np.dot(eri0, rdm1_tril) if with_k: eri0 = lib.unpack_tril(eri0, axis=-1) eri0 = eri0.reshape(p1 - p0, nmo, nmo, nmo) vk[p0:p1] = lib.einsum('ijkl,jk->il', eri0, rdm1) if with_j: vj = lib.unpack_tril(vj) return vj, vk
def get_veff(ks_grad, mol=None, dm=None): ''' First order derivative of DFT effective potential matrix (wrt electron coordinates) Args: ks_grad : grad.uhf.Gradients or grad.uks.Gradients object ''' if mol is None: mol = ks_grad.mol if dm is None: dm = ks_grad.base.make_rdm1() t0 = (time.clock(), time.time()) mf = ks_grad.base ni = mf._numint if ks_grad.grids is not None: grids = ks_grad.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) if mf.nlc != '': raise NotImplementedError #enabling range-separated hybrids omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin) mem_now = lib.current_memory()[0] max_memory = max(2000, ks_grad.max_memory * .9 - mem_now) if ks_grad.grid_response: exc, vxc = get_vxc_full_response(ni, mol, grids, mf.xc, dm, max_memory=max_memory, verbose=ks_grad.verbose) logger.debug1(ks_grad, 'sum(grids response) %s', exc.sum(axis=0)) else: exc, vxc = get_vxc(ni, mol, grids, mf.xc, dm, max_memory=max_memory, verbose=ks_grad.verbose) t0 = logger.timer(ks_grad, 'vxc', *t0) if abs(hyb) < 1e-10 and abs(alpha) < 1e-10: vj = ks_grad.get_j(mol, dm) vxc += vj else: vj, vk = ks_grad.get_jk(mol, dm) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb operator with mol.with_range_coulomb(omega): vk += ks_grad.get_k(mol, dm) * (alpha - hyb) vxc += vj - vk * .5 return lib.tag_array(vxc, exc1_grid=exc)
def make_rdm1(self, mo_coeff=None, mo_occ=None): if mo_coeff is None: mo_coeff = self.mo_coeff_on_imp if mo_occ is None: mo_occ = self.mo_occ nbf = mo_coeff.shape[0] mo = mo_coeff[:,mo_occ>0] dm = numpy.dot(mo, mo.T.conj()) * 2 log.debug1(self, 'density.diag = %s', dm.diagonal()) return dm
def dump_flags(self, verbose=None): grad_class.dump_flags(self, verbose) logger.info(self, '** Add background charges for %s **', grad_class) if self.verbose >= logger.DEBUG1: logger.debug1(self, 'Charge Location') coords = self.base.mm_mol.atom_coords() charges = self.base.mm_mol.atom_charges() for i, z in enumerate(charges): logger.debug1(self, '%.9g %s', z, coords[i]) return self
def molecular_response_ov(vind, space_ov, nocc, nmo, double, log_dest): """ Retrieves a raw response matrix. Args: vind (Callable): a pyscf matvec routine; space_ov (ndarray): the active `ov` space mask: either the same mask for both rows and columns (1D array) or separate `ov` masks for rows and columns (2D array); nocc (int): the number of occupied orbitals (frozen and active); nmo (int): the total number of orbitals; double (bool): set to True if `vind` returns the double-sized (i.e. full) matrix; log_dest (object): pyscf logging; Returns: The TD matrix. Note: The runtime scales with the size of the column mask `space_ov[1]` but not the row mask `space_ov[0]`. """ space_ov = numpy.array(space_ov) nocc_full, nvirt_full = nocc, nmo - nocc size_full = nocc_full * nvirt_full if space_ov.shape not in ((size_full, ), (2, size_full)): raise ValueError( "The 'space_ov' argument should be a 1D array with dimension {size_full:d} or a 2D array with" " dimensions 2x{size_full:d}, found: {actual}".format( size_full=size_full, actual=space_ov.shape, )) ov1, ov2 = space_ov size = sum(ov2) probe = numpy.zeros((size, 2 * size_full if double else size_full)) probe[numpy.arange(probe.shape[0]), numpy.argwhere(ov2)[:, 0]] = 1 logger.debug1( log_dest, "Requesting response against {} matrix (column space: {})".format( "x".join(str(i) for i in probe.shape), format_mask(ov2), )) result = vind(probe).T logger.debug1(log_dest, " output: {}".format(result.shape)) if double: result = result[numpy.tile(ov1, 2)] half = sum(ov1) result_a = result[:half] result_b = result[half:] return result_a, -result_b.conj() else: return result[ov1]
def update(self, x, xerr=None): '''Extrapolate vector * If xerr the error vector is given, this function will push the target vector and error vector in the DIIS subspace, and use the error vector to extrapolate the vector and return the extrapolated vector. * If xerr is None, this function will take the difference between the current given vector and the last given vector as the error vector to extrapolate the vector. ''' if xerr is not None: self.push_err_vec(xerr) self.push_vec(x) nd = self.get_num_vec() if nd < self.min_space: return x dt = numpy.array(self.get_err_vec(self._head - 1), copy=False) for i in range(nd): tmp = 0 dti = self.get_err_vec(i) for p0, p1 in prange(0, dt.size, BLOCK_SIZE): tmp += numpy.dot(dt[p0:p1].conj(), dti[p0:p1]) self._H[self._head, i + 1] = tmp self._H[i + 1, self._head] = tmp.conjugate() dt = None h = self._H[:nd + 1, :nd + 1] g = numpy.zeros(nd + 1, x.dtype) g[0] = 1 #try: # c = numpy.linalg.solve(h, g) #except numpy.linalg.linalg.LinAlgError: # logger.warn(self, ' diis singular') if 1: w, v = scipy.linalg.eigh(h) idx = abs(w) > 1e-14 c = numpy.dot(v[:, idx] * (1 / w[idx]), numpy.dot(v[:, idx].T.conj(), g)) logger.debug1(self, 'diis-c %s', c) if self._xprev is None: xnew = numpy.zeros_like(x.ravel()) else: self._xprev = None # release memory first self._xprev = xnew = numpy.zeros_like(x.ravel()) for i, ci in enumerate(c[1:]): xi = self.get_vec(i) for p0, p1 in prange(0, x.size, BLOCK_SIZE): xnew[p0:p1] += xi[p0:p1] * ci return xnew.reshape(x.shape)
def update(self, x, xerr=None): '''Extrapolate vector * If xerr the error vector is given, this function will push the target vector and error vector in the DIIS subspace, and use the error vector to extrapolate the vector and return the extrapolated vector. * If xerr is None, this function will take the difference between the current given vector and the last given vector as the error vector to extrapolate the vector. ''' if xerr is not None: self.push_err_vec(xerr) self.push_vec(x) nd = self.get_num_vec() if nd < self.min_space: return x dt = numpy.array(self.get_err_vec(self._head-1), copy=False) for i in range(nd): tmp = 0 dti = self.get_err_vec(i) for p0,p1 in prange(0, dt.size, BLOCK_SIZE): tmp += numpy.dot(dt[p0:p1].conj(), dti[p0:p1]) self._H[self._head,i+1] = tmp self._H[i+1,self._head] = tmp.conjugate() dt = None h = self._H[:nd+1,:nd+1] g = numpy.zeros(nd+1, x.dtype) g[0] = 1 #try: # c = numpy.linalg.solve(h, g) #except numpy.linalg.linalg.LinAlgError: # logger.warn(self, ' diis singular') if 1: w, v = scipy.linalg.eigh(h) idx = abs(w)>1e-14 c = numpy.dot(v[:,idx]*(1/w[idx]), numpy.dot(v[:,idx].T.conj(), g)) logger.debug1(self, 'diis-c %s', c) if self._xprev is None: xnew = numpy.zeros_like(x.ravel()) else: self._xprev = None # release memory first self._xprev = xnew = numpy.zeros_like(x.ravel()) for i, ci in enumerate(c[1:]): xi = self.get_vec(i) for p0,p1 in prange(0, x.size, BLOCK_SIZE): xnew[p0:p1] += xi[p0:p1] * ci return xnew.reshape(x.shape)
def dump_flags(self): log = logger.Logger(self.stdout, self.verbose) logger.info(self, '\n') logger.info(self, '******** %s flags ********', self.__class__) logger.info(self, 'gs = %s', self.gs) logger.info(self, 'auxbasis = %s', self.auxbasis) logger.info(self, 'eta = %s', self.eta) if isinstance(self._cderi, str): logger.info(self, '_cderi = %s', self._cderi) else: logger.info(self, '_cderi = %s', self._cderi_file.name) logger.info(self, 'len(kpts) = %d', len(self.kpts)) logger.debug1(self, ' kpts = %s', self.kpts)
def DMRG_MPS_NEVPT(mc, root=0, fcisolver=None,maxm = 500, tol =1e-6, parallel= True): if (isinstance(mc, basestring)): fh5 = h5py.File(mc,'r') mol = eval(fh5['mol'].value) ncas = fh5['mc/ncas'].value ncore = fh5['mc/ncore'].value nvirt = fh5['mc/nvirt'].value nelecas = fh5['mc/nelecas'].value fh5.close() mc_chk = mc else : mol = mc.mol ncas = mc.ncas ncore = mc.ncore nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore nelecas = mc.nelecas mc_chk = 'mc_chkfile' write_chk(mc,root,mc_chk) if fcisolver is None: fcisolver = DMRGCI(mol, maxm, tol) fcisolver.twopdm = False fcisolver.nroots = mc.fcisolver.nroots scratch = fcisolver.scratchDirectory fcisolver.scratchDirectory = '' #if (not parallel): # ci.extraline.append('restart_mps_nevpt %d %d %d'%(ncas,ncore, nvirt)) fcisolver.extraline.append('fullrestart') fcisolver.extraline.append('nevpt_state_num %d'%root) writeDMRGConfFile(nelecas[0], nelecas[1], False, fcisolver) fcisolver.scratchDirectory = scratch if fcisolver.verbose >= logger.DEBUG1: inFile = fcisolver.configFile #inFile = os.path.join(self.scratchDirectory,self.configFile) logger.debug1(fcisolver, 'Block Input conf') logger.debug1(fcisolver, open(inFile, 'r').read()) from subprocess import check_call import os full_path = os.path.realpath(__file__) check_call('%s %s/nevpt_mpi.py %s %s %s %s %s'%(fcisolver.mpiprefix, os.path.dirname(full_path), mc_chk, fcisolver.executable, fcisolver.configFile,fcisolver.outputFile, fcisolver.scratchDirectory), shell=True)
def update(self, s, d, f): if isinstance(f, numpy.ndarray) and f.ndim == 2: sdf = reduce(numpy.dot, (s,d,f)) errvec = sdf.T.conj() - sdf else: sdf_a = reduce(numpy.dot, (s, d[0], f[0])) sdf_b = reduce(numpy.dot, (s, d[1], f[1])) errvec = numpy.hstack((sdf_a.T.conj() - sdf_a, sdf_b.T.conj() - sdf_b)) logger.debug1(self, 'diis-norm(errvec)=%g', numpy.linalg.norm(errvec)) xnew = pyscf.lib.diis.DIIS.update(self, f, xerr=errvec) if self.rollback > 0 and len(self._bookkeep) == self.space: self._bookkeep = self._bookkeep[-self.rollback:] return xnew
def kernel(self, h1e, eri, norb, nelec, ci0=None, ecore=0, restart=None, **kwargs): if restart is None: restart = self.restart state_id = min(self.config['eps_vars']) if restart or ci0 is not None: if self.verbose >= logger.DEBUG1: logger.debug1(self, 'restart was set. wf is read from wf_eps* file.') self.cleanup(remove_wf=False) wfn_file = get_wfn_file(self, state_id) if os.path.isfile(wfn_file): shutil.move(wfn_file, get_wfn_file(self, state_id * 2)) else: self.cleanup(remove_wf=True) if 'orbsym' in kwargs: self.orbsym = kwargs['orbsym'] writeIntegralFile(self, h1e, eri, norb, nelec, ecore) conf = {} if 'tol' in kwargs: conf['tol'] = kwargs['tol'] write_config(self, nelec, conf) if self.dryrun: logger.info(self, 'Only write integrals and config') if self.nroots == 1: calc_e = 0.0 roots = '' else : calc_e = [0.0] * self.nroots roots = [''] * self.nroots return calc_e, roots if self.nroots != 1: raise NotImplementedError execute_shci(self) if self.verbose >= logger.DEBUG1: with open(os.path.join(self.runtimedir, self.outputfile), 'r') as f: self.stdout.write(f.read()) calc_e = read_energy(self) # Each eps_vars is associated to one approximate wfn. roots = state_id = min(self.config['eps_vars']) if not os.path.isfile(get_wfn_file(self, state_id)): raise RuntimeError('Eigenstate %s not found' % get_wfn_file(self, state_id)) return calc_e, roots
def dump_flags(self): log = logger.Logger(self.stdout, self.verbose) logger.info(self, "\n") logger.info(self, "******** %s flags ********", self.__class__) logger.info(self, "gs = %s", self.gs) logger.info(self, "metric = %s", self.metric) logger.info(self, "approx_sr_level = %s", self.approx_sr_level) logger.info(self, "auxbasis = %s", self.auxbasis) logger.info(self, "eta = %s", self.eta) if isinstance(self._cderi, str): logger.info(self, "_cderi = %s", self._cderi) else: logger.info(self, "_cderi = %s", self._cderi_file.name) logger.info(self, "len(kpts) = %d", len(self.kpts)) logger.debug1(self, " kpts = %s", self.kpts)
def get_veff(ks_grad, mol=None, dm=None): '''Coulomb + XC functional ''' if mol is None: mol = ks_grad.mol if dm is None: dm = ks_grad.base.make_rdm1() t0 = (time.clock(), time.time()) mf = ks_grad.base ni = mf._numint if ks_grad.grids is not None: grids = ks_grad.grids else: grids = mf.grids if grids.coords is None: grids.build(with_non0tab=True) if mf.nlc != '': raise NotImplementedError #enabling range-separated hybrids omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin) mem_now = lib.current_memory()[0] max_memory = max(2000, ks_grad.max_memory*.9-mem_now) if ks_grad.grid_response: exc, vxc = get_vxc_full_response(ni, mol, grids, mf.xc, dm, max_memory=max_memory, verbose=ks_grad.verbose) logger.debug1(ks_grad, 'sum(grids response) %s', exc.sum(axis=0)) else: exc, vxc = get_vxc(ni, mol, grids, mf.xc, dm, max_memory=max_memory, verbose=ks_grad.verbose) t0 = logger.timer(ks_grad, 'vxc', *t0) if abs(hyb) < 1e-10: vj = ks_grad.get_j(mol, dm) vxc += vj[0] + vj[1] else: vj, vk = ks_grad.get_jk(mol, dm) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb operator with mol.with_range_coulomb(omega): vk += ks_grad.get_k(mol, dm) * (alpha - hyb) vxc += vj[0] + vj[1] - vk return lib.tag_array(vxc, exc1_grid=exc)
def eig(self, f, s): atm = self.mol symb = atm.atom_symbol(0) idx_by_l = [[] for i in range(param.L_MAX)] i0 = 0 for ib in range(atm.nbas): l = atm.bas_angular(ib) nc = atm.bas_nctr(ib) i1 = i0 + nc * (l*2+1) idx_by_l[l].extend(range(i0, i1, l*2+1)) i0 = i1 nbf = atm.nao_nr() self._occ = numpy.zeros(nbf) mo_c = numpy.zeros((nbf, nbf)) mo_e = numpy.zeros(nbf) # fraction occupation for l in range(param.L_MAX): if idx_by_l[l]: n2occ, frac = frac_occ(symb, l) logger.debug1(self, 'l = %d occ = %d + %.4g', l, n2occ, frac) idx = numpy.array(idx_by_l[l]) f1 = 0 s1 = 0 for m in range(l*2+1): f1 = f1 + f[idx+m,:][:,idx+m] s1 = s1 + s[idx+m,:][:,idx+m] f1 *= 1./(l*2+1) s1 *= 1./(l*2+1) e, c = hf.SCF.eig(self, f1, s1) for i, ei in enumerate(e): logger.debug1(self, 'l = %d e_%d = %.9g', l, i, ei) for m in range(l*2+1): mo_e[idx] = e self._occ[idx[:n2occ]] = 2 if frac > 1e-15: self._occ[idx[n2occ]] = frac for i,i1 in enumerate(idx): mo_c[idx,i1] = c[:,i] idx += 1 return mo_e, mo_c
def update(self, s, d, f, mf, h1e, vhf): if self._head >= self.space: self._head = 0 if not self._buffer: shape = (self.space,) + f.shape self._buffer['dm' ] = numpy.zeros(shape, dtype=f.dtype) self._buffer['fock'] = numpy.zeros(shape, dtype=f.dtype) self._buffer['dm' ][self._head] = d self._buffer['fock'][self._head] = f ds = self._buffer['dm' ] fs = self._buffer['fock'] fun, c = adiis_minimize(ds, fs, self._head) if self.verbose >= logger.DEBUG1: etot = mf.energy_elec(d, h1e, vhf)[0] + fun logger.debug1(self, 'E %s diis-c %s ', etot, c) fock = numpy.einsum('i,i...pq->...pq', c, fs) self._head += 1 return fock
def hot_load(envs): try: with open(configfile) as f: # filter out comments raw_js = [] balance = 0 data = [x for x in f.readlines() if not x.startswith('#') and x.rstrip()] for n, line in enumerate(data): if not line.lstrip().startswith('#'): raw_js.append(line) balance += line.count('{') - line.count('}') if balance == 0: break raw_py = ''.join(data[n+1:]) raw_js = ''.join(raw_js) logger.debug(casscf, 'Reading CASSCF parameters from config file %s', os.path.realpath(configfile)) logger.debug1(casscf, ' Inject casscf settings %s', raw_js) conf = json.loads(raw_js) casscf.__dict__.update(conf.pop('casscf')) # Not yet found a way to update locals() on the runtime # https://docs.python.org/2/library/functions.html#locals #for k in conf: # if k in envs: # logger.info(casscf, 'Update envs[%s] = %s', k, conf[k]) # envs[k] = conf[k] logger.debug1(casscf, ' Inject python script\n%s\n', raw_py) if len(raw_py.strip()) > 0: if sys.version_info >= (3,): # A hacky call using eval because exec are so different in python2 and python3 eval(compile('exec(raw_py, envs, {})', '<str>', 'exec')) else: eval(compile('exec raw_py in envs, {}', '<str>', 'exec')) except Exception as e: logger.warn(casscf, 'CASSCF hot_load error %s', e) logger.warn(casscf, ''.join(traceback.format_exc())) if callable(old_cb): old_cb(envs)
def update(self, x, xerr=None): '''use DIIS method to solve Eq. operator(x) = x.''' if xerr is not None: self.push_err_vec(xerr) self.push_vec(x) nd = self.get_num_vec() if nd < self.min_space: return x dt = numpy.array(self.get_err_vec(self._head-1), copy=False) for i in range(nd): tmp = 0 dti = self.get_err_vec(i) for p0,p1 in prange(0, x.size, BLOCK_SIZE): tmp += numpy.dot(dt[p0:p1].conj(), dti[p0:p1]) self._H[self._head,i+1] = tmp self._H[i+1,self._head] = tmp.conjugate() dt = None h = self._H[:nd+1,:nd+1] g = numpy.zeros(nd+1, x.dtype) g[0] = 1 try: c = numpy.linalg.solve(h, g) except numpy.linalg.linalg.LinAlgError: logger.warn(self, 'singularity in diis') w, v = scipy.linalg.eigh(h) idx = abs(w)>1e-14 c = numpy.dot(v[:,idx]*(1/w[idx]), numpy.dot(v[:,idx].T.conj(), g)) logger.debug1(self, 'diis-c %s', c) if self._xprev is None: xnew = numpy.zeros_like(x.ravel()) else: self._xprev = None # release memory first self._xprev = xnew = numpy.zeros_like(x.ravel()) for i, ci in enumerate(c[1:]): xi = self.get_vec(i) for p0,p1 in prange(0, x.size, BLOCK_SIZE): xnew[p0:p1] += xi[p0:p1] * ci return xnew.reshape(x.shape)
def update(self, s, d, f, mf, h1e, vhf): if self._head >= self.space: self._head = 0 if not self._buffer: shape = (self.space,) + f.shape self._buffer['dm' ] = numpy.zeros(shape, dtype=f.dtype) self._buffer['fock'] = numpy.zeros(shape, dtype=f.dtype) self._buffer['etot'] = numpy.zeros(self.space) self._buffer['dm' ][self._head] = d self._buffer['fock'][self._head] = f self._buffer['etot'][self._head] = mf.energy_elec(d, h1e, vhf)[0] self._head += 1 ds = self._buffer['dm' ] fs = self._buffer['fock'] es = self._buffer['etot'] etot, c = ediis_minimize(es, ds, fs) logger.debug1(self, 'E %s diis-c %s', etot, c) fock = numpy.einsum('i,i...pq->...pq', c, fs) return fock
def get_occ(self, mo_energy=None, mo_coeff=None): if mo_energy is None: mo_energy = self.mo_energy mol = self.mol c = lib.param.LIGHT_SPEED n4c = len(mo_energy) n2c = n4c // 2 mo_occ = numpy.zeros(n2c * 2) if mo_energy[n2c] > -1.999 * c**2: mo_occ[n2c:n2c+mol.nelectron] = 1 else: lumo = mo_energy[mo_energy > -1.999 * c**2][mol.nelectron] mo_occ[mo_energy > -1.999 * c**2] = 1 mo_occ[mo_energy >= lumo] = 0 if self.verbose >= logger.INFO: logger.info(self, 'H**O %d = %.12g LUMO %d = %.12g', n2c+mol.nelectron, mo_energy[n2c+mol.nelectron-1], n2c+mol.nelectron+1, mo_energy[n2c+mol.nelectron]) logger.debug1(self, 'NES mo_energy = %s', mo_energy[:n2c]) logger.debug(self, 'PES mo_energy = %s', mo_energy[n2c:]) return mo_occ
def extract_frag_energy(self, emb, dm1, e2frag): nimp = len(emb.bas_on_frag) hcore = emb._pure_hcore hfdm = self.entire_scf.make_rdm1(self.entire_scf.mo_coeff, self.entire_scf.mo_occ) vhf = emb.mat_ao2impbas(emb.entire_scf.get_veff(self.mol, hfdm)) e = numpy.dot(dm1[:nimp].flatten(), hcore[:nimp].flatten()) \ + numpy.dot(dm1[:nimp].flatten(), vhf[:nimp].flatten()) * .5 #emb.mo_coeff_on_imp are changed in function embscf_ #hfdm = emb.make_rdm1(emb.mo_coeff_on_imp, emb.mo_occ) # Note the cancellation of h1e[part] dot dm1[part] in HF and FCI energy expression c = scipy.linalg.eigh(emb._project_fock)[1] hfdm = emb.make_rdm1(c, emb.mo_occ) vhfemb = emb.get_veff(emb.mol, hfdm) ecorr = e2frag - numpy.dot(dm1[:nimp].flatten(), vhfemb[:nimp].flatten())*.5 log.debug1(self, ' FCI pTraceSys = %.12g, ecorr = %12g', e2frag, ecorr) e_frag = e + ecorr nelec_frag = dm1[:nimp].trace() return e_frag, nelec_frag
def kernel(self, h1e, eri, norb, nelec, fciRestart=None, **kwargs): if self.nroots == 1: roots = 0 else: roots = range(self.nroots) if fciRestart is None: fciRestart = self.restart or self._restart writeIntegralFile(self, h1e, eri, norb, nelec) writeDMRGConfFile(self, nelec, fciRestart) if self.verbose >= logger.DEBUG1: inFile = os.path.join(self.runtimeDir, self.configFile) logger.debug1(self, 'Block Input conf') logger.debug1(self, open(inFile, 'r').read()) if self.onlywriteIntegral: logger.info(self, 'Only write integral') try: calc_e = readEnergy(self) except IOError: if self.nroots == 1: calc_e = 0.0 else : calc_e = [0.0] * self.nroots return calc_e, roots executeBLOCK(self) if self.verbose >= logger.DEBUG1: outFile = os.path.join(self.runtimeDir, self.outputFile) logger.debug1(self, open(outFile).read()) calc_e = readEnergy(self) return calc_e, roots
def energy_elec(mf, dm, h1e=None, vhf=None): r'''Electronic part of Hartree-Fock energy, for given core hamiltonian and HF potential ... math:: E = \sum_{ij}h_{ij} \gamma_{ji} + \frac{1}{2}\sum_{ijkl} \gamma_{ji}\gamma_{lk} \langle ik||jl\rangle Args: mf : an instance of SCF class dm : 2D ndarray one-partical density matrix Kwargs: h1e : 2D ndarray Core hamiltonian vhf : 2D ndarray HF potential Returns: Hartree-Fock electronic energy and the 2-electron part contribution Examples: >>> from pyscf import gto, scf >>> mol = gto.M(atom='H 0 0 0; H 0 0 1.1') >>> mf = scf.RHF(mol) >>> mf.scf() >>> dm = mf.make_rdm1() >>> scf.hf.energy_elec(mf, dm) (-1.5176090667746334, 0.60917167853723675) ''' if h1e is None: h1e = mf.get_hcore() if vhf is None: vhf = mf.get_veff(mf.mol, dm) e1 = numpy.einsum('ji,ji', h1e.conj(), dm).real e_coul = numpy.einsum('ji,ji', vhf.conj(), dm).real * .5 logger.debug1(mf, 'E_coul = %.15g', e_coul) return e1+e_coul, e_coul
def approx_kernel(self, h1e, eri, norb, nelec, fciRestart=None, **kwargs): fciRestart = True if isinstance(nelec, (int, numpy.integer)): neleca = nelec//2 + nelec%2 nelecb = nelec - neleca else : neleca, nelecb = nelec writeIntegralFile(h1e, eri, norb, neleca, nelecb, self) writeDMRGConfFile(neleca, nelecb, fciRestart, self, True) if self.verbose >= logger.DEBUG1: inFile = self.configFile #inFile = os.path.join(self.scratchDirectory,self.configFile) logger.debug1(self, 'Block Input conf') logger.debug1(self, open(inFile, 'r').read()) executeBLOCK(self) if self.verbose >= logger.DEBUG1: outFile = self.outputFile #outFile = os.path.join(self.scratchDirectory,self.outputFile) logger.debug1(self, open(outFile).read()) calc_e = readEnergy(self) if self.nroots==1: roots = 0 else: roots = range(self.nroots) return calc_e, roots
def nevpt_intermediate(self, tag, norb, nelec, state, **kwargs): if self.has_nevpt == False: writeDMRGConfFile(self, nelec, True, with_2pdm=False, extraline=['restart_nevpt2_npdm']) if self.verbose >= logger.DEBUG1: inFile = os.path.join(self.runtimeDir, self.configFile) logger.debug1(self, 'Block Input conf') logger.debug1(self, open(inFile, 'r').read()) executeBLOCK(self) if self.verbose >= logger.DEBUG1: outFile = os.path.join(self.runtimeDir, self.outputFile) logger.debug1(self, open(outFile).read()) self.has_nevpt = True a16 = numpy.zeros( (norb, norb, norb, norb, norb, norb) ) filename = "%s_matrix.%d.%d.txt" % (tag, state, state) with open(os.path.join(self.scratchDirectory, "node0", filename), "r") as f: norb_read = int(f.readline().split()[0]) assert(norb_read == norb) for line in f: linesp = line.split() i, j, k, l, m, n = [int(x) for x in linesp[:6]] a16[i,j,k,l,m,n] = float(linesp[6]) return a16