def test(): mol = gto.M(atom="Li 0. 0. 0.; Li 0. 0. 1.5", basis="sto-3g", unit="bohr", verbose=0) mf = scf.RHF(mol).run() # Lowdin orthogonalized AO basis. lowdin = lo.orth_ao(mol, "lowdin") # MOs in the Lowdin basis. mo = solve(lowdin, mf.mo_coeff) # make AO to localized orbital coefficients. mfobdm = mf.make_rdm1(mo, mf.mo_occ) ### Test OBDM calculation. nconf = 500 nsteps = 400 obdm_steps = 4 warmup = 15 wf = PySCFSlaterUHF(mol, mf) configs = initial_guess(mol, nconf) energy = EnergyAccumulator(mol) obdm = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nsweeps=1) obdm_up = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nsweeps=1, spin=0) obdm_down = OBDMAccumulator(mol=mol, orb_coeff=lowdin, nsweeps=1, spin=1) df, coords = vmc( wf, configs, nsteps=nsteps, accumulators={ "energy": energy, "obdm": obdm, "obdm_up": obdm_up, "obdm_down": obdm_down, }, ) df = DataFrame(df) obdm_est = {} for k in ["obdm", "obdm_up", "obdm_down"]: avg_norm = np.array(df.loc[warmup:, k + "norm"].values.tolist()).mean(axis=0) avg_obdm = np.array(df.loc[warmup:, k + "value"].values.tolist()).mean(axis=0) obdm_est[k] = normalize_obdm(avg_obdm, avg_norm) print("Average OBDM(orb,orb)", obdm_est["obdm"].diagonal().round(3)) print("mf obdm", mfobdm.diagonal().round(3)) assert np.max(np.abs(obdm_est["obdm"] - mfobdm)) < 0.05 print(obdm_est["obdm_up"].diagonal().round(3)) print(obdm_est["obdm_down"].diagonal().round(3)) assert np.mean( np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm)) < 0.05
def gen_basis(mol, mf, obdm, threshold=1e-2): """From an obdm, use IAOs to generate a minimal atomic basis for a given state """ n = obdm.shape[0] obdm *= n w, v = np.linalg.eig(obdm) keep = np.abs(w) > threshold a = lo.orth_ao(mol, 'lowdin') basis = np.dot(a, v[:, keep]).real iao = lo.iao.iao(mol, basis) iao = lo.vec_lowdin(iao, mf.get_ovlp()) return iao
def find_basis_evaluate(mfchk, hdf_opt, hdf_vmc, hdf_final): """Given a wave function in hdf_opt, compute the 1-RDM (stored in hdf_vmc) , generate a minimal atomic basis and compute the energy/OBDM/TBDM and store in hdf_final """ from pyqmc.obdm import OBDMAccumulator from pyqmc.tbdm import TBDMAccumulator from pyqmc import EnergyAccumulator sys = pyqmc_from_hdf(mfchk) mol = sys["mol"] a = lo.orth_ao(mol, "lowdin") obdm_up = OBDMAccumulator(mol=mol, orb_coeff=a, spin=0) obdm_down = OBDMAccumulator(mol=mol, orb_coeff=a, spin=1) with h5py.File(hdf_opt, "r") as hdf_in: if f"wf" in hdf_in.keys(): print("reading in wave function") grp = hdf_in[f"wf"] for k in grp.keys(): sys["wf"].parameters[k] = np.array(grp[k]) configs = pyqmc.initial_guess(sys["mol"], 1000) pyqmc.vmc( sys["wf"], configs, nsteps=500, hdf_file=hdf_vmc, accumulators={ "obdm_up": obdm_up, "obdm_down": obdm_down }, ) with h5py.File(hdf_vmc, "r") as vmc_hdf: obdm_up = np.mean(np.array(vmc_hdf["obdm_upvalue"]), axis=0) obdm_down = np.mean(np.array(vmc_hdf["obdm_downvalue"]), axis=0) basis_up = gen_basis(mol, sys["mf"], obdm_up) basis_down = gen_basis(mol, sys["mf"], obdm_down) obdm_up_acc = OBDMAccumulator(mol=mol, orb_coeff=basis_up, spin=0) obdm_down_acc = OBDMAccumulator(mol=mol, orb_coeff=basis_down, spin=1) tbdm = TBDMAccumulator(mol, np.array([basis_up, basis_down]), spin=(0, 1)) acc = { "energy": EnergyAccumulator(mol), "obdm_up": obdm_up_acc, "obdm_down": obdm_down_acc, "tbdm": tbdm, } configs = pyqmc.initial_guess(sys["mol"], 1000) pyqmc.vmc(sys["wf"], configs, nsteps=500, hdf_file=hdf_final, accumulators=acc)
def test(): mol = gto.M(atom="Li 0. 0. 0.; Li 0. 0. 1.5", basis="sto-3g", unit="bohr", verbose=0) mf = scf.RHF(mol).run() # Lowdin orthogonalized AO basis. lowdin = lo.orth_ao(mol, "lowdin") # MOs in the Lowdin basis. mo = solve(lowdin, mf.mo_coeff) # make AO to localized orbital coefficients. mfobdm = mf.make_rdm1(mo, mf.mo_occ) ### Test OBDM calculation. nconf = 500 nsteps = 400 warmup = 15 wf = Slater(mol, mf) configs = initial_guess(mol, nconf) obdm_dict = dict(mol=mol, orb_coeff=lowdin, nsweeps=5, warmup=15) obdm = OBDMAccumulator(**obdm_dict) obdm_up = OBDMAccumulator(**obdm_dict, spin=0) obdm_down = OBDMAccumulator(**obdm_dict, spin=1) df, coords = vmc( wf, configs, nsteps=nsteps, accumulators={ "obdm": obdm, "obdm_up": obdm_up, "obdm_down": obdm_down }, ) obdm_est = {} for k in ["obdm", "obdm_up", "obdm_down"]: avg_norm = np.mean(df[k + "norm"][warmup:], axis=0) avg_obdm = np.mean(df[k + "value"][warmup:], axis=0) obdm_est[k] = normalize_obdm(avg_obdm, avg_norm) assert np.mean( np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm)) < 0.05
def dumpLocal(fname): chkfile = fname+'.chk' outfile = fname+'_cmo.molden' tools.molden.from_chkfile(outfile, chkfile) mol,mf = scf.chkfile.load_scf(chkfile) mo_coeff = mf["mo_coeff"] ova=mol.intor_symmetric("cint1e_ovlp_sph") nb = mo_coeff.shape[1] nalpha = (mol.nelectron+mol.spin)/2 nbeta = (mol.nelectron-mol.spin)/2 print 'nalpha,nbeta,mol.spin,nb:',\ nalpha,nbeta,mol.spin,nb # UHF-alpha/beta ma = mo_coeff[0] mb = mo_coeff[1] #============================= # Localization #============================= ma_c = ma[:,:nalpha].copy() ma_v = ma[:,nalpha:].copy() #-------------------- # Occupied space: PM #-------------------- import pmloc ierr,uc = pmloc.loc(mol,ma_c) mc = numpy.dot(ma_c,uc) #-------------------- # Virtual space: PAO #-------------------- from pyscf import lo aux = lo.orth_ao(mol,method='meta_lowdin') mv = scdm(ma_v,ova,aux) # P[dm] pa = numpy.dot(ma[:,:nalpha],ma[:,:nalpha].T) pb = numpy.dot(mb[:,:nbeta],mb[:,:nbeta].T) pT = 0.5*(pa+pb) # E-SORT enorb = mf["mo_energy"] fa = reduce(numpy.dot,(ma,numpy.diag(enorb[0]),ma.T)) fb = reduce(numpy.dot,(mb,numpy.diag(enorb[1]),mb.T)) fav = 0.5*(fa+fb) mc,occ_c,ec = psort(ova,fav,pT,mc) mv,occ_v,ev = psort(ova,fav,pT,mv) #---Check--- tij = reduce(numpy.dot,(mc.T,ova,ma_c)) sig = scipy.linalg.svd(tij,compute_uv=False) print 'nc=',nalpha,numpy.sum(sig**2) assert abs(nalpha-numpy.sum(sig**2))<1.e-8 tij = reduce(numpy.dot,(mv.T,ova,ma_v)) sig = scipy.linalg.svd(tij,compute_uv=False) print 'nv=',nb-nalpha,numpy.sum(sig**2) assert abs(nb-nalpha-numpy.sum(sig**2))<1.e-8 lmo = numpy.hstack([mc,mv]) enorb = numpy.hstack([ec,ev]) occ = numpy.hstack([occ_c,occ_v]) lowdinPop(mol,lmo,ova,enorb,occ) dumpLMO(mol,fname,lmo) print 'nalpha,nbeta,mol.spin,nb:',\ nalpha,nbeta,mol.spin,nb return 0
from functools import reduce import numpy from pyscf import gto, scf, lo x = .63 mol = gto.M(atom=[['C', (0, 0, 0)], ['H', (x , x, x)], ['H', (-x, -x, x)], ['H', (-x, x, -x)], ['H', ( x, -x, -x)]], basis='ccpvtz') mf = scf.RHF(mol).run() # C matrix stores the AO to localized orbital coefficients C = lo.orth_ao(mol, 'meta_lowdin') # C is orthogonal wrt to the AO overlap matrix. C^T S C is an identity matrix. print(abs(reduce(numpy.dot, (C.T, mf.get_ovlp(), C)) - numpy.eye(mol.nao_nr())).max()) # should be close to 0 # The following linear equation can also be solved using the matrix # multiplication reduce(numpy.dot (C.T, mf.get_ovlp(), mf.mo_coeff)) mo = numpy.linalg.solve(C, mf.mo_coeff) # # Mulliken population analysis based on meta-lowdin orbitals # dm = mf.make_rdm1(mo, mf.mo_occ) mf.mulliken_pop(mol, dm, numpy.eye(mol.nao_nr()))
def get_localized_orbitals(mf, lo_method, mo=None): if mo is None: mo = mf.mo_coeff if not isinstance(mf, khf.KSCF): mol = mf.mol s1e = mf.get_ovlp() if lo_method.lower() == 'lowdin' or lo_method.lower() == 'meta_lowdin': C = lo.orth_ao(mf, 'meta_lowdin', s=s1e) C_inv = np.dot(C.conj().T, s1e) if isinstance(mf, scf.hf.RHF): C_inv_spin = C_inv else: C_inv_spin = np.array([C_inv] * 2) elif lo_method == 'iao': s1e = mf.get_ovlp() pmol = mf.mol.copy() pmol.build(False, False, basis='minao') if isinstance(mf, scf.hf.RHF): mo_coeff_occ = mf.mo_coeff[:, mf.mo_occ > 0] C = lo.iao.iao(mf.mol, mo_coeff_occ) # Orthogonalize IAO C = lo.vec_lowdin(C, s1e) C_inv = np.dot(C.conj().T, s1e) C_inv_spin = C_inv else: mo_coeff_occ_a = mf.mo_coeff[0][:, mf.mo_occ[0] > 0] mo_coeff_occ_b = mf.mo_coeff[1][:, mf.mo_occ[1] > 0] C_a = lo.iao.iao(mf.mol, mo_coeff_occ_a) C_b = lo.iao.iao(mf.mol, mo_coeff_occ_b) C_a = lo.vec_lowdin(C_a, s1e) C_b = lo.vec_lowdin(C_b, s1e) C_inv_a = np.dot(C_a.T, s1e) C_inv_b = np.dot(C_b.T, s1e) C_inv_spin = np.array([C_inv_a, C_inv_b]) elif lo_method == 'nao': C = lo.orth_ao(mf, 'nao') C_inv = np.dot(C.conj().T, s1e) if isinstance(mf, scf.hf.RHF): C_inv_spin = C_inv else: C_inv_spin = np.array([C_inv] * 2) else: raise NotImplementedError("UNDEFINED LOCAL ORBITAL TYPE, EXIT...") mo_lo = np.einsum('...jk,...kl->...jl', C_inv_spin, mo) return C_inv_spin, mo_lo else: cell = mf.cell s1e = mf.get_ovlp() if lo_method.lower() == 'lowdin' or lo_method.lower() == 'meta_lowdin': nkpt = len(mf.kpts) C_arr = [] C_inv_arr = [] for i in range(nkpt): C_curr = lo.orth_ao(mf, 'meta_lowdin', s=s1e[i]) C_inv_arr.append(np.dot(C_curr.conj().T, s1e[i])) C_inv_arr = np.array(C_inv_arr) if isinstance(mf, scf.hf.RHF): C_inv_spin = C_inv_arr else: C_inv_spin = np.array([C_inv_arr] * 2) else: raise NotImplementedError("CONSTRUCTING...EXIT") mo_lo = np.einsum('...jk,...kl->...jl', C_inv_spin, mo) return C_inv_spin, mo_lo
''' Mulliken population analysis with meta-Lowdin orbitals ''' from functools import reduce import numpy from pyscf import gto, scf, lo x = .63 mol = gto.M(atom=[['C', (0, 0, 0)], ['H', (x, x, x)], ['H', (-x, -x, x)], ['H', (-x, x, -x)], ['H', (x, -x, -x)]], basis='ccpvtz') mf = scf.RHF(mol).run() # C matrix stores the AO to localized orbital coefficients C = lo.orth_ao(mol, 'meta_lowdin') # C is orthogonal wrt to the AO overlap matrix. C^T S C is an identity matrix. print( abs(reduce(numpy.dot, (C.T, mf.get_ovlp(), C)) - numpy.eye(mol.nao_nr())).max()) # should be close to 0 # The following linear equation can also be solved using the matrix # multiplication reduce(numpy.dot (C.T, mf.get_ovlp(), mf.mo_coeff)) mo = numpy.linalg.solve(C, mf.mo_coeff) # # Mulliken population analysis based on meta-lowdin orbitals # dm = mf.make_rdm1(mo, mf.mo_occ) mf.mulliken_pop(mol, dm, numpy.eye(mol.nao_nr()))
def genEmbedBasis(mol, mo_coeff, selectionRule, thresh=0.001, lao='meta_lowdin', debug=False, ifplot=True): print('\n[embed.genEmbedBasis] for unrestricted determinant') ova = mol.intor_symmetric("cint1e_ovlp_sph") nb = mo_coeff.shape[1] # Check overlap diff = reduce(numpy.dot, (mo_coeff[0].T, ova, mo_coeff[0])) - numpy.identity(nb) print(' (CtSC-I)[a]', numpy.linalg.norm(diff)) diff = reduce(numpy.dot, (mo_coeff[1].T, ova, mo_coeff[1])) - numpy.identity(nb) print(' (CtSC-I)[b]', numpy.linalg.norm(diff)) # UHF-alpha/beta ma = mo_coeff[0] mb = mo_coeff[1] nalpha = (mol.nelectron + mol.spin) / 2 nbeta = (mol.nelectron - mol.spin) / 2 print(' nalpha/nbeta = ', (nalpha, nbeta)) # Spin-averaged DM ma_occ = ma[:, :nalpha] mb_occ = mb[:, :nbeta] pTa = numpy.dot(ma_occ, ma_occ.T) pTb = numpy.dot(mb_occ, mb_occ.T) pT = pTa + pTb #------------------------------------ # OAO basis #------------------------------------ # Due to optimization by segmentation, # the lowdin here do not correspond to # the idea lowdin OAO. if lao == 'bad_lowdin': s12 = sqrtm(ova) s12inv = lowdin(ova) # Better choice: Pbas*|chiANO> elif lao == 'meta_lowdin': from pyscf import lo meta = lo.orth_ao(mol, method='meta_lowdin') diff = reduce(numpy.dot, (meta.T, ova, meta)) - numpy.identity(nb) s12inv = meta.copy() s12 = numpy.linalg.inv(s12inv) # # Psi = chiAO*C # = (chiAO*Y)*(Yinv*C) # DM in ortho basis = Yinv*C*n*C^T*Yinv^T # Only in lowdin basis Y^T=Y. # pTOAO = reduce(numpy.dot, (s12, pT, s12.T)) #------------------------------------ # Define impurity labels = mol.spheric_labels() fragBasis = [] fragLabels = [] for idx, item in enumerate(labels): ifselect = False if selectionRule(item): ifselect = True if ifselect: fragBasis.append(idx) fragLabels.append(item) print(' Define central fragment:') print(' No. of totalBasis:', nb) print(' No. of fragBasis :', len(fragBasis)) print(' Indices of fragBasis:', fragBasis) print(' fragLabels:') for idx, item in enumerate(fragLabels): print(' idx = ', idx, ' fragBas=', item) compBasis = list(set(range(nb)) - set(fragBasis)) nfrag = len(fragBasis) ncomp = len(compBasis) # Fragment pTf = pTOAO[numpy.ix_(fragBasis, fragBasis)] ef, u = scipy.linalg.eigh(-pTf) ef = -ef ne_f = sum(ef) print(' Diag_values of pTf:\n', numpy.diag(pTf)) print(' Eigenvalues of pTf:\n', ef) uf = numpy.zeros((nb, nfrag)) # Retain the locality for impurity #uf[fragBasis,:] = u uf[fragBasis, :] = numpy.identity(nfrag) # Complementary if ncomp > 0: pTc = pTOAO[numpy.ix_(compBasis, compBasis)] ec, v = scipy.linalg.eigh(-pTc) ec = -ec ne_c = sum(ec) print(' Eigenvalues of pTc:\n', ec) cindx = [] aindx = [] vindx = [] for i in range(ncomp): if abs(ec[i] - 2.0) < thresh: cindx.append(i) elif abs(ec[i]) < thresh: vindx.append(i) else: aindx.append(i) ncStrict = len(numpy.argwhere(abs(ec - 2.0) < 1.e-6)) nvStrict = len(numpy.argwhere(abs(ec) < 1.e-6)) naStrict = ncomp - ncStrict - nvStrict nc = len(cindx) na = len(aindx) nv = len(vindx) vc = numpy.zeros((nb, nc)) va = numpy.zeros((nb, na)) vv = numpy.zeros((nb, nv)) vc[compBasis, :] = v[:, cindx] va[compBasis, :] = v[:, aindx] vv[compBasis, :] = v[:, vindx] # Set up the proper ordering ucoeff = numpy.hstack((uf, va, vc, vv)) print('-' * 70) print(' Final results for classification of basis with thresh=', thresh) print('-' * 70) print(' (nf,na,nc,nv) = ', nfrag, na, nc, nv) print(' (ncomp,ncStrict,nvStrict,naStrict) =', ncomp, ncStrict, nvStrict, naStrict) print(' Eigen_na =\n', ec[aindx]) if ifplot: import matplotlib.pyplot as plt plt.plot(abs(ef), marker='o', linewidth=2.0) plt.plot(abs(ec), marker='o', linewidth=2.0) plt.show() else: ne_c = 0.0 ucoeff = uf.copy() # Check pTu = reduce(numpy.dot, (ucoeff.T, pTOAO, ucoeff)) print(' Nf =', ne_f, 'Nc =', ne_c, 'Nt =', ne_f + ne_c) if debug: print(' diagonal of pTu =') print(numpy.diag(pTu)) print('ucoeff\n', ucoeff) # Back to AO basis basis = numpy.dot(s12inv, ucoeff) # Dump diff = reduce(numpy.dot, (basis.T, ova, basis)) - numpy.identity(nb) print(' CtSC-I=', numpy.linalg.norm(diff)) with open('embas.molden', 'w') as thefile: molden.header(mol, thefile) molden.orbital_coeff(mol, thefile, basis) with open('cmoA.molden', 'w') as thefile: molden.header(mol, thefile) molden.orbital_coeff(mol, thefile, ma) with open('cmoB.molden', 'w') as thefile: molden.header(mol, thefile) molden.orbital_coeff(mol, thefile, mb) ua = reduce(numpy.dot, (basis.T, ova, ma_occ)) ub = reduce(numpy.dot, (basis.T, ova, mb_occ)) if debug: print(' ua\n', ua) if debug: print(' ub\n', ub) ia = abs(reduce(numpy.dot, (ua.T, ua))) ib = abs(reduce(numpy.dot, (ub.T, ub))) print(' diffIa=', numpy.linalg.norm(ia - numpy.identity(nalpha))) print(' diffIb=', numpy.linalg.norm(ib - numpy.identity(nbeta))) return basis, ua, ub
def test(): from pyscf import gto, scf, lo from numpy.linalg import solve from pyqmc.slater import PySCFSlaterRHF from pyqmc.mc import initial_guess, vmc from pyqmc.accumulators import EnergyAccumulator from pandas import DataFrame ### Generate some basic objects. # Simple Li2 run. mol = gto.M(atom='Li 0. 0. 0.; Li 0. 0. 1.5', basis='sto-3g', unit='bohr', verbose=0) mf = scf.RHF(mol).run() # Lowdin orthogonalized AO basis. lowdin = lo.orth_ao(mol, 'lowdin') # MOs in the Lowdin basis. mo = solve(lowdin, mf.mo_coeff) # make AO to localized orbital coefficients. mfobdm = mf.make_rdm1(mo, mf.mo_occ) #print(mfobdm.diagonal().round(2)) ### Test one-body sampler. #test_sample_onebody(mol,lowdin,mf,nsample=int(1e4)) #test_sample_onebody(mol,lowdin,mf,nsample=int(4e4)) #test_sample_onebody(mol,lowdin,mf,nsample=int(1e5)) ### Test OBDM calculation. nconf = 500 nsteps = 400 obdm_steps = 2 warmup = 15 wf = PySCFSlaterRHF(mol, mf) configs = initial_guess(mol, nconf) energy = EnergyAccumulator(mol) obdm = OBDMAccumulator(mol=mol, orb_coeff=mf.mo_coeff, nstep=obdm_steps) df, coords = vmc(wf, configs, nsteps=nsteps, accumulators={ 'energy': energy, 'obdm': obdm }) df = DataFrame(df) df['obdm'] = df[['obdmvalue','obdmnorm']]\ .apply(lambda x:normalize_obdm(x['obdmvalue'],x['obdmnorm']),axis=1) print(df[['obdmvalue', 'obdmnorm', 'obdm']].applymap(lambda x: x.ravel()[0])) avg_norm = np.array(df.loc[warmup:, 'obdmnorm'].values.tolist()).mean(axis=0) avg_obdm = np.array(df.loc[warmup:, 'obdm'].values.tolist()).mean(axis=0) std_obdm = np.array( df.loc[warmup:, 'obdm'].values.tolist()).std(axis=0) / nsteps**0.5 print("Average norm(orb)", avg_norm) print("Average OBDM(orb,orb)", avg_obdm.diagonal().round(3)) print("OBDM error (orb,orb)", std_obdm.diagonal().round( 3)) # Note this needs reblocking to be accurate. print("AO occupation", mfobdm[0, 0]) print('mean field', mf.energy_tot(), 'vmc estimation', np.mean(df['energytotal'][warmup:]), np.std(df['energytotal'][warmup:]))
''' import numpy from pyscf import gto, scf, lo x = .63 mol = gto.M(atom=[['C', (0, 0, 0)], ['H', (x , x, x)], ['H', (-x, -x, x)], ['H', (-x, x, -x)], ['H', ( x, -x, -x)]], basis='ccpvtz') mf = scf.RHF(mol).run() # C matrix stores the AO to localized orbital coefficients C = lo.orth_ao(mf, 'nao') # C is orthogonal wrt to the AO overlap matrix. C^T S C is an identity matrix. print(abs(reduce(numpy.dot, (C.T, mf.get_ovlp(), C)) - numpy.eye(mol.nao_nr())).max()) # should be close to 0 # The following linear equation can also be solved using the matrix # multiplication reduce(numpy.dot (C.T, mf.get_ovlp(), mf.mo_coeff)) mo = numpy.linalg.solve(C, mf.mo_coeff) # # Mulliken population analysis based on NAOs # dm = mf.make_rdm1(mo, mf.mo_occ) mf.mulliken_pop(mol, dm, numpy.eye(mol.nao_nr()))
#!/usr/bin/env python ''' Mulliken population analysis with NAO ''' import numpy from pyscf import gto, scf, lo x = .63 mol = gto.M(atom=[['C', (0, 0, 0)], ['H', (x, x, x)], ['H', (-x, -x, x)], ['H', (-x, x, -x)], ['H', (x, -x, -x)]], basis='ccpvtz') mf = scf.RHF(mol).run() c = lo.orth_ao(mf, 'nao') mo = numpy.linalg.solve(c, mf.mo_coeff) dm = mf.make_rdm1(mo, mf.mo_occ) mf.mulliken_pop(mol, dm, numpy.eye(mol.nao_nr()))
def dumpLUNO(fname, thresh=0.01): chkfile = fname + '.chk' outfile = fname + '_cmo.molden' tools.molden.from_chkfile(outfile, chkfile) #============================= # Natural orbitals # Lowdin basis X=S{-1/2} # psi = chi * C # = chi' * C' # = chi*X*(X{-1}C') #============================= mol, mf = scf.chkfile.load_scf(chkfile) mo_coeff = mf["mo_coeff"] ova = mol.intor_symmetric("cint1e_ovlp_sph") nb = mo_coeff.shape[1] # Check overlap diff = reduce(numpy.dot, (mo_coeff[0].T, ova, mo_coeff[0])) - numpy.identity(nb) print numpy.linalg.norm(diff) diff = reduce(numpy.dot, (mo_coeff[1].T, ova, mo_coeff[1])) - numpy.identity(nb) print numpy.linalg.norm(diff) # UHF-alpha/beta ma = mo_coeff[0] mb = mo_coeff[1] nalpha = (mol.nelectron + mol.spin) / 2 nbeta = (mol.nelectron - mol.spin) / 2 # Spin-averaged DM pTa = numpy.dot(ma[:, :nalpha], ma[:, :nalpha].T) pTb = numpy.dot(mb[:, :nbeta], mb[:, :nbeta].T) pT = 0.5 * (pTa + pTb) # Lowdin basis s12 = sqrtm(ova) s12inv = lowdin(ova) pTOAO = reduce(numpy.dot, (s12, pT, s12)) eig, coeff = scipy.linalg.eigh(-pTOAO) eig = -2.0 * eig eig[eig < 0.0] = 0.0 eig[abs(eig) < 1.e-14] = 0.0 ifplot = False #True if ifplot: import matplotlib.pyplot as plt plt.plot(range(nb), eig, 'ro') plt.show() # Back to AO basis coeff = numpy.dot(s12inv, coeff) diff = reduce(numpy.dot, (coeff.T, ova, coeff)) - numpy.identity(nb) print 'CtSC-I', numpy.linalg.norm(diff) # # Averaged Fock # enorb = mf["mo_energy"] fa = reduce(numpy.dot, (ma, numpy.diag(enorb[0]), ma.T)) fb = reduce(numpy.dot, (mb, numpy.diag(enorb[1]), mb.T)) # Non-orthogonal cases: FC=SCE # Fao = SC*e*C{-1} = S*C*e*Ct*S fav = 0.5 * (fa + fb) # Expectation value of natural orbitals <i|F|i> fexpt = reduce(numpy.dot, (coeff.T, ova, fav, ova, coeff)) enorb = numpy.diag(fexpt) nocc = eig.copy() # # Reordering and define active space according to thresh # idx = 0 active = [] for i in range(nb): if nocc[i] <= 2.0 - thresh and nocc[i] >= thresh: active.append(True) else: active.append(False) print '\nNatural orbitals:' for i in range(nb): print 'orb:', i, active[i], nocc[i], enorb[i] active = numpy.array(active) actIndices = list(numpy.argwhere(active == True).flatten()) cOrbs = coeff[:, :actIndices[0]] aOrbs = coeff[:, actIndices] vOrbs = coeff[:, actIndices[-1] + 1:] nb = cOrbs.shape[0] nc = cOrbs.shape[1] na = aOrbs.shape[1] nv = vOrbs.shape[1] print 'core orbs:', cOrbs.shape print 'act orbs:', aOrbs.shape print 'vir orbs:', vOrbs.shape assert nc + na + nv == nb # dump UNO with open(fname + '_uno.molden', 'w') as thefile: molden.header(mol, thefile) molden.orbital_coeff(mol, thefile, coeff) #===================== # Population analysis #===================== from pyscf import lo aux = lo.orth_ao(mol, method='meta_lowdin') #clmo = ulocal.scdm(cOrbs,ova,aux) #almo = ulocal.scdm(aOrbs,ova,aux) clmo = cOrbs almo = aOrbs ierr, uc = pmloc.loc(mol, clmo) ierr, ua = pmloc.loc(mol, almo) clmo = clmo.dot(uc) almo = almo.dot(ua) vlmo = ulocal.scdm(vOrbs, ova, aux) # P-SORT mo_c, n_c, e_c = ulocal.psort(ova, fav, pT, clmo) mo_o, n_o, e_o = ulocal.psort(ova, fav, pT, almo) mo_v, n_v, e_v = ulocal.psort(ova, fav, pT, vlmo) lmo = numpy.hstack((mo_c, mo_o, mo_v)).copy() enorb = numpy.hstack([e_c, e_o, e_v]) occ = numpy.hstack([n_c, n_o, n_v]) # CHECK diff = reduce(numpy.dot, (lmo.T, ova, lmo)) - numpy.identity(nb) print 'diff=', numpy.linalg.norm(diff) ulocal.lowdinPop(mol, lmo, ova, enorb, occ) ulocal.dumpLMO(mol, fname, lmo) print 'nalpha,nbeta,mol.spin,nb:',\ nalpha,nbeta,mol.spin,nb return mol, ova, fav, pT, nb, nalpha, nbeta, nc, na, nv, lmo, enorb, occ
def dumpLUNO(fname,thresh=0.01): chkfile = fname+'.chk' outfile = fname+'_cmo.molden' tools.molden.from_chkfile(outfile, chkfile) #============================= # Natural orbitals # Lowdin basis X=S{-1/2} # psi = chi * C # = chi' * C' # = chi*X*(X{-1}C') #============================= mol,mf = scf.chkfile.load_scf(chkfile) mo_coeff = mf["mo_coeff"] ova=mol.intor_symmetric("cint1e_ovlp_sph") nb = mo_coeff.shape[1] # Check overlap diff = reduce(numpy.dot,(mo_coeff[0].T,ova,mo_coeff[0])) - numpy.identity(nb) print numpy.linalg.norm(diff) diff = reduce(numpy.dot,(mo_coeff[1].T,ova,mo_coeff[1])) - numpy.identity(nb) print numpy.linalg.norm(diff) # UHF-alpha/beta ma = mo_coeff[0] mb = mo_coeff[1] nalpha = (mol.nelectron+mol.spin)/2 nbeta = (mol.nelectron-mol.spin)/2 # Spin-averaged DM pTa = numpy.dot(ma[:,:nalpha],ma[:,:nalpha].T) pTb = numpy.dot(mb[:,:nbeta],mb[:,:nbeta].T) pT = 0.5*(pTa+pTb) # Lowdin basis s12 = sqrtm(ova) s12inv = lowdin(ova) pTOAO = reduce(numpy.dot,(s12,pT,s12)) eig,coeff = scipy.linalg.eigh(-pTOAO) eig = -2.0*eig eig[eig<0.0]=0.0 eig[abs(eig)<1.e-14]=0.0 ifplot = False #True if ifplot: import matplotlib.pyplot as plt plt.plot(range(nb),eig,'ro') plt.show() # Back to AO basis coeff = numpy.dot(s12inv,coeff) diff = reduce(numpy.dot,(coeff.T,ova,coeff)) - numpy.identity(nb) print 'CtSC-I',numpy.linalg.norm(diff) # # Averaged Fock # enorb = mf["mo_energy"] fa = reduce(numpy.dot,(ma,numpy.diag(enorb[0]),ma.T)) fb = reduce(numpy.dot,(mb,numpy.diag(enorb[1]),mb.T)) # Non-orthogonal cases: FC=SCE # Fao = SC*e*C{-1} = S*C*e*Ct*S fav = 0.5*(fa+fb) # Expectation value of natural orbitals <i|F|i> fexpt = reduce(numpy.dot,(coeff.T,ova,fav,ova,coeff)) enorb = numpy.diag(fexpt) nocc = eig.copy() # # Reordering and define active space according to thresh # idx = 0 active=[] for i in range(nb): if nocc[i]<=2.0-thresh and nocc[i]>=thresh: active.append(True) else: active.append(False) print '\nNatural orbitals:' for i in range(nb): print 'orb:',i,active[i],nocc[i],enorb[i] active = numpy.array(active) actIndices = list(numpy.argwhere(active==True).flatten()) cOrbs = coeff[:,:actIndices[0]] aOrbs = coeff[:,actIndices] vOrbs = coeff[:,actIndices[-1]+1:] nb = cOrbs.shape[0] nc = cOrbs.shape[1] na = aOrbs.shape[1] nv = vOrbs.shape[1] print 'core orbs:',cOrbs.shape print 'act orbs:',aOrbs.shape print 'vir orbs:',vOrbs.shape assert nc+na+nv == nb # dump UNO with open(fname+'_uno.molden','w') as thefile: molden.header(mol,thefile) molden.orbital_coeff(mol,thefile,coeff) #===================== # Population analysis #===================== from pyscf import lo aux = lo.orth_ao(mol,method='meta_lowdin') #clmo = ulocal.scdm(cOrbs,ova,aux) #almo = ulocal.scdm(aOrbs,ova,aux) clmo = cOrbs almo = aOrbs ierr,uc = pmloc.loc(mol,clmo) ierr,ua = pmloc.loc(mol,almo) clmo = clmo.dot(uc) almo = almo.dot(ua) vlmo = ulocal.scdm(vOrbs,ova,aux) # P-SORT mo_c,n_c,e_c = ulocal.psort(ova,fav,pT,clmo) mo_o,n_o,e_o = ulocal.psort(ova,fav,pT,almo) mo_v,n_v,e_v = ulocal.psort(ova,fav,pT,vlmo) lmo = numpy.hstack((mo_c,mo_o,mo_v)).copy() enorb = numpy.hstack([e_c,e_o,e_v]) occ = numpy.hstack([n_c,n_o,n_v]) # CHECK diff = reduce(numpy.dot,(lmo.T,ova,lmo)) - numpy.identity(nb) print 'diff=',numpy.linalg.norm(diff) ulocal.lowdinPop(mol,lmo,ova,enorb,occ) ulocal.dumpLMO(mol,fname,lmo) print 'nalpha,nbeta,mol.spin,nb:',\ nalpha,nbeta,mol.spin,nb return mol,ova,fav,pT,nb,nalpha,nbeta,nc,na,nv,lmo,enorb,occ
mol.verbose = 4 mol.spin = 0 mol.symmetry = 1 mol.charge = 0 mol.build() mf = dft.RKS(mol).density_fit() mf.with_df.auxbasis = 'def2-svp-jkfit' mf.conv_tol = 1e-8 mf.grids.radi_method = dft.mura_knowles mf.grids.becke_scheme = dft.stratmann mf.grids.level = 4 mf.xc = 'pbe0' mf.kernel() c = lo.orth_ao(mol, 'nao', scf_method=mf) mo = numpy.linalg.solve(c, mf.mo_coeff) dm = mf.make_rdm1(mo, mf.mo_occ) s = mol.intor('cint1e_ovlp_sph') s = reduce(numpy.dot, (c.T, s, c)) label = mol.spheric_labels(False) lib.logger.info(mf, '\nPopulation and charges in NAO basis') lib.logger.info(mf, '###################################') pop = einsum('ij,ji->i', dm, s) chg1 = numpy.zeros(mol.natm) qq1 = numpy.zeros(mol.natm) for i, s1 in enumerate(label): chg1[s1[0]] += pop[i]
O 0.0 0.0 1.12 ''' mol.verbose = 4 mol.spin = 0 mol.symmetry = 0 mol.charge = 0 mol.build() mf = scf.RHF(mol) mf.kernel() dm = mf.make_rdm1() nao = mol.nao_nr() s = mol.intor('cint1e_ovlp_sph') c = lo.orth.restore_ao_character(mol, 'ano') orth_coeff = lo.orth_ao(mol, 'nao', scf_method=mf, pre_orth_ao=c, s=s) c_inv = numpy.dot(orth_coeff.T, s) dm = reduce(numpy.dot, (c_inv, dm, c_inv.T.conj())) s = numpy.eye(nao) label = mol.spheric_labels(False) lib.logger.info(mf, '\nPopulation and charges in NAO basis') lib.logger.info(mf, '###################################') pop = einsum('ij,ji->i', dm, s) chg1 = numpy.zeros(mol.natm) qq1 = numpy.zeros(mol.natm) for i, s1 in enumerate(label): chg1[s1[0]] += pop[i] for ia in range(mol.natm): symb = mol.atom_symbol(ia)