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 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 split_guess_lines(guess_lines): from PyQuante.Util import parseline from PyQuante.NumWrap import transpose, array import re orbpat = re.compile('Orbital Energy') orb = [] orbe = [] occs = [] orbs = [] for line in guess_lines: if orbpat.search(line): orbei, occi = parseline(line, 'xxxfxf') orbe.append(orbei) occs.append(occi) orb = [] orbs.append(orb) else: orb.extend(map(float, line.split())) orbs = transpose(array(orbs)) return occs, orbe, orbs
def split_guess_lines(guess_lines): from PyQuante.Util import parseline from PyQuante.NumWrap import transpose,array import re orbpat = re.compile('Orbital Energy') orb = [] orbe = [] occs = [] orbs = [] for line in guess_lines: if orbpat.search(line): orbei,occi = parseline(line,'xxxfxf') orbe.append(orbei) occs.append(occi) orb = [] orbs.append(orb) else: orb.extend(map(float,line.split())) orbs = transpose(array(orbs)) return occs,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
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 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 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 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)