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 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 update(self): D2 = matrixmultiply(self.D,self.D) D3 = matrixmultiply(self.D,D2) cn = trace(D2-D3)/trace(self.D-D2) if cn < 0.5: self.D = ((1.0-2.0*cn)*self.D+(1.0+cn)*D2-D3)/(1.0-cn) else: self.D = ((1+cn)*D2-D3)/cn return
def update(self): D2 = matrixmultiply(self.D, self.D) D3 = matrixmultiply(self.D, D2) cn = trace(D2 - D3) / trace(self.D - D2) if cn < 0.5: self.D = ((1.0 - 2.0 * cn) * self.D + (1.0 + cn) * D2 - D3) / (1.0 - cn) else: self.D = ((1 + cn) * D2 - D3) / cn return
def get_exx_gradient(b, nbf, nel, nocc, ETemp, Enuke, S, h, Ints, H0, Gij, **opts): """Computes the gradient for the OEP/HF functional. return_flag 0 Just return gradient 1 Return energy,gradient 2 Return energy,gradient,orbe,orbs """ # Dump the gradient every 10 steps so we can restart... global gradcall gradcall += 1 #if gradcall % 5 == 0: logging.debug("B vector:\n%s" % b) # Form the new potential and the new orbitals energy, orbe, orbs, F = get_exx_energy(b, nbf, nel, nocc, ETemp, Enuke, S, h, Ints, H0, Gij, return_flag=2) Fmo = matrixmultiply(transpose(orbs), matrixmultiply(F, orbs)) norb = nbf bp = zeros(nbf, 'd') # dE/db for g in xrange(nbf): # Transform Gij[g] to MOs. This is done over the whole # space rather than just the parts we need. I can speed # this up later by only forming the i,a elements required Gmo = matrixmultiply(transpose(orbs), matrixmultiply(Gij[g], orbs)) # Now sum the appropriate terms to get the b gradient for i in xrange(nocc): for a in xrange(nocc, norb): bp[g] = bp[g] + Fmo[i, a] * Gmo[i, a] / (orbe[i] - orbe[a]) #logging.debug("EXX Grad: %10.5f" % (sqrt(dot(bp,bp)))) return_flag = opts.get('return_flag', 0) if return_flag == 1: return energy, bp elif return_flag == 2: return energy, bp, orbe, orbs return bp
def getF(self, F, D): n, m = F.shape err = matrixmultiply(F,matrixmultiply(D,self.S)) -\ matrixmultiply(self.S,matrixmultiply(D,F)) err = ravel(err) maxerr = max(abs(err)) self.maxerr = maxerr if maxerr < self.errcutoff and not self.started: if VERBOSE: print "Starting DIIS: Max Err = ", maxerr self.started = 1 if not self.started: # Do simple averaging until DIIS starts if self.Fold != None: Freturn = 0.5 * F + 0.5 * self.Fold self.Fold = F else: self.Fold = F Freturn = F return Freturn self.Fs.append(F) self.Errs.append(err) nit = len(self.Errs) a = zeros((nit + 1, nit + 1), 'd') b = zeros(nit + 1, 'd') for i in xrange(nit): for j in xrange(nit): a[i, j] = dot(self.Errs[i], self.Errs[j]) for i in xrange(nit): a[nit, i] = a[i, nit] = -1.0 b[i] = 0 #mtx2file(a,'A%d.dat' % nit) a[nit, nit] = 0 b[nit] = -1.0 # The try loop makes this a bit more stable. # Thanks to John Kendrick! try: c = solve(a, b) except: self.Fold = F return F F = zeros((n, m), 'd') for i in xrange(nit): F += c[i] * self.Fs[i] return F
def getF(self, F, D): n, m = F.shape err = matrixmultiply(F, matrixmultiply(D, self.S)) - matrixmultiply(self.S, matrixmultiply(D, F)) err = ravel(err) maxerr = max(abs(err)) self.maxerr = maxerr if maxerr < self.errcutoff and not self.started: if VERBOSE: print "Starting DIIS: Max Err = ", maxerr self.started = 1 if not self.started: # Do simple averaging until DIIS starts if self.Fold != None: Freturn = 0.5 * F + 0.5 * self.Fold self.Fold = F else: self.Fold = F Freturn = F return Freturn self.Fs.append(F) self.Errs.append(err) nit = len(self.Errs) a = zeros((nit + 1, nit + 1), "d") b = zeros(nit + 1, "d") for i in range(nit): for j in range(nit): a[i, j] = dot(self.Errs[i], self.Errs[j]) for i in range(nit): a[nit, i] = a[i, nit] = -1.0 b[i] = 0 # mtx2file(a,'A%d.dat' % nit) a[nit, nit] = 0 b[nit] = -1.0 # The try loop makes this a bit more stable. # Thanks to John Kendrick! try: c = solve(a, b) except: self.Fold = F return F F = zeros((n, m), "d") for i in range(nit): F += c[i] * self.Fs[i] return F
def update(self): D2 = matrixmultiply(self.D, self.D) Df = matrixmultiply(D2, 4 * self.D - 3 * D2) trf = trace(Df) Dp = self.I - self.D Dp2 = matrixmultiply(Dp, Dp) Dg = matrixmultiply(D2, Dp2) trg = trace(Dg) gamma = (self.Ne - trf) / trg if gamma > 2: self.D = 2 * self.D - D2 elif gamma < 0: self.D = D2 else: self.D = Df - gamma * Dg return
def update(self): D2 = matrixmultiply(self.DS, self.D) if self.Ne_curr < self.Ne: self.D = 2 * self.D - D2 else: self.D = D2 return
def update(self): D2 = matrixmultiply(self.D,self.D) Df = matrixmultiply(D2,4*self.D-3*D2) trf = trace(Df) Dp = self.I-self.D Dp2 = matrixmultiply(Dp,Dp) Dg = matrixmultiply(D2,Dp2) trg = trace(Dg) gamma = (self.Ne-trf)/trg if gamma > 2: self.D = 2*self.D-D2 elif gamma < 0: self.D = D2 else: self.D = Df-gamma*Dg return
def update(self): D2 = matrixmultiply(self.DS,self.D) if self.Ne_curr < self.Ne: self.D = 2*self.D-D2 else: self.D = D2 return
def getF(self, F, D): n, m = F.shape err = matrixmultiply(F,matrixmultiply(D,self.S)) -\ matrixmultiply(self.S,matrixmultiply(D,F)) err = ravel(err) maxerr = max(abs(err)) if maxerr < self.errcutoff and not self.started: if VERBOSE: print "Starting DIIS: Max Err = ", maxerr self.started = 1 if not self.started: # Do simple averaging until DIIS starts if self.Fold: Freturn = 0.5 * F + 0.5 * self.Fold else: Freturn = F self.Fold = F return Freturn elif not self.errold: Freturn = 0.5 * F + 0.5 * self.Fold self.errold = err return Freturn a = zeros((3, 3), 'd') b = zeros(3, 'd') a[0, 0] = dot(self.errold, self.errold) a[1, 0] = dot(self.errold, err) a[0, 1] = a[1, 0] a[1, 1] = dot(err, err) a[:, 2] = -1 a[2, :] = -1 a[2, 2] = 0 b[2] = -1 c = solve(a, b) # Handle a few special cases: alpha = c[1] print alpha, c #if alpha < 0: alpha = 0 #if alpha > 1: alpha = 1 F = (1 - alpha) * self.Fold + alpha * F self.errold = err self.Fold = F return F
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 getF(self, F, D): n, m = F.shape err = matrixmultiply(F, matrixmultiply(D, self.S)) - matrixmultiply(self.S, matrixmultiply(D, F)) err = ravel(err) maxerr = max(abs(err)) if maxerr < self.errcutoff and not self.started: if VERBOSE: print "Starting DIIS: Max Err = ", maxerr self.started = 1 if not self.started: # Do simple averaging until DIIS starts if self.Fold: Freturn = 0.5 * F + 0.5 * self.Fold else: Freturn = F self.Fold = F return Freturn elif not self.errold: Freturn = 0.5 * F + 0.5 * self.Fold self.errold = err return Freturn a = zeros((3, 3), "d") b = zeros(3, "d") a[0, 0] = dot(self.errold, self.errold) a[1, 0] = dot(self.errold, err) a[0, 1] = a[1, 0] a[1, 1] = dot(err, err) a[:, 2] = -1 a[2, :] = -1 a[2, 2] = 0 b[2] = -1 c = solve(a, b) # Handle a few special cases: alpha = c[1] print alpha, c # if alpha < 0: alpha = 0 # if alpha > 1: alpha = 1 F = (1 - alpha) * self.Fold + alpha * F self.errold = err self.Fold = F return F
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 rotion(orbs,h,Hs,f,a,b,noccsh): nsh = len(noccsh) nocc = sum(noccsh) if nsh == 1: return orbs # No effect for closed shell systems rot = get_rot(h,Hs,f,a,b,noccsh) print "Rotation matrix:\n",rot erot = expmat(rot) print "Exp rotation matrix:\n",erot T = matrixmultiply(orbs[:,:nocc],erot) orbs[:,:nocc] = T return 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 update(self): Ne_curr = trace(self.D) D2 = matrixmultiply(self.D, self.D) Ne2 = trace(D2) self.Ne_curr = Ne_curr # Anders claims this works better; I didn't see a difference #if abs(2*Ne_curr-Ne2-self.Ne) < abs(Ne2-self.Ne): if Ne_curr < self.Ne: self.D = 2 * self.D - D2 else: self.D = D2 return
def update(self): Ne_curr = trace(self.D) D2 = matrixmultiply(self.D,self.D) Ne2 = trace(D2) self.Ne_curr = Ne_curr # Anders claims this works better; I didn't see a difference #if abs(2*Ne_curr-Ne2-self.Ne) < abs(Ne2-self.Ne): if Ne_curr < self.Ne: self.D = 2*self.D-D2 else: self.D = D2 return
def get_exx_gradient(b,nbf,nel,nocc,ETemp,Enuke,S,h,Ints,H0,Gij,**opts): """Computes the gradient for the OEP/HF functional. return_flag 0 Just return gradient 1 Return energy,gradient 2 Return energy,gradient,orbe,orbs """ # Dump the gradient every 10 steps so we can restart... global gradcall gradcall += 1 #if gradcall % 5 == 0: logging.debug("B vector:\n%s" % b) # Form the new potential and the new orbitals energy,orbe,orbs,F = get_exx_energy(b,nbf,nel,nocc,ETemp,Enuke, S,h,Ints,H0,Gij,return_flag=2) Fmo = matrixmultiply(transpose(orbs),matrixmultiply(F,orbs)) norb = nbf bp = zeros(nbf,'d') # dE/db for g in range(nbf): # Transform Gij[g] to MOs. This is done over the whole # space rather than just the parts we need. I can speed # this up later by only forming the i,a elements required Gmo = matrixmultiply(transpose(orbs),matrixmultiply(Gij[g],orbs)) # Now sum the appropriate terms to get the b gradient for i in range(nocc): for a in range(nocc,norb): bp[g] = bp[g] + Fmo[i,a]*Gmo[i,a]/(orbe[i]-orbe[a]) #logging.debug("EXX Grad: %10.5f" % (sqrt(dot(bp,bp)))) return_flag = opts.get('return_flag',0) if return_flag == 1: return energy,bp elif return_flag == 2: return energy,bp,orbe,orbs return bp
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 expmat(A,**kwargs): nmax = kwargs.get('nmax',12) cut = kwargs.get('cut',1e-8) E = identity(A.shape[0],'d') D = E for i in xrange(1,nmax): D = matrixmultiply(D,A)/i E += D maxel = D.max() if abs(maxel) < cut: break else: print "Warning: expmat unconverged after %d iters: %g" % (nmax,maxel) return E
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 solve(self, H, **kwargs): from PyQuante.LA2 import mkdens_spinavg, simx, geigh from PyQuante.NumWrap import matrixmultiply, eigh if self.first_iteration: self.first_iteration = False self.orbe, self.orbs = geigh(H, self.S) else: Ht = simx(H, self.orbs) if self.pass_nroots: self.orbe, orbs = self.solver(Ht, self.nroots) else: self.orbe, orbs = self.solver(Ht) self.orbs = matrixmultiply(self.orbs, orbs) self.D = mkdens_spinavg(self.orbs, self.nclosed, self.nopen) self.entropy = 0 return self.D, self.entropy
def solve(self,H,**opts): from PyQuante.LA2 import mkdens_spinavg,simx,geigh from PyQuante.NumWrap import matrixmultiply,eigh if self.first_iteration: self.first_iteration = False self.orbe,self.orbs = geigh(H,self.S) else: Ht = simx(H,self.orbs) if self.pass_nroots: self.orbe,orbs = self.solver(Ht,self.nroots) else: self.orbe,orbs = self.solver(Ht) self.orbs = matrixmultiply(self.orbs,orbs) self.D = mkdens_spinavg(self.orbs,self.nclosed,self.nopen) self.entropy = 0 return self.D,self.entropy
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 converged(self): self.DS = matrixmultiply(self.D, self.S) self.Ne_curr = trace(self.DS) return abs(self.Ne_curr - self.Ne) < self.tol
def mo2ao(M,C,S): SC = matrixmultiply(S,C) return simx(M,SC,'t')
def update(self): D2 = matrixmultiply(self.D, self.D) self.D = 3 * D2 - 2 * matrixmultiply(self.D, D2) return
def update(self): D2 = matrixmultiply(self.D,self.D) self.D = 3*D2-2*matrixmultiply(self.D,D2) return
def oep_hf_an(atoms, orbs, **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_hf(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) 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() nocc, nopen = atoms.get_closedopen() Enuke = atoms.get_enuke() # Form the OEP using Yang/Wu, PRL 89 143002 (2002) nbf = len(bfs) norb = nbf bp = zeros(nbf, 'd') bvec = opts.get('bvec', None) if bvec: assert len(bvec) == npbf b = array(bvec) else: b = 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(orbs, 0, nocc) J0 = getJ(Ints, D0) Vfa = (2 * (nel - 1.) / nel) * J0 H0 = h + Vfa b = zeros(nbf, 'd') eold = 0 for iter in xrange(maxiter): Hoep = get_Hoep(b, H0, Gij) orbe, orbs = geigh(Hoep, S) D = mkdens(orbs, 0, nocc) Vhf = get2JmK(Ints, D) energy = trace2(2 * h + Vhf, D) + Enuke if abs(energy - eold) < tol: break else: eold = energy logging.debug("OEP AN Opt: %d %f" % (iter, energy)) dV_ao = Vhf - Vfa dV = matrixmultiply(transpose(orbs), matrixmultiply(dV_ao, orbs)) X = zeros((nbf, nbf), 'd') c = zeros(nbf, 'd') Gkt = zeros((nbf, nbf), 'd') for k in xrange(nbf): # This didn't work; in fact, it made things worse: Gk = matrixmultiply(transpose(orbs), matrixmultiply(Gij[k], orbs)) for i in xrange(nocc): for a in xrange(nocc, norb): c[k] += dV[i, a] * Gk[i, a] / (orbe[i] - orbe[a]) for l in xrange(nbf): Gl = matrixmultiply(transpose(orbs), matrixmultiply(Gij[l], orbs)) for i in xrange(nocc): for a in xrange(nocc, norb): X[k, l] += Gk[i, a] * Gl[i, a] / (orbe[i] - orbe[a]) # This should actually be a pseudoinverse... b = solve(X, c) logger.info("Final OEP energy = %f" % energy) return energy, orbe, orbs
def H2O_Molecule(tst,info,auX,auZ): H2O = Molecule('H2O', [('O', ( 0.0, 0.0, 0.0)), ('H', ( auX, 0.0, auZ)), ('H', (-auX, 0.0, auZ))], units='Bohr') # Get a better energy estimate if dft: print "# info=%s A.U.=(%g,%g) " % (info,auX,auZ) edft,orbe2,orbs2 = dft(H2O,functional='SVWN') bfs= getbasis(H2O,basis_data=basis_data) #S is overlap of 2 basis funcs #h is (kinetic+nucl) 1 body term #ints is 2 body terms S,h,ints=getints(bfs,H2O) #enhf is the Hartee-Fock energy #orbe is the orbital energies #orbs is the orbital overlaps enhf,orbe,orbs=rhf(H2O,integrals=(S,h,ints)) enuke = Molecule.get_enuke(H2O) # print "orbe=%d" % len(orbe) temp = matrixmultiply(h,orbs) hmol = matrixmultiply(transpose(orbs),temp) MOInts = TransformInts(ints,orbs) if single: print "h = \n",h print "S = \n",S print "ints = \n",ints print "orbe = \n",orbe print "orbs = \n",orbs print "" print "Index 0: 1 or 2 in the paper, Index 1: 3 or 4 in the paper (for pqrs)" print "" print "hmol = \n",hmol print "MOInts:" print "I,J,K,L = PQRS order: Cre1,Cre2,Ann1,Ann2" if 1: print "tst=%d info=%s nuc=%.9f Ehf=%.9f" % (tst,info,enuke,enhf), cntOrbs = 0 maxOrb = 0 npts = len(hmol[:]) for i in xrange(npts): for j in range(i,npts): if abs(hmol[i,j]) > 1.0e-7: print "%d,%d=%.9f" % (i,j,hmol[i,j]), cntOrbs += 1 if i > maxOrb: maxOrb = i if j > maxOrb: maxOrb = j nbf,nmo = orbs.shape mos = range(nmo) for i in mos: for j in xrange(i+1): ij = i*(i+1)/2+j for k in mos: for l in xrange(k+1): kl = k*(k+1)/2+l if ij >= kl: ijkl = ijkl2intindex(i,j,k,l) if abs(MOInts[ijkl]) > 1.0e-7: print "%d,%d,%d,%d=%.9f" % (l,i,j,k,MOInts[ijkl]), cntOrbs += 1 if i > maxOrb: maxOrb = i if j > maxOrb: maxOrb = j print "" return (maxOrb,cntOrbs)
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 converged(self): self.DS = matrixmultiply(self.D,self.S) self.Ne_curr = trace(self.DS) return abs(self.Ne_curr - self.Ne) < self.tol
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_hf_an(atoms,orbs,**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_hf(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) 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() nocc,nopen = atoms.get_closedopen() Enuke = atoms.get_enuke() # Form the OEP using Yang/Wu, PRL 89 143002 (2002) nbf = len(bfs) norb = nbf bp = zeros(nbf,'d') bvec = opts.get('bvec',None) if bvec: assert len(bvec) == npbf b = array(bvec) else: b = 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(orbs,0,nocc) J0 = getJ(Ints,D0) Vfa = (2*(nel-1.)/nel)*J0 H0 = h + Vfa b = zeros(nbf,'d') eold = 0 for iter in range(maxiter): Hoep = get_Hoep(b,H0,Gij) orbe,orbs = geigh(Hoep,S) D = mkdens(orbs,0,nocc) Vhf = get2JmK(Ints,D) energy = trace2(2*h+Vhf,D)+Enuke if abs(energy-eold) < tol: break else: eold = energy logging.debug("OEP AN Opt: %d %f" % (iter,energy)) dV_ao = Vhf-Vfa dV = matrixmultiply(transpose(orbs),matrixmultiply(dV_ao,orbs)) X = zeros((nbf,nbf),'d') c = zeros(nbf,'d') Gkt = zeros((nbf,nbf),'d') for k in range(nbf): # This didn't work; in fact, it made things worse: Gk = matrixmultiply(transpose(orbs),matrixmultiply(Gij[k],orbs)) for i in range(nocc): for a in range(nocc,norb): c[k] += dV[i,a]*Gk[i,a]/(orbe[i]-orbe[a]) for l in range(nbf): Gl = matrixmultiply(transpose(orbs),matrixmultiply(Gij[l],orbs)) for i in range(nocc): for a in range(nocc,norb): X[k,l] += Gk[i,a]*Gl[i,a]/(orbe[i]-orbe[a]) # This should actually be a pseudoinverse... b = solve(X,c) logging.info("Final OEP energy = %f" % energy) return energy,orbe,orbs
def urotate(self,U): "Rotate molecule by the unitary matrix U" from PyQuante.NumWrap import matrixmultiply #self.r = matrixmultiply(self.r,U) self.r = matrixmultiply(U,self.r) return
def urotate(self, U): "Rotate molecule by the unitary matrix U" from PyQuante.NumWrap import matrixmultiply #self.r = matrixmultiply(self.r,U) self.r = matrixmultiply(U, self.r) return
def H2O_Molecule(tst, info, auX, auZ): H2O = Molecule('H2O', [('O', (0.0, 0.0, 0.0)), ('H', (auX, 0.0, auZ)), ('H', (-auX, 0.0, auZ))], units='Bohr') # Get a better energy estimate if dft: print "# info=%s A.U.=(%g,%g) " % (info, auX, auZ) edft, orbe2, orbs2 = dft(H2O, functional='SVWN') bfs = getbasis(H2O, basis_data=basis_data) #S is overlap of 2 basis funcs #h is (kinetic+nucl) 1 body term #ints is 2 body terms S, h, ints = getints(bfs, H2O) #enhf is the Hartee-Fock energy #orbe is the orbital energies #orbs is the orbital overlaps enhf, orbe, orbs = rhf(H2O, integrals=(S, h, ints)) enuke = Molecule.get_enuke(H2O) # print "orbe=%d" % len(orbe) temp = matrixmultiply(h, orbs) hmol = matrixmultiply(transpose(orbs), temp) MOInts = TransformInts(ints, orbs) if single: print "h = \n", h print "S = \n", S print "ints = \n", ints print "orbe = \n", orbe print "orbs = \n", orbs print "" print "Index 0: 1 or 2 in the paper, Index 1: 3 or 4 in the paper (for pqrs)" print "" print "hmol = \n", hmol print "MOInts:" print "I,J,K,L = PQRS order: Cre1,Cre2,Ann1,Ann2" if 1: print "tst=%d info=%s nuc=%.9f Ehf=%.9f" % (tst, info, enuke, enhf), cntOrbs = 0 maxOrb = 0 npts = len(hmol[:]) for i in xrange(npts): for j in range(i, npts): if abs(hmol[i, j]) > 1.0e-7: print "%d,%d=%.9f" % (i, j, hmol[i, j]), cntOrbs += 1 if i > maxOrb: maxOrb = i if j > maxOrb: maxOrb = j nbf, nmo = orbs.shape mos = range(nmo) for i in mos: for j in xrange(i + 1): ij = i * (i + 1) / 2 + j for k in mos: for l in xrange(k + 1): kl = k * (k + 1) / 2 + l if ij >= kl: ijkl = ijkl2intindex(i, j, k, l) if abs(MOInts[ijkl]) > 1.0e-7: print "%d,%d,%d,%d=%.9f" % (l, i, j, k, MOInts[ijkl]), cntOrbs += 1 if i > maxOrb: maxOrb = i if j > maxOrb: maxOrb = j print "" return (maxOrb, cntOrbs)
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)
#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 #Start of SCF Procedures############################