def __init__(self, mf, method = 'overlap'): ''' Prepare the orthonormal/localized set of orbitals for DMET Args: mf : a mean-field wf method : overlap/boys/lowdin/meta_lowdin. if method == lattice: U = 1 Return: U : Tranformation matrix to the orthonormal basis ''' self.mol = mf.mol self.mf = mf self.Nelecs = mf.mol.nelectron self.Norbs = mf.mol.nao_nr() self.U = None self.orthoOEI = None self.orthoTEI = None self.S = mf.get_ovlp() if method == 'overlap': self.U = scipy.linalg.fractional_matrix_power(self.S, -0.5) elif method == 'boys': self.U = self.mf.mo_coeff loc = localizer.localizer( self.mol, self.U, method, use_full_hessian = True ) loc.verbose = 0 self.U = loc.optimize( threshold = 1.e-8 ) elif method == 'lowdin': ovlp = self.mol.intor('cint1e_ovlp_sph') ovlp_eigs, ovlp_vecs = np.linalg.eigh( ovlp ) assert ( np.linalg.norm( np.dot( np.dot( ovlp_vecs, np.diag( ovlp_eigs ) ), ovlp_vecs.T ) - ovlp ) < 1e-10 ) self.U = np.dot( np.dot( ovlp_vecs, np.diag( np.power( ovlp_eigs, -0.5 ) ) ), ovlp_vecs.T ) elif method == 'meta_lowdin': nao.AOSHELL[4] = ['1s0p0d0f', '2s1p0d0f'] #redefine the valence shell for Be self.U = orth.orth_ao( self.mol, 'meta_lowdin' ) elif method == 'lattice': self.orthoOEI = self.mf.get_hcore() self.orthoTEI = ao2mo.incore.full(ao2mo.restore(8, self.mf._eri, self.Norbs), self.S, compact=False).reshape(self.Norbs, self.Norbs, self.Norbs, self.Norbs) self.orthoFOCK = self.orthoOEI + self.mf.get_veff() if method != 'lattice': #Tranform One-Electron Integral to orthonormal basis OEI = self.mf.get_hcore() self.orthoOEI = reduce(np.dot, (self.U.T, OEI, self.U)) #Tranform Two-Electron Integral to orthonormal basis Norbs = self.Norbs g_format = self.mol.intor('cint2e_sph') TEI = np.zeros([Norbs, Norbs, Norbs, Norbs]) for cn1 in range(Norbs): for cn2 in range(Norbs): for cn3 in range(Norbs): for cn4 in range(Norbs): TEI[cn1][cn2][cn3][cn4] = g_format[cn1*Norbs + cn2][cn3*Norbs + cn4] self.orthoTEI = ao2mo.incore.full(ao2mo.restore(8, TEI, Norbs), self.U, compact=False).reshape(Norbs, Norbs, Norbs, Norbs) #Tranform Fock to orthonormal basis vhf = self.mf.get_veff() FOCK = OEI + vhf self.orthoFOCK = reduce(np.dot, (self.U.T, FOCK, self.U))
def build_iAO_basis(mol,Cf,Cf_core,Cf_vale,nfreeze): import numpy as np import scipy.linalg as sla S_f = mol.intor_symmetric('cint1e_ovlp_sph') nup = mol.nelectron//2 iao, Cf_core = build_iao(S_f,Cf[:,:nup],Cf_vale,P_core=Cf_core,nfreeze=nfreeze) loc = localizer.localizer(mol,iao,'boys') loc.verbose = 5 iao_loc = loc.optimize (threshold=1.0e-5) # loc = lo.Boys(mol, iao).kernel() # iao_loc = loc del loc # need to find occupied orbitals orthogonal to core if(Cf_core is not None): Cf_x = project(Cf[:,:nup],S_f,Cf_core,'out') return iao_loc,Cf_core,Cf_x else: Cf_x = Cf[:,:nup] return iao_loc,None,Cf_x
# # We now dump out UHF natual orbitals and localized orbitals to help identify # active space. # # dump UHF natrual orbital # tools.molden.from_mo(mol, fname+'_uno.molden', coeff) #============================= # localized orbitals #============================= iflocal = False if iflocal: # We implemented different localization later from pyscf.tools import localizer loc = localizer.localizer(mol,ma[:,:mol.nelectron/2],'boys') loc.verbose = 10 new_coeff = loc.optimize() loc = localizer.localizer(mol,ma[:,mol.nelectron/2:],'boys') new_coeff2 = loc.optimize() lmo = numpy.hstack([new_coeff,new_coeff2]) tools.molden.from_mo(mol, fname+'lmo.molden', lmo) # # Test orthogonality because occasionally localization procedure may break the # orbital orthogonality (when AO functions are close to linear dependent). # cOrbsOAO = numpy.dot(s12,cOrbs) aOrbsOAO = numpy.dot(s12,aOrbs) vOrbsOAO = numpy.dot(s12,vOrbs) print('Ortho-cOAO',numpy.linalg.norm(numpy.dot(cOrbsOAO.T,cOrbsOAO)-numpy.identity(nc)))
# # We now dump out UHF natual orbitals and localized orbitals to help identify # active space. # # dump UHF natrual orbital # tools.molden.from_mo(mol, fname + '_uno.molden', coeff) #============================= # localized orbitals #============================= iflocal = False if iflocal: # We implemented different localization later from pyscf.tools import localizer loc = localizer.localizer(mol, ma[:, :mol.nelectron / 2], 'boys') loc.verbose = 10 new_coeff = loc.optimize() loc = localizer.localizer(mol, ma[:, mol.nelectron / 2:], 'boys') new_coeff2 = loc.optimize() lmo = numpy.hstack([new_coeff, new_coeff2]) tools.molden.from_mo(mol, fname + 'lmo.molden', lmo) # # Test orthogonality because occasionally localization procedure may break the # orbital orthogonality (when AO functions are close to linear dependent). # cOrbsOAO = numpy.dot(s12, cOrbs) aOrbsOAO = numpy.dot(s12, aOrbs) vOrbsOAO = numpy.dot(s12, vOrbs) print('Ortho-cOAO',
C 1.211265339156 -0.699329968382 0.000000000000 H -2.157597486829 1.245660462400 0.000000000000 C -1.211265339156 0.699329968382 0.000000000000 H -2.157597486829 -1.245660462400 0.000000000000 C -1.211265339156 -0.699329968382 0.000000000000 ''' mol.basis = '6-31g' mol.symmetry = 0 mol.charge = 0 mol.spin = 0 mol.build() mf = scf.RHF(mol) mf.verbose = 0 mf.scf() filename_mo = 'benzene-631g-mo.molden' filename_boys = 'benzene-631g-boys.molden' with open(filename_mo, 'w') as thefile: molden.header(mol, thefile) molden.orbital_coeff(mol, thefile, mf.mo_coeff) print("Molecular orbitals saved in", filename_mo) # Localize the pi-type orbitals. Counting starts from 0! 12 orbitals as 6-31G is DZ. tolocalize = np.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1 loc = localizer.localizer(mol, mf.mo_coeff[:, tolocalize], 'boys') loc.verbose = param.VERBOSE_DEBUG new_coeff = loc.optimize() loc.dump_molden(filename_boys, new_coeff) print("Boys localized pi-orbitals saved in", filename_boys)
def __init__(self, the_mf, active_orbs, localizationtype, ao_rotation=None, use_full_hessian=True, localization_threshold=1e-6): assert ((localizationtype == 'meta_lowdin') or (localizationtype == 'boys') or (localizationtype == 'lowdin') or (localizationtype == 'iao')) # Information on the full HF problem self.mol = the_mf.mol self.fullEhf = the_mf.hf_energy self.fullDMao = np.dot(np.dot(the_mf.mo_coeff, np.diag(the_mf.mo_occ)), the_mf.mo_coeff.T) self.fullJKao = scf.hf.get_veff( self.mol, self.fullDMao, 0, 0, 1) #Last 3 numbers: dm_last, vhf_last, hermi self.fullFOCKao = self.mol.intor('cint1e_kin_sph') + self.mol.intor( 'cint1e_nuc_sph') + self.fullJKao # Active space information self._which = localizationtype self.active = np.zeros([self.mol.nao_nr()], dtype=int) self.active[active_orbs] = 1 self.Norbs = np.sum(self.active) # Number of active space orbitals self.Nelec = int( np.rint(self.mol.nelectron - np.sum(the_mf.mo_occ[self.active == 0])) ) # Total number of electrons minus frozen part # Localize the orbitals if ((self._which == 'meta_lowdin') or (self._which == 'boys')): if (self._which == 'meta_lowdin'): assert (self.Norbs == self.mol.nao_nr() ) # Full active space required if (self._which == 'boys'): self.ao2loc = the_mf.mo_coeff[:, self.active == 1] if (self.Norbs == self.mol.nao_nr() ): # If you want the full active, do meta-Lowdin nao.AOSHELL[4] = ['1s0p0d0f', '2s1p0d0f' ] # redefine the valence shell for Be self.ao2loc = orth.orth_ao(self.mol, 'meta_lowdin') if (ao_rotation != None): self.ao2loc = np.dot(self.ao2loc, ao_rotation.T) if (self._which == 'boys'): old_verbose = self.mol.verbose self.mol.verbose = 5 loc = localizer.localizer(self.mol, self.ao2loc, self._which, use_full_hessian) self.mol.verbose = old_verbose self.ao2loc = loc.optimize(threshold=localization_threshold) self.TI_OK = False # Check yourself if OK, then overwrite if (self._which == 'lowdin'): assert (self.Norbs == self.mol.nao_nr() ) # Full active space required ovlp = self.mol.intor('cint1e_ovlp_sph') ovlp_eigs, ovlp_vecs = np.linalg.eigh(ovlp) assert (np.linalg.norm( np.dot(np.dot(ovlp_vecs, np.diag(ovlp_eigs)), ovlp_vecs.T) - ovlp) < 1e-10) self.ao2loc = np.dot( np.dot(ovlp_vecs, np.diag(np.power(ovlp_eigs, -0.5))), ovlp_vecs.T) self.TI_OK = False # Check yourself if OK, then overwrite if (self._which == 'iao'): assert (self.Norbs == self.mol.nao_nr() ) # Full active space assumed self.ao2loc = iao_helper.localize_iao(self.mol, the_mf) if (ao_rotation != None): self.ao2loc = np.dot(self.ao2loc, ao_rotation.T) self.TI_OK = False # Check yourself if OK, then overwrite #self.molden( 'dump.molden' ) # Debugging mode assert (self.loc_ortho() < 1e-8) # Effective Hamiltonian due to frozen part self.frozenDMmo = np.array(the_mf.mo_occ, copy=True) self.frozenDMmo[self.active == 1] = 0 # Only the frozen MO occupancies nonzero self.frozenDMao = np.dot( np.dot(the_mf.mo_coeff, np.diag(self.frozenDMmo)), the_mf.mo_coeff.T) self.frozenJKao = scf.hf.get_veff( self.mol, self.frozenDMao, 0, 0, 1) #Last 3 numbers: dm_last, vhf_last, hermi self.frozenOEIao = self.fullFOCKao - self.fullJKao + self.frozenJKao # Active space OEI and ERI self.activeCONST = self.mol.energy_nuc() + np.einsum( 'ij,ij->', self.frozenOEIao - 0.5 * self.frozenJKao, self.frozenDMao) self.activeOEI = np.dot(np.dot(self.ao2loc.T, self.frozenOEIao), self.ao2loc) self.activeFOCK = np.dot(np.dot(self.ao2loc.T, self.fullFOCKao), self.ao2loc) if (self.Norbs <= 150): self.ERIinMEM = True self.activeERI = ao2mo.outcore.full_iofree( self.mol, self.ao2loc, compact=False).reshape(self.Norbs, self.Norbs, self.Norbs, self.Norbs) else: self.ERIinMEM = False self.activeERI = None
C 1.211265339156 -0.699329968382 0.000000000000 H -2.157597486829 1.245660462400 0.000000000000 C -1.211265339156 0.699329968382 0.000000000000 H -2.157597486829 -1.245660462400 0.000000000000 C -1.211265339156 -0.699329968382 0.000000000000 ''' mol.basis = '6-31g' mol.symmetry = 0 mol.charge = 0 mol.spin = 0 mol.build() mf = scf.RHF( mol ) mf.verbose = 0 mf.scf() filename_mo = 'benzene-631g-mo.molden' filename_boys = 'benzene-631g-boys.molden' with open( filename_mo, 'w' ) as thefile: molden.header( mol, thefile ) molden.orbital_coeff( mol, thefile, mf.mo_coeff ) print("Molecular orbitals saved in", filename_mo) # Localize the pi-type orbitals. Counting starts from 0! 12 orbitals as 6-31G is DZ. tolocalize = np.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1 loc = localizer.localizer( mol, mf.mo_coeff[:,tolocalize], 'boys' ) loc.verbose = param.VERBOSE_DEBUG new_coeff = loc.optimize() loc.dump_molden( filename_boys, new_coeff ) print("Boys localized pi-orbitals saved in", filename_boys)
def __init__( self, the_mf, active_orbs, localizationtype, ao_rotation=None, use_full_hessian=True, localization_threshold=1e-6 ): assert (( localizationtype == 'meta_lowdin' ) or ( localizationtype == 'boys' ) or ( localizationtype == 'lowdin' ) or ( localizationtype == 'iao' )) # Information on the full HF problem self.mol = the_mf.mol self.fullEhf = the_mf.hf_energy self.fullDMao = np.dot(np.dot( the_mf.mo_coeff, np.diag( the_mf.mo_occ )), the_mf.mo_coeff.T ) self.fullJKao = scf.hf.get_veff( self.mol, self.fullDMao, 0, 0, 1 ) #Last 3 numbers: dm_last, vhf_last, hermi self.fullFOCKao = self.mol.intor('cint1e_kin_sph') + self.mol.intor('cint1e_nuc_sph') + self.fullJKao # Active space information self._which = localizationtype self.active = np.zeros( [ self.mol.nao_nr() ], dtype=int ) self.active[ active_orbs ] = 1 self.Norbs = np.sum( self.active ) # Number of active space orbitals self.Nelec = int(np.rint( self.mol.nelectron - np.sum( the_mf.mo_occ[ self.active==0 ] ))) # Total number of electrons minus frozen part # Localize the orbitals if (( self._which == 'meta_lowdin' ) or ( self._which == 'boys' )): if ( self._which == 'meta_lowdin' ): assert( self.Norbs == self.mol.nao_nr() ) # Full active space required if ( self._which == 'boys' ): self.ao2loc = the_mf.mo_coeff[ : , self.active==1 ] if ( self.Norbs == self.mol.nao_nr() ): # If you want the full active, do meta-Lowdin nao.AOSHELL[4] = ['1s0p0d0f', '2s1p0d0f'] # redefine the valence shell for Be self.ao2loc = orth.orth_ao( self.mol, 'meta_lowdin' ) if ( ao_rotation != None ): self.ao2loc = np.dot( self.ao2loc, ao_rotation.T ) if ( self._which == 'boys' ): old_verbose = self.mol.verbose self.mol.verbose = 5 loc = localizer.localizer( self.mol, self.ao2loc, self._which, use_full_hessian ) self.mol.verbose = old_verbose self.ao2loc = loc.optimize( threshold=localization_threshold ) self.TI_OK = False # Check yourself if OK, then overwrite if ( self._which == 'lowdin' ): assert( self.Norbs == self.mol.nao_nr() ) # Full active space required ovlp = self.mol.intor('cint1e_ovlp_sph') ovlp_eigs, ovlp_vecs = np.linalg.eigh( ovlp ) assert ( np.linalg.norm( np.dot( np.dot( ovlp_vecs, np.diag( ovlp_eigs ) ), ovlp_vecs.T ) - ovlp ) < 1e-10 ) self.ao2loc = np.dot( np.dot( ovlp_vecs, np.diag( np.power( ovlp_eigs, -0.5 ) ) ), ovlp_vecs.T ) self.TI_OK = False # Check yourself if OK, then overwrite if ( self._which == 'iao' ): assert( self.Norbs == self.mol.nao_nr() ) # Full active space assumed self.ao2loc = iao_helper.localize_iao( self.mol, the_mf ) if ( ao_rotation != None ): self.ao2loc = np.dot( self.ao2loc, ao_rotation.T ) self.TI_OK = False # Check yourself if OK, then overwrite #self.molden( 'dump.molden' ) # Debugging mode assert( self.loc_ortho() < 1e-8 ) # Effective Hamiltonian due to frozen part self.frozenDMmo = np.array( the_mf.mo_occ, copy=True ) self.frozenDMmo[ self.active==1 ] = 0 # Only the frozen MO occupancies nonzero self.frozenDMao = np.dot(np.dot( the_mf.mo_coeff, np.diag( self.frozenDMmo )), the_mf.mo_coeff.T ) self.frozenJKao = scf.hf.get_veff( self.mol, self.frozenDMao, 0, 0, 1 ) #Last 3 numbers: dm_last, vhf_last, hermi self.frozenOEIao = self.fullFOCKao - self.fullJKao + self.frozenJKao # Active space OEI and ERI self.activeCONST = self.mol.energy_nuc() + np.einsum( 'ij,ij->', self.frozenOEIao - 0.5*self.frozenJKao, self.frozenDMao ) self.activeOEI = np.dot( np.dot( self.ao2loc.T, self.frozenOEIao ), self.ao2loc ) self.activeFOCK = np.dot( np.dot( self.ao2loc.T, self.fullFOCKao ), self.ao2loc ) if ( self.Norbs <= 150 ): self.ERIinMEM = True self.activeERI = ao2mo.outcore.full_iofree( self.mol, self.ao2loc, compact=False ).reshape(self.Norbs, self.Norbs, self.Norbs, self.Norbs) else: self.ERIinMEM = False self.activeERI = None
from pyscf import gto, scf, lo from pyscf.tools import localizer mol = gto.Mole() mol.atom = ''' He 0. 0. 0.2 H 0. -0.5 -0.4 H 0. 0.5 -0.4 ''' mol.basis = 'sto-3g' mol.build() mf = scf.RHF(mol).run() print mf.mo_coeff loc = localizer.localizer(mol, mf.mo_coeff, 'boys') loc.verbose = 5 print("loc object") print(loc.coeff) new_coeff = loc.optimize(threshold=1e-5) #loc = lo.Boys(mol, mf.mo_coeff).kernel() print(new_coeff) #print("localized = ") #print( loc)
C 1.211265339156 -0.699329968382 0.000000000000 H -2.157597486829 1.245660462400 0.000000000000 C -1.211265339156 0.699329968382 0.000000000000 H -2.157597486829 -1.245660462400 0.000000000000 C -1.211265339156 -0.699329968382 0.000000000000 ''' mol.basis = '6-31g' mol.symmetry = 0 mol.charge = 0 mol.spin = 0 mol.build() mf = scf.RHF( mol ) mf.verbose = 0 mf.scf() filename_mo = 'benzene-631g-mo.molden' filename_edmiston = 'benzene-631g-edmiston.molden' with open( filename_mo, 'w' ) as thefile: molden.header( mol, thefile ) molden.orbital_coeff( mol, thefile, mf.mo_coeff ) print("Molecular orbitals saved in", filename_mo) # Localize the pi-type orbitals. Counting starts from 0! 12 orbitals as 6-31G is DZ. tolocalize = np.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1 loc = localizer.localizer( mol, mf.mo_coeff[:,tolocalize], 'edmiston' ) loc.verbose = param.VERBOSE_DEBUG new_coeff = loc.optimize() loc.dump_molden( filename_edmiston, new_coeff ) print("Edmiston-Ruedenberg localized pi-orbitals saved in", filename_edmiston)