def get_energy(self, b): self.iter += 1 ba = b[:self.nbf] bb = b[self.nbf:] self.Hoepa = get_Hoep(ba, self.H0, self.Gij) self.Hoepb = get_Hoep(bb, self.H0, self.Gij) self.orbea, self.orbsa = geigh(self.Hoepa, self.S) self.orbeb, self.orbsb = geigh(self.Hoepb, self.S) if self.etemp: self.Da, entropya = mkdens_fermi(2 * self.nalpha, self.orbea, self.orbsa, self.etemp) self.Db, entropyb = mkdens_fermi(2 * self.nbeta, self.orbeb, self.orbsb, self.etemp) self.entropy = 0.5 * (entropya + entropyb) else: self.Da = mkdens(self.orbsa, 0, self.nalpha) self.Db = mkdens(self.orbsb, 0, self.nbeta) self.entropy = 0 J = getJ(self.Ints, self.Da + self.Db) Ka = getK(self.Ints, self.Da) Kb = getK(self.Ints, self.Db) self.Fa = self.h + J - Ka self.Fb = self.h + J - Kb self.energy = 0.5*(trace2(self.h+self.Fa,self.Da) + trace2(self.h+self.Fb,self.Db))\ + self.Enuke + self.entropy if self.iter == 1 or self.iter % 10 == 0: logging.debug("%4d %10.5f %10.5f" % (self.iter, self.energy, dot(b, b))) return self.energy
def get_energy(self,b): self.iter += 1 ba = b[:self.nbf] bb = b[self.nbf:] self.Hoepa = get_Hoep(ba,self.H0,self.Gij) self.Hoepb = get_Hoep(bb,self.H0,self.Gij) self.orbea,self.orbsa = geigh(self.Hoepa,self.S) self.orbeb,self.orbsb = geigh(self.Hoepb,self.S) if self.etemp: self.Da,entropya = mkdens_fermi(2*self.nalpha,self.orbea,self.orbsa, self.etemp) self.Db,entropyb = mkdens_fermi(2*self.nbeta,self.orbeb,self.orbsb, self.etemp) self.entropy = 0.5*(entropya+entropyb) else: self.Da = mkdens(self.orbsa,0,self.nalpha) self.Db = mkdens(self.orbsb,0,self.nbeta) self.entropy=0 J = getJ(self.Ints,self.Da+self.Db) Ka = getK(self.Ints,self.Da) Kb = getK(self.Ints,self.Db) self.Fa = self.h + J - Ka self.Fb = self.h + J - Kb self.energy = 0.5*(trace2(self.h+self.Fa,self.Da) + trace2(self.h+self.Fb,self.Db))\ + self.Enuke + self.entropy if self.iter == 1 or self.iter % 10 == 0: logging.debug("%4d %10.5f %10.5f" % (self.iter,self.energy,dot(b,b))) return self.energy
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 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 test_mol(mol,**opts): basis_data = opts.get('basis_data',None) do_python_tests = opts.get('do_python_tests',True) make_hf_driver(mol,basis_data=basis_data) if do_python_tests: bfs = getbasis(mol,basis_data) S= getS(bfs) T = getT(bfs) V = getV(bfs,mol) Ints = get2ints(bfs) nclosed,nopen = mol.get_closedopen() enuke = mol.get_enuke() assert nopen==0 h = T+V orbe,orbs = GHeigenvectors(h,S) print "Eval of h: ", print orbe for i in range(10): D = mkdens(orbs,0,nclosed) J = getJ(Ints,D) K = getK(Ints,D) orbe,orbs = GHeigenvectors(h+2*J-K,S) eone = TraceProperty(D,h) ej = TraceProperty(D,J) ek = TraceProperty(D,K) energy = enuke+2*eone+2*ej-ek print i,energy,enuke,eone,ej,ek return
def test_mol(mol, **opts): basis_data = opts.get('basis_data', None) do_python_tests = opts.get('do_python_tests', True) make_hf_driver(mol, basis_data=basis_data) if do_python_tests: bfs = getbasis(mol, basis_data) S = getS(bfs) T = getT(bfs) V = getV(bfs, mol) Ints = get2ints(bfs) nclosed, nopen = mol.get_closedopen() enuke = mol.get_enuke() assert nopen == 0 h = T + V orbe, orbs = GHeigenvectors(h, S) print "Eval of h: ", print orbe for i in range(10): D = mkdens(orbs, 0, nclosed) J = getJ(Ints, D) K = getK(Ints, D) orbe, orbs = GHeigenvectors(h + 2 * J - K, S) eone = TraceProperty(D, h) ej = TraceProperty(D, J) ek = TraceProperty(D, K) energy = enuke + 2 * eone + 2 * ej - ek print i, energy, enuke, eone, ej, ek return
def get_os_hams(Ints,Ds): # GVB2P5 did this a little more efficiently; they stored # 2J-K for the core, then J,K for each open shell. Didn't # seem worth it here, so I'm jst storing J,K separately Hs = [] for D in Ds: Hs.append(getJ(Ints,D)) Hs.append(getK(Ints,D)) return Hs
def update(self,**opts): from PyQuante.LA2 import trace2 from PyQuante.Ints import getJ,getK self.amat,entropya = self.solvera.solve(self.Fa) self.bmat,entropyb = self.solverb.solve(self.Fb) Da = self.amat Db = self.bmat D = Da+Db self.entropy = 0.5*(entropya+entropyb) self.J = getJ(self.ERI,D) self.Ej = 0.5*trace2(D,self.J) self.Ka = getK(self.ERI,Da) self.Kb = getK(self.ERI,Db) self.Exc = -0.5*(trace2(Da,self.Ka)+trace2(Db,self.Kb)) self.Eone = trace2(D,self.h) self.Fa = self.h + self.J - self.Ka self.Fb = self.h + self.J - self.Kb self.energy = self.Eone + self.Ej + self.Exc + self.Enuke + self.entropy return
def update(self, **kwargs): from PyQuante.LA2 import trace2 from PyQuante.Ints import getJ, getK self.amat, entropya = self.solvera.solve(self.Fa) self.bmat, entropyb = self.solverb.solve(self.Fb) Da = self.amat Db = self.bmat D = Da + Db self.entropy = 0.5 * (entropya + entropyb) self.J = getJ(self.ERI, D) self.Ej = 0.5 * trace2(D, self.J) self.Ka = getK(self.ERI, Da) self.Kb = getK(self.ERI, Db) self.Exc = -0.5 * (trace2(Da, self.Ka) + trace2(Db, self.Kb)) self.Eone = trace2(D, self.h) self.Fa = self.h + self.J - self.Ka self.Fb = self.h + self.J - self.Kb self.energy = self.Eone + self.Ej + self.Exc + self.Enuke + self.entropy return
def update(self,**opts): from PyQuante.LA2 import trace2 from PyQuante.Ints import getJ,getK if self.DoAveraging and self.dmat is not None: self.F = self.Averager.getF(self.F,self.dmat) self.dmat,self.entropy = self.solver.solve(self.F,**opts) D = self.dmat self.J = getJ(self.ERI,D) self.Ej = 2*trace2(D,self.J) self.K = getK(self.ERI,D) self.Exc = -trace2(D,self.K) self.Eone = 2*trace2(D,self.h) self.F = self.h + 2*self.J - self.K self.energy = self.Eone + self.Ej + self.Exc + self.Enuke + self.entropy return
def update(self, **kwargs): from PyQuante.LA2 import trace2 from PyQuante.Ints import getJ, getK if self.DoAveraging and self.dmat is not None: self.F = self.Averager.getF(self.F, self.dmat) self.dmat, self.entropy = self.solver.solve(self.F, **kwargs) D = self.dmat self.J = getJ(self.ERI, D) self.Ej = 2 * trace2(D, self.J) self.K = getK(self.ERI, D) self.Exc = -trace2(D, self.K) self.Eone = 2 * trace2(D, self.h) self.F = self.h + 2 * self.J - self.K self.energy = self.Eone + self.Ej + self.Exc + self.Enuke + self.entropy return
def oep_uhf_an(atoms,orbsa,orbsb,**opts): """oep_hf - Form the optimized effective potential for HF exchange. Implementation of Wu and Yang's Approximate Newton Scheme from J. Theor. Comp. Chem. 2, 627 (2003). oep_uhf(atoms,orbs,**opts) atoms A Molecule object containing a list of the atoms orbs A matrix of guess orbitals Options ------- bfs None The basis functions to use for the wfn pbfs None The basis functions to use for the pot basis_data None The basis data to use to construct bfs integrals None The one- and two-electron integrals to use If not None, S,h,Ints """ maxiter = opts.get('maxiter',100) tol = opts.get('tol',1e-5) ETemp = opts.get('ETemp',False) bfs = opts.get('bfs',None) if not bfs: basis = opts.get('basis',None) bfs = getbasis(atoms,basis) # The basis set for the potential can be set different from # that used for the wave function pbfs = opts.get('pbfs',None) if not pbfs: pbfs = bfs npbf = len(pbfs) integrals = opts.get('integrals',None) if integrals: S,h,Ints = integrals else: S,h,Ints = getints(bfs,atoms) nel = atoms.get_nel() nclosed,nopen = atoms.get_closedopen() nalpha,nbeta = nclosed+nopen,nclosed Enuke = atoms.get_enuke() # Form the OEP using Yang/Wu, PRL 89 143002 (2002) nbf = len(bfs) norb = nbf ba = zeros(npbf,'d') bb = zeros(npbf,'d') # Form and store all of the three-center integrals # we're going to need. # These are <ibf|gbf|jbf> (where 'bf' indicates basis func, # as opposed to MO) # N^3 storage -- obviously you don't want to do this for # very large systems Gij = [] for g in range(npbf): gmat = zeros((nbf,nbf),'d') Gij.append(gmat) gbf = pbfs[g] for i in range(nbf): ibf = bfs[i] for j in range(i+1): jbf = bfs[j] gij = three_center(ibf,gbf,jbf) gmat[i,j] = gij gmat[j,i] = gij # Compute the Fermi-Amaldi potential based on the LDA density. # We're going to form this matrix from the Coulombic matrix that # arises from the input orbitals. D0 and J0 refer to the density # matrix and corresponding Coulomb matrix D0 = mkdens(orbsa,0,nalpha)+mkdens(orbsb,0,nbeta) J0 = getJ(Ints,D0) Vfa = ((nel-1.)/nel)*J0 H0 = h + Vfa eold = 0 for iter in range(maxiter): Hoepa = get_Hoep(ba,H0,Gij) Hoepb = get_Hoep(ba,H0,Gij) orbea,orbsa = geigh(Hoepa,S) orbeb,orbsb = geigh(Hoepb,S) if ETemp: efermia = get_efermi(2*nalpha,orbea,ETemp) occsa = get_fermi_occs(efermia,orbea,ETemp) Da = mkdens_occs(orbsa,occsa) efermib = get_efermi(2*nbeta,orbeb,ETemp) occsb = get_fermi_occs(efermib,orbeb,ETemp) Db = mkdens_occs(orbsb,occsb) entropy = 0.5*(get_entropy(occsa,ETemp)+get_entropy(occsb,ETemp)) else: Da = mkdens(orbsa,0,nalpha) Db = mkdens(orbsb,0,nbeta) J = getJ(Ints,Da) + getJ(Ints,Db) Ka = getK(Ints,Da) Kb = getK(Ints,Db) energy = (trace2(2*h+J-Ka,Da)+trace2(2*h+J-Kb,Db))/2\ +Enuke if ETemp: energy += entropy if abs(energy-eold) < tol: break else: eold = energy logging.debug("OEP AN Opt: %d %f" % (iter,energy)) # Do alpha and beta separately # Alphas dV_ao = J-Ka-Vfa dV = matrixmultiply(orbsa,matrixmultiply(dV_ao,transpose(orbsa))) X = zeros((nbf,nbf),'d') c = zeros(nbf,'d') for k in range(nbf): Gk = matrixmultiply(orbsa,matrixmultiply(Gij[k], transpose(orbsa))) for i in range(nalpha): for a in range(nalpha,norb): c[k] += dV[i,a]*Gk[i,a]/(orbea[i]-orbea[a]) for l in range(nbf): Gl = matrixmultiply(orbsa,matrixmultiply(Gij[l], transpose(orbsa))) for i in range(nalpha): for a in range(nalpha,norb): X[k,l] += Gk[i,a]*Gl[i,a]/(orbea[i]-orbea[a]) # This should actually be a pseudoinverse... ba = solve(X,c) # Betas dV_ao = J-Kb-Vfa dV = matrixmultiply(orbsb,matrixmultiply(dV_ao,transpose(orbsb))) X = zeros((nbf,nbf),'d') c = zeros(nbf,'d') for k in range(nbf): Gk = matrixmultiply(orbsb,matrixmultiply(Gij[k], transpose(orbsb))) for i in range(nbeta): for a in range(nbeta,norb): c[k] += dV[i,a]*Gk[i,a]/(orbeb[i]-orbeb[a]) for l in range(nbf): Gl = matrixmultiply(orbsb,matrixmultiply(Gij[l], transpose(orbsb))) for i in range(nbeta): for a in range(nbeta,norb): X[k,l] += Gk[i,a]*Gl[i,a]/(orbeb[i]-orbeb[a]) # This should actually be a pseudoinverse... bb = solve(X,c) logging.info("Final OEP energy = %f" % energy) return energy,(orbea,orbeb),(orbsa,orbsb)
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
def oep_uhf_an(atoms, orbsa, orbsb, **opts): """oep_hf - Form the optimized effective potential for HF exchange. Implementation of Wu and Yang's Approximate Newton Scheme from J. Theor. Comp. Chem. 2, 627 (2003). oep_uhf(atoms,orbs,**opts) atoms A Molecule object containing a list of the atoms orbs A matrix of guess orbitals Options ------- bfs None The basis functions to use for the wfn pbfs None The basis functions to use for the pot basis_data None The basis data to use to construct bfs integrals None The one- and two-electron integrals to use If not None, S,h,Ints """ maxiter = opts.get('maxiter', 100) tol = opts.get('tol', 1e-5) ETemp = opts.get('ETemp', False) bfs = opts.get('bfs', None) if not bfs: basis = opts.get('basis', None) bfs = getbasis(atoms, basis) # The basis set for the potential can be set different from # that used for the wave function pbfs = opts.get('pbfs', None) if not pbfs: pbfs = bfs npbf = len(pbfs) integrals = opts.get('integrals', None) if integrals: S, h, Ints = integrals else: S, h, Ints = getints(bfs, atoms) nel = atoms.get_nel() nclosed, nopen = atoms.get_closedopen() nalpha, nbeta = nclosed + nopen, nclosed Enuke = atoms.get_enuke() # Form the OEP using Yang/Wu, PRL 89 143002 (2002) nbf = len(bfs) norb = nbf ba = zeros(npbf, 'd') bb = zeros(npbf, 'd') # Form and store all of the three-center integrals # we're going to need. # These are <ibf|gbf|jbf> (where 'bf' indicates basis func, # as opposed to MO) # N^3 storage -- obviously you don't want to do this for # very large systems Gij = [] for g in xrange(npbf): gmat = zeros((nbf, nbf), 'd') Gij.append(gmat) gbf = pbfs[g] for i in xrange(nbf): ibf = bfs[i] for j in xrange(i + 1): jbf = bfs[j] gij = three_center(ibf, gbf, jbf) gmat[i, j] = gij gmat[j, i] = gij # Compute the Fermi-Amaldi potential based on the LDA density. # We're going to form this matrix from the Coulombic matrix that # arises from the input orbitals. D0 and J0 refer to the density # matrix and corresponding Coulomb matrix D0 = mkdens(orbsa, 0, nalpha) + mkdens(orbsb, 0, nbeta) J0 = getJ(Ints, D0) Vfa = ((nel - 1.) / nel) * J0 H0 = h + Vfa eold = 0 for iter in xrange(maxiter): Hoepa = get_Hoep(ba, H0, Gij) Hoepb = get_Hoep(ba, H0, Gij) orbea, orbsa = geigh(Hoepa, S) orbeb, orbsb = geigh(Hoepb, S) if ETemp: efermia = get_efermi(2 * nalpha, orbea, ETemp) occsa = get_fermi_occs(efermia, orbea, ETemp) Da = mkdens_occs(orbsa, occsa) efermib = get_efermi(2 * nbeta, orbeb, ETemp) occsb = get_fermi_occs(efermib, orbeb, ETemp) Db = mkdens_occs(orbsb, occsb) entropy = 0.5 * (get_entropy(occsa, ETemp) + get_entropy(occsb, ETemp)) else: Da = mkdens(orbsa, 0, nalpha) Db = mkdens(orbsb, 0, nbeta) J = getJ(Ints, Da) + getJ(Ints, Db) Ka = getK(Ints, Da) Kb = getK(Ints, Db) energy = (trace2(2*h+J-Ka,Da)+trace2(2*h+J-Kb,Db))/2\ +Enuke if ETemp: energy += entropy if abs(energy - eold) < tol: break else: eold = energy logging.debug("OEP AN Opt: %d %f" % (iter, energy)) # Do alpha and beta separately # Alphas dV_ao = J - Ka - Vfa dV = matrixmultiply(orbsa, matrixmultiply(dV_ao, transpose(orbsa))) X = zeros((nbf, nbf), 'd') c = zeros(nbf, 'd') for k in xrange(nbf): Gk = matrixmultiply(orbsa, matrixmultiply(Gij[k], transpose(orbsa))) for i in xrange(nalpha): for a in xrange(nalpha, norb): c[k] += dV[i, a] * Gk[i, a] / (orbea[i] - orbea[a]) for l in xrange(nbf): Gl = matrixmultiply(orbsa, matrixmultiply(Gij[l], transpose(orbsa))) for i in xrange(nalpha): for a in xrange(nalpha, norb): X[k, l] += Gk[i, a] * Gl[i, a] / (orbea[i] - orbea[a]) # This should actually be a pseudoinverse... ba = solve(X, c) # Betas dV_ao = J - Kb - Vfa dV = matrixmultiply(orbsb, matrixmultiply(dV_ao, transpose(orbsb))) X = zeros((nbf, nbf), 'd') c = zeros(nbf, 'd') for k in xrange(nbf): Gk = matrixmultiply(orbsb, matrixmultiply(Gij[k], transpose(orbsb))) for i in xrange(nbeta): for a in xrange(nbeta, norb): c[k] += dV[i, a] * Gk[i, a] / (orbeb[i] - orbeb[a]) for l in xrange(nbf): Gl = matrixmultiply(orbsb, matrixmultiply(Gij[l], transpose(orbsb))) for i in xrange(nbeta): for a in xrange(nbeta, norb): X[k, l] += Gk[i, a] * Gl[i, a] / (orbeb[i] - orbeb[a]) # This should actually be a pseudoinverse... bb = solve(X, c) logger.info("Final OEP energy = %f" % energy) return energy, (orbea, orbeb), (orbsa, orbsb)
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