def update(self, **kwargs): from PyQuante.Ints import getJ, getK from PyQuante.LA2 import geigh, mkdens from PyQuante.rohf import ao2mo from PyQuante.hartree_fock import get_energy from PyQuante.NumWrap import eigh, matrixmultiply if self.orbs is None: self.orbe, self.orbs = geigh(self.h, self.S) Da = mkdens(self.orbs, 0, self.nalpha) Db = mkdens(self.orbs, 0, self.nbeta) Ja = getJ(self.ERI, Da) Jb = getJ(self.ERI, Db) Ka = getK(self.ERI, Da) Kb = getK(self.ERI, Db) Fa = self.h + Ja + Jb - Ka Fb = self.h + Ja + Jb - Kb energya = get_energy(self.h, Fa, Da) energyb = get_energy(self.h, Fb, Db) self.energy = (energya + energyb) / 2 + self.Enuke Fa = ao2mo(Fa, self.orbs) Fb = ao2mo(Fb, self.orbs) # Building the approximate Fock matrices in the MO basis F = 0.5 * (Fa + Fb) K = Fb - Fa # The Fock matrix now looks like # F-K | F + K/2 | F # --------------------------------- # F + K/2 | F | F - K/2 # --------------------------------- # F | F - K/2 | F + K # Make explicit slice objects to simplify this do = slice(0, self.nbeta) so = slice(self.nbeta, self.nalpha) uo = slice(self.nalpha, self.norbs) F[do, do] -= K[do, do] F[uo, uo] += K[uo, uo] F[do, so] += 0.5 * K[do, so] F[so, do] += 0.5 * K[so, do] F[so, uo] -= 0.5 * K[so, uo] F[uo, so] -= 0.5 * K[uo, so] self.orbe, mo_orbs = eigh(F) self.orbs = matrixmultiply(self.orbs, mo_orbs) return
def update(self,**opts): from PyQuante.Ints import getJ,getK from PyQuante.LA2 import geigh,mkdens from PyQuante.rohf import ao2mo from PyQuante.hartree_fock import get_energy from PyQuante.NumWrap import eigh,matrixmultiply if self.orbs is None: self.orbe,self.orbs = geigh(self.h, self.S) Da = mkdens(self.orbs,0,self.nalpha) Db = mkdens(self.orbs,0,self.nbeta) Ja = getJ(self.ERI,Da) Jb = getJ(self.ERI,Db) Ka = getK(self.ERI,Da) Kb = getK(self.ERI,Db) Fa = self.h+Ja+Jb-Ka Fb = self.h+Ja+Jb-Kb energya = get_energy(self.h,Fa,Da) energyb = get_energy(self.h,Fb,Db) self.energy = (energya+energyb)/2 + self.Enuke Fa = ao2mo(Fa,self.orbs) Fb = ao2mo(Fb,self.orbs) # Building the approximate Fock matrices in the MO basis F = 0.5*(Fa+Fb) K = Fb-Fa # The Fock matrix now looks like # F-K | F + K/2 | F # --------------------------------- # F + K/2 | F | F - K/2 # --------------------------------- # F | F - K/2 | F + K # Make explicit slice objects to simplify this do = slice(0,self.nbeta) so = slice(self.nbeta,self.nalpha) uo = slice(self.nalpha,self.norbs) F[do,do] -= K[do,do] F[uo,uo] += K[uo,uo] F[do,so] += 0.5*K[do,so] F[so,do] += 0.5*K[so,do] F[so,uo] -= 0.5*K[so,uo] F[uo,so] -= 0.5*K[uo,so] self.orbe,mo_orbs = eigh(F) self.orbs = matrixmultiply(self.orbs,mo_orbs) return
def simple_hf(atoms,S,h,Ints): from PyQuante.LA2 import mkdens from PyQuante.hartree_fock import get_energy orbe,orbs = geigh(h,S) nclosed,nopen = atoms.get_closedopen() enuke = atoms.get_enuke() nocc = nclosed eold = 0 for i in range(15): D = mkdens(orbs,0,nocc) G = get2JmK(Ints,D) F = h+G orbe,orbs = geigh(F,S) energy = get_energy(h,F,D,enuke) print "%d %f" % (i,energy) if abs(energy-eold) < 1e-4: break eold = energy print "Final HF energy for system %s is %f" % (atoms.name,energy) return energy,orbe,orbs
def simple_hf(atoms, S, h, Ints): from PyQuante.LA2 import mkdens from PyQuante.hartree_fock import get_energy orbe, orbs = geigh(h, S) nclosed, nopen = atoms.get_closedopen() enuke = atoms.get_enuke() nocc = nclosed eold = 0 for i in range(15): D = mkdens(orbs, 0, nocc) G = get2JmK(Ints, D) F = h + G orbe, orbs = geigh(F, S) energy = get_energy(h, F, D, enuke) print "%d %f" % (i, energy) if abs(energy - eold) < 1e-4: break eold = energy print "Final HF energy for system %s is %f" % (atoms.name, energy) return energy, orbe, orbs
def rohf(atoms,**opts): """\ rohf(atoms,**opts) - Restriced Open Shell Hartree Fock atoms A Molecule object containing the molecule """ ConvCriteria = opts.get('ConvCriteria',1e-5) MaxIter = opts.get('MaxIter',40) DoAveraging = opts.get('DoAveraging',True) averaging = opts.get('averaging',0.95) verbose = opts.get('verbose',True) bfs = opts.get('bfs',None) if not bfs: basis_data = opts.get('basis_data',None) bfs = getbasis(atoms,basis_data) nbf = len(bfs) integrals = opts.get('integrals', None) if integrals: S,h,Ints = integrals else: S,h,Ints = getints(bfs,atoms) nel = atoms.get_nel() nalpha,nbeta = atoms.get_alphabeta() S,h,Ints = getints(bfs,atoms) orbs = opts.get('orbs',None) if orbs is None: orbe,orbs = geigh(h,S) norbs = nbf enuke = atoms.get_enuke() eold = 0. if verbose: print "ROHF calculation on %s" % atoms.name if verbose: print "Nbf = %d" % nbf if verbose: print "Nalpha = %d" % nalpha if verbose: print "Nbeta = %d" % nbeta if verbose: print "Averaging = %s" % DoAveraging print "Optimization of HF orbitals" for i in xrange(MaxIter): if verbose: print "SCF Iteration:",i,"Starting Energy:",eold Da = mkdens(orbs,0,nalpha) Db = mkdens(orbs,0,nbeta) if DoAveraging: if i: Da = averaging*Da + (1-averaging)*Da0 Db = averaging*Db + (1-averaging)*Db0 Da0 = Da Db0 = Db Ja = getJ(Ints,Da) Jb = getJ(Ints,Db) Ka = getK(Ints,Da) Kb = getK(Ints,Db) Fa = h+Ja+Jb-Ka Fb = h+Ja+Jb-Kb energya = get_energy(h,Fa,Da) energyb = get_energy(h,Fb,Db) eone = (trace2(Da,h) + trace2(Db,h))/2 etwo = (trace2(Da,Fa) + trace2(Db,Fb))/2 energy = (energya+energyb)/2 + enuke print i,energy,eone,etwo,enuke if abs(energy-eold) < ConvCriteria: break eold = energy Fa = ao2mo(Fa,orbs) Fb = ao2mo(Fb,orbs) # Building the approximate Fock matrices in the MO basis F = 0.5*(Fa+Fb) K = Fb-Fa # The Fock matrix now looks like # F-K | F + K/2 | F # --------------------------------- # F + K/2 | F | F - K/2 # --------------------------------- # F | F - K/2 | F + K # Make explicit slice objects to simplify this do = slice(0,nbeta) so = slice(nbeta,nalpha) uo = slice(nalpha,norbs) F[do,do] -= K[do,do] F[uo,uo] += K[uo,uo] F[do,so] += 0.5*K[do,so] F[so,do] += 0.5*K[so,do] F[so,uo] -= 0.5*K[so,uo] F[uo,so] -= 0.5*K[uo,so] orbe,mo_orbs = eigh(F) orbs = matrixmultiply(orbs,mo_orbs) if verbose: print "Final ROHF energy for system %s is %f" % (atoms.name,energy) return energy,orbe,orbs
from PyQuante.Ints import get2JmK,getbasis,getints from PyQuante.Convergence import DIIS from PyQuante.hartree_fock import get_energy bfs = getbasis(h2,basis="3-21g") nclosed,nopen = h2.get_closedopen() nocc = nclosed nel = h2.get_nel() S,h,Ints = getints(bfs,h2) orbe,orbs = geigh(h,S) enuke = h2.get_enuke() eold = 0 avg = DIIS(S) for i in range(20): D = mkdens(orbs,0,nocc) G = get2JmK(Ints,D) F = h+G F = avg.getF(F,D) orbe,orbs = geigh(F,S) energy = get_energy(h,F,D,enuke) print i,energy,energy-eold if abs(energy-eold)<1e-5: break eold = energy print "Converged" print energy, "(benchmark = -1.122956)"
def pyq1_rohf(atomtuples=[(2,(0,0,0))],basis = '6-31G**',maxit=10,mult=3): from PyQuante import Ints,settings,Molecule from PyQuante.hartree_fock import get_energy from PyQuante.MG2 import MG2 as MolecularGrid from PyQuante.LA2 import mkdens,geigh,trace2,simx from PyQuante.Ints import getJ,getK print ("PyQ1 ROHF run") atoms = Molecule('Pyq1',atomlist=atomtuples,multiplicity=mult) bfs = Ints.getbasis(atoms,basis=basis) S,h,I2e = Ints.getints(bfs,atoms) nbf = norbs = len(bfs) nel = atoms.get_nel() nalpha,nbeta = atoms.get_alphabeta() enuke = atoms.get_enuke() orbe,orbs = geigh(h,S) eold = 0 for i in range(maxit): Da = mkdens(orbs,0,nalpha) Db = mkdens(orbs,0,nbeta) Ja = getJ(I2e,Da) Jb = getJ(I2e,Db) Ka = getK(I2e,Da) Kb = getK(I2e,Db) Fa = h+Ja+Jb-Ka Fb = h+Ja+Jb-Kb energya = get_energy(h,Fa,Da) energyb = get_energy(h,Fb,Db) eone = (trace2(Da,h) + trace2(Db,h))/2 etwo = (trace2(Da,Fa) + trace2(Db,Fb))/2 energy = (energya+energyb)/2 + enuke print (i,energy,eone,etwo,enuke) if abs(energy-eold) < 1e-5: break eold = energy Fa = simx(Fa,orbs) Fb = simx(Fb,orbs) # Building the approximate Fock matrices in the MO basis F = 0.5*(Fa+Fb) K = Fb-Fa # The Fock matrix now looks like # F-K | F + K/2 | F # --------------------------------- # F + K/2 | F | F - K/2 # --------------------------------- # F | F - K/2 | F + K # Make explicit slice objects to simplify this do = slice(0,nbeta) so = slice(nbeta,nalpha) uo = slice(nalpha,norbs) F[do,do] -= K[do,do] F[uo,uo] += K[uo,uo] F[do,so] += 0.5*K[do,so] F[so,do] += 0.5*K[so,do] F[so,uo] -= 0.5*K[so,uo] F[uo,so] -= 0.5*K[uo,so] orbe,mo_orbs = np.linalg.eigh(F) orbs = np.dot(orbs,mo_orbs) return energy,orbe,orbs
def pyq1_rohf(atomtuples=[(2, (0, 0, 0))], basis='6-31G**', maxit=10, mult=3): from PyQuante import Ints, settings, Molecule from PyQuante.hartree_fock import get_energy from PyQuante.MG2 import MG2 as MolecularGrid from PyQuante.LA2 import mkdens, geigh, trace2, simx from PyQuante.Ints import getJ, getK print("PyQ1 ROHF run") atoms = Molecule('Pyq1', atomlist=atomtuples, multiplicity=mult) bfs = Ints.getbasis(atoms, basis=basis) S, h, I2e = Ints.getints(bfs, atoms) nbf = norbs = len(bfs) nel = atoms.get_nel() nalpha, nbeta = atoms.get_alphabeta() enuke = atoms.get_enuke() orbe, orbs = geigh(h, S) eold = 0 for i in range(maxit): Da = mkdens(orbs, 0, nalpha) Db = mkdens(orbs, 0, nbeta) Ja = getJ(I2e, Da) Jb = getJ(I2e, Db) Ka = getK(I2e, Da) Kb = getK(I2e, Db) Fa = h + Ja + Jb - Ka Fb = h + Ja + Jb - Kb energya = get_energy(h, Fa, Da) energyb = get_energy(h, Fb, Db) eone = (trace2(Da, h) + trace2(Db, h)) / 2 etwo = (trace2(Da, Fa) + trace2(Db, Fb)) / 2 energy = (energya + energyb) / 2 + enuke print(i, energy, eone, etwo, enuke) if abs(energy - eold) < 1e-5: break eold = energy Fa = simx(Fa, orbs) Fb = simx(Fb, orbs) # Building the approximate Fock matrices in the MO basis F = 0.5 * (Fa + Fb) K = Fb - Fa # The Fock matrix now looks like # F-K | F + K/2 | F # --------------------------------- # F + K/2 | F | F - K/2 # --------------------------------- # F | F - K/2 | F + K # Make explicit slice objects to simplify this do = slice(0, nbeta) so = slice(nbeta, nalpha) uo = slice(nalpha, norbs) F[do, do] -= K[do, do] F[uo, uo] += K[uo, uo] F[do, so] += 0.5 * K[do, so] F[so, do] += 0.5 * K[so, do] F[so, uo] -= 0.5 * K[so, uo] F[uo, so] -= 0.5 * K[uo, so] orbe, mo_orbs = np.linalg.eigh(F) orbs = np.dot(orbs, mo_orbs) return energy, orbe, orbs
#get eigen values and vectors of transformed Fock matrix eVal, eVec = eigh(Fmo) #Section 9############################ #transform eigen vectors back to AO basis to get C C = matrixmultiply(X, eVec) #Section 10############################ #calculate a new density matrix from C D = HF.mkdens(C, 0, molecule.get_closedopen()[0]) #Section 11############################ #check convergence critera, #which for this particular program is checking #the delta energy of the system E = HF.get_energy(Hcore, F, D, molecule.get_enuke()) #append to energy list energy.append(E) #increment cycle counter cycle += 1 #if the change in energy from one iteration to the next #is less than the specfied convergence difference, then end SCF procedure if (abs(energy[cycle] - energy[cycle - 1]) <= convergenceLimit): break #End of SCF procedure, #print important information print("Emergy: " + str(energy[cycle]) + " Hartrees")