def testOrthog(self): from PyQuante.LA2 import CanOrth, SymOrth, CholOrth, simx from PyQuante.NumWrap import eigh solver = SCF(h2, method="HF") h, S = solver.h, solver.S X1 = CanOrth(S) X2 = SymOrth(S) X3 = CholOrth(S) h1 = simx(h, X1) ha = simx(h, X2) h3 = simx(h, X3) e1, v1 = eigh(h1) e2, v2 = eigh(ha) e3, v3 = eigh(h3) self.assertAlmostEqual(e1[0], e2[0], 6) self.assertAlmostEqual(e1[0], e3[0], 6)
def inertial(self): "Transform to inertial coordinates" from PyQuante.NumWrap import zeros, eigh rcom = self.com() print "Translating to COM: ", rcom self.translate(-rcom) I = zeros((3, 3), 'd') for atom in self: m = atom.mass() x, y, z = atom.pos() x2, y2, z2 = x * x, y * y, z * z I[0, 0] += m * (y2 + z2) I[1, 1] += m * (x2 + z2) I[2, 2] += m * (x2 + y2) I[0, 1] -= m * x * y I[1, 0] = I[0, 1] I[0, 2] -= m * x * z I[2, 0] = I[0, 2] I[1, 2] -= m * y * z I[2, 1] = I[1, 2] E, U = eigh(I) print "Moments of inertial ", E self.urotate(U) print "New coordinates: " print self return
def lanczos_minmax(F, S=None, **kwargs): "Estimate the min/max evals of F using a few iters of Lanczos" doS = S is not None niter = kwargs.get('niter', settings.DMPLanczosMinmaxIters) N = F.shape[0] niter = min(N, niter) x = zeros(N, 'd') x[0] = 1 q = x avals = [] bvals = [] if doS: r = matrixmultiply(S, q) else: r = q beta = sqrt(matrixmultiply(q, r)) wold = zeros(N, 'd') for i in xrange(niter): w = r / beta v = q / beta r = matrixmultiply(F, v) r = r - wold * beta alpha = matrixmultiply(v, r) avals.append(alpha) r = r - w * alpha if doS: q = solve(S, r) else: q = r beta = sqrt(matrixmultiply(q, r)) bvals.append(beta) wold = w E, V = eigh(tridiagmat(avals, bvals)) return min(E), max(E)
def testOrthog(self): from PyQuante.LA2 import CanOrth, SymOrth, CholOrth, simx from PyQuante.NumWrap import eigh solver = SCF(h2,method="HF") h,S = solver.h, solver.S X1 = CanOrth(S) X2 = SymOrth(S) X3 = CholOrth(S) h1 = simx(h,X1) ha = simx(h,X2) h3 = simx(h,X3) e1,v1 = eigh(h1) e2,v2 = eigh(ha) e3,v3 = eigh(h3) self.assertAlmostEqual(e1[0],e2[0],6) self.assertAlmostEqual(e1[0],e3[0],6)
def inertial(self): "Transform to inertial coordinates" from PyQuante.NumWrap import zeros,eigh rcom = self.com() print "Translating to COM: ",rcom self.translate(-rcom) I = zeros((3,3),'d') for atom in self: m = atom.mass() x,y,z = atom.pos() x2,y2,z2 = x*x,y*y,z*z I[0,0] += m*(y2+z2) I[1,1] += m*(x2+z2) I[2,2] += m*(x2+y2) I[0,1] -= m*x*y I[1,0] = I[0,1] I[0,2] -= m*x*z I[2,0] = I[0,2] I[1,2] -= m*y*z I[2,1] = I[1,2] E,U = eigh(I) print "Moments of inertial ",E self.urotate(U) print "New coordinates: " print self return
def lanczos_minmax(F,S=None,**kwargs): "Estimate the min/max evals of F using a few iters of Lanczos" doS = S is not None niter = kwargs.get('niter',8) N = F.shape[0] niter = min(N,niter) x = zeros(N,'d') x[0] = 1 q = x avals = [] bvals = [] if doS: r = matrixmultiply(S,q) else: r = q beta = sqrt(matrixmultiply(q,r)) wold = zeros(N,'d') for i in xrange(niter): w = r/beta v = q/beta r = matrixmultiply(F,v) r = r - wold*beta alpha = matrixmultiply(v,r) avals.append(alpha) r = r-w*alpha if doS: q = solve(S,r) else: q = r beta = sqrt(matrixmultiply(q,r)) bvals.append(beta) wold = w E,V = eigh(tridiagmat(avals,bvals)) return min(E),max(E)
def geigh(H,A,**opts): """\ Generalized eigenproblem using a symmetric matrix H. """ X = SymOrthCutoff(A) val,vec = eigh(simx(H,X)) vec = matrixmultiply(X,vec) return val,vec
def geigh(H, A, **opts): """\ Generalized eigenproblem using a symmetric matrix H. """ X = SymOrthCutoff(A) val, vec = eigh(simx(H, X)) vec = matrixmultiply(X, vec) return val, vec
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 SymOrthCutoff(S, scut=1e-5): """Symmetric orthogonalization of the real symmetric matrix S. This is given by Ut(1/sqrt(lambda))U, where lambda,U are the eigenvalues/vectors. Only eigenvectors with eigenvalues greater that a cutoff are kept. This approximation is useful in cases where the basis set has linear dependencies. """ val, vec = eigh(S) n = vec.shape[0] shalf = identity(n, 'd') for i in range(n): if val[i] > scut: shalf[i, i] /= sqrt(val[i]) else: shalf[i, i] = 0. X = simx(shalf, vec, 'T') return X
def SymOrthCutoff(S,scut=1e-5): """Symmetric orthogonalization of the real symmetric matrix S. This is given by Ut(1/sqrt(lambda))U, where lambda,U are the eigenvalues/vectors. Only eigenvectors with eigenvalues greater that a cutoff are kept. This approximation is useful in cases where the basis set has linear dependencies. """ val,vec = eigh(S) n = vec.shape[0] shalf = identity(n,'d') for i in range(n): if val[i] > scut: shalf[i,i] /= sqrt(val[i]) else: shalf[i,i] = 0. X = simx(shalf,vec,'T') return X
def ocbse(orbs,h,Hs,f,a,b,noccsh): # Need to write this so that we don't need the orbs 3 times! nsh = len(noccsh) nbf = norb = h.shape[0] orbe = zeros(norb,'d') for ish in xrange(nsh): orbs_in_shell = get_orbs_in_shell(ish,noccsh,norb) F = get_os_fock(ish,nsh,f,a,b,h,Hs) # form the orbital space of all of the orbs in ish plus the virts T = orbs.take(orbs_in_shell,1) #print "take worked? ",(T==get_orbs(orbs,orbs_in_shell)).all() # Transform to MO space Fmo = ao2mo(F,T) mo_orbe,mo_orbs = eigh(Fmo) T = matrixmultiply(T,mo_orbs) # Insert orbital energies into the right place update_orbe(orbs_in_shell,orbe,mo_orbe) update_orbs(orbs_in_shell,orbs,T) return orbe,orbs
def davidson(A, nroots, **kwargs): etol = kwargs.get('etol', settings.DavidsonEvecTolerance ) # tolerance on the eigenval convergence ntol = kwargs.get('ntol', settings.DavidsonNormTolerance ) # tolerance on the vector norms for addn n, m = A.shape ninit = max(nroots, 2) B = zeros((n, ninit), 'd') for i in xrange(ninit): B[i, i] = 1. nc = 0 # number of converged roots eigold = 1e10 for iter in xrange(n): if nc >= nroots: break D = matrixmultiply(A, B) S = matrixmultiply(transpose(B), D) m = len(S) eval, evec = eigh(S) bnew = zeros(n, 'd') for i in xrange(m): bnew += evec[i, nc] * (D[:, i] - eval[nc] * B[:, i]) for i in xrange(n): denom = max(eval[nc] - A[i, i], 1e-8) # Maximum amplification factor bnew[i] /= denom norm = orthog(bnew, B) bnew = bnew / norm if abs(eval[nc] - eigold) < etol: nc += 1 eigold = eval[nc] if norm > ntol: B = appendColumn(B, bnew) E = eval[:nroots] nv = len(evec) V = matrixmultiply(B[:, :nv], evec) return E, V
def davidson(A,nroots,**kwargs): etol = kwargs.get('etol',settings.DavidsonEvecTolerance) # tolerance on the eigenval convergence ntol = kwargs.get('ntol',settings.DavidsonNormTolerance) # tolerance on the vector norms for addn n,m = A.shape ninit = max(nroots,2) B = zeros((n,ninit),'d') for i in xrange(ninit): B[i,i] = 1. nc = 0 # number of converged roots eigold = 1e10 for iter in xrange(n): if nc >= nroots: break D = matrixmultiply(A,B) S = matrixmultiply(transpose(B),D) m = len(S) eval,evec = eigh(S) bnew = zeros(n,'d') for i in xrange(m): bnew += evec[i,nc]*(D[:,i] - eval[nc]*B[:,i]) for i in xrange(n): denom = max(eval[nc]-A[i,i],1e-8) # Maximum amplification factor bnew[i] /= denom norm = orthog(bnew,B) bnew = bnew / norm if abs(eval[nc]-eigold) < etol: nc += 1 eigold = eval[nc] if norm > ntol: B = appendColumn(B,bnew) E = eval[:nroots] nv = len(evec) V = matrixmultiply(B[:,:nv],evec) return E,V
#Form Hcore Hcore = KE + Vext #calculate two electron integrals elecRepulsion = Ints.get2ints(basisSet) #Section 3############################ #Calculate Transformation Matrix X from Overlap matrix X = linalg.SymOrth(S) #Section 4############################ #guess density matrix from Core Hamiltonian #diagnolize Hamiltonian and transform hamiltonian to get guess orbitals eVal, eVec = eigh(linalg.simx(Hcore, X)) #transform orbitals from AO to MO basis orbitals = matrixmultiply(Hcore, X) #guess Density from guess orbitals and number of closed electron shells D = HF.mkdens(orbitals, 0, molecule.get_closedopen()[0]) #Start of SCF Procedures############################ #init variables for SCF cycle = 0 energy = [float("-inf")] while (cycle < maxCycle): #while max. number of cycles not reached #continues with SCF iterations
def solve_fock(self): from PyQuante.NumWrap import eigh from PyQuante.LA2 import mkdens self.orbea,self.orbsa = eigh(self.Fa) self.orbeb,self.orbsb = eigh(self.Fb)
def solve_fock(self): from PyQuante.NumWrap import eigh self.orbe,self.orbs = eigh(self.F)
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 solve_fock(self): from PyQuante.NumWrap import eigh self.orbe, self.orbs = eigh(self.F)
def solve_fock(self): from PyQuante.NumWrap import eigh from PyQuante.LA2 import mkdens self.orbea, self.orbsa = eigh(self.Fa) self.orbeb, self.orbsb = eigh(self.Fb)