def scfopen(atoms, F0, nalpha, nbeta, **opts): "SCF procedure for open-shell molecules" verbose = opts.get("verbose", False) D = get_guess_D(atoms) Da = 0.5 * D Db = 0.5 * D Eold = 0 for i in xrange(10): F1a = get_F1_open(atoms, Da, Db) F1b = get_F1_open(atoms, Db, Da) F2a = get_F2_open(atoms, Da, Db) F2b = get_F2_open(atoms, Db, Da) Fa = F0 + F1a + F2a Fb = F0 + F1b + F2b Eel = 0.5 * trace2(Da, F0 + Fa) + 0.5 * trace2(Db, F0 + Fb) if verbose: print i, Eel if abs(Eel - Eold) < 0.001: break Eold = Eel orbea, orbsa = eigh(Fa) orbeb, orbsb = eigh(Fb) Da = mkdens(orbsa, 0, nalpha) Db = mkdens(orbsb, 0, nbeta) return Eel
def der_oneeE(a, D, bset, atoms): dH_dXa, dH_dYa, dH_dZa = der_Hcore_matrix(a, bset, atoms) doneE_Xa = trace2(D, dH_dXa) doneE_Ya = trace2(D, dH_dYa) doneE_Za = trace2(D, dH_dZa) #print doneE_Xa,doneE_Ya,doneE_Za return array([doneE_Xa, doneE_Ya, doneE_Za], 'd')
def der_oneeE(a,D,bset,atoms): dH_dXa,dH_dYa,dH_dZa = der_Hcore_matrix(a,bset,atoms) doneE_Xa = trace2(D,dH_dXa) doneE_Ya = trace2(D,dH_dYa) doneE_Za = trace2(D,dH_dZa) #print doneE_Xa,doneE_Ya,doneE_Za return array([doneE_Xa,doneE_Ya,doneE_Za],'d')
def der_twoeE(a,D,bset): d2Ints_dXa,d2Ints_dYa,d2Ints_dZa = der2Ints(a,bset) Gx,Gy,Gz = der2JmK(D,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa) dtwoeE_Xa = trace2(D,Gx) dtwoeE_Ya = trace2(D,Gy) dtwoeE_Za = trace2(D,Gz) #print dtwoeE_Xa,dtwoeE_Ya,dtwoeE_Za return array([dtwoeE_Xa,dtwoeE_Ya,dtwoeE_Za],'d')
def der_twoeE(a, D, bset): d2Ints_dXa, d2Ints_dYa, d2Ints_dZa = der2Ints(a, bset) Gx, Gy, Gz = der2JmK(D, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa) dtwoeE_Xa = trace2(D, Gx) dtwoeE_Ya = trace2(D, Gy) dtwoeE_Za = trace2(D, Gz) #print dtwoeE_Xa,dtwoeE_Ya,dtwoeE_Za return array([dtwoeE_Xa, dtwoeE_Ya, dtwoeE_Za], 'd')
def scfclosed(atoms, F0, nclosed, **opts): "SCF procedure for closed-shell molecules" verbose = opts.get("verbose", False) do_avg = opts.get("avg", False) maxiter = opts.get("maxiter", 50) D = get_guess_D(atoms) Eold = 0 if do_avg: avg = SimpleAverager(do_avg) for i in xrange(maxiter): if do_avg: D = avg.getD(D) F1 = get_F1(atoms, D) F2 = get_F2(atoms, D) F = F0 + F1 + F2 Eel = 0.5 * trace2(D, F0 + F) if verbose: print i + 1, Eel, get_Hf(atoms, Eel) # if verbose: print i+1,Eel if abs(Eel - Eold) < 0.001: if verbose: print "Exiting because converged", i + 1, Eel, Eold break Eold = Eel orbe, orbs = eigh(F) D = 2 * mkdens(orbs, 0, nclosed) return Eel
def der_dmat(a,Qmat,bset): """ Looking at Szabo's equation C.12 you can see that this term results from adding up the terms that involve derivatives of the density matrix elements P_mu,nu. Following Szabo we compute this term as sum_mu,nu Q_mu,nu dS_mu,nu / dRa where the Q matrix is essentially a density matrix that is weighted by the orbital eigenvalues. Computing the derivative of the overlap integrals is done in the der_overlap_matrix function later in this module. """ dS_dXa,dS_dYa,dS_dZa = der_overlap_matrix(a,bset) dDmat_Xa = trace2(Qmat,dS_dXa) dDmat_Ya = trace2(Qmat,dS_dYa) dDmat_Za = trace2(Qmat,dS_dZa) #print dDmat_Xa,dDmat_Ya,dDmat_Za return array([dDmat_Xa,dDmat_Ya,dDmat_Za],'d')
def der_dmat(a, Qmat, bset): """ Looking at Szabo's equation C.12 you can see that this term results from adding up the terms that involve derivatives of the density matrix elements P_mu,nu. Following Szabo we compute this term as sum_mu,nu Q_mu,nu dS_mu,nu / dRa where the Q matrix is essentially a density matrix that is weighted by the orbital eigenvalues. Computing the derivative of the overlap integrals is done in the der_overlap_matrix function later in this module. """ dS_dXa, dS_dYa, dS_dZa = der_overlap_matrix(a, bset) dDmat_Xa = trace2(Qmat, dS_dXa) dDmat_Ya = trace2(Qmat, dS_dYa) dDmat_Za = trace2(Qmat, dS_dZa) #print dDmat_Xa,dDmat_Ya,dDmat_Za return array([dDmat_Xa, dDmat_Ya, dDmat_Za], 'd')
def der_twoeE_uhf(a,Da,Db,bset): d2Ints_dXa,d2Ints_dYa,d2Ints_dZa = der2Ints(a,bset) dJax,dJay,dJaz = derJ(Da,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa) dJbx,dJby,dJbz = derJ(Db,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa) dKax,dKay,dKaz = derK(Da,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa) dKbx,dKby,dKbz = derK(Db,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa) Dab = Da + Db dtwoeE_Xa = 0.5*trace2(Dab,dJax+dJbx) - 0.5*(trace2(Da,dKax)+trace2(Db,dKbx)) dtwoeE_Ya = 0.5*trace2(Dab,dJay+dJby) - 0.5*(trace2(Da,dKay)+trace2(Db,dKby)) dtwoeE_Za = 0.5*trace2(Dab,dJaz+dJbz) - 0.5*(trace2(Da,dKaz)+trace2(Db,dKbz)) return array([dtwoeE_Xa,dtwoeE_Ya,dtwoeE_Za],'d')
def der_twoeE_uhf(a, Da, Db, bset): d2Ints_dXa, d2Ints_dYa, d2Ints_dZa = der2Ints(a, bset) dJax, dJay, dJaz = derJ(Da, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa) dJbx, dJby, dJbz = derJ(Db, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa) dKax, dKay, dKaz = derK(Da, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa) dKbx, dKby, dKbz = derK(Db, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa) Dab = Da + Db dtwoeE_Xa = 0.5 * trace2( Dab, dJax + dJbx) - 0.5 * (trace2(Da, dKax) + trace2(Db, dKbx)) dtwoeE_Ya = 0.5 * trace2( Dab, dJay + dJby) - 0.5 * (trace2(Da, dKay) + trace2(Db, dKby)) dtwoeE_Za = 0.5 * trace2( Dab, dJaz + dJbz) - 0.5 * (trace2(Da, dKaz) + trace2(Db, dKbz)) return array([dtwoeE_Xa, dtwoeE_Ya, dtwoeE_Za], 'd')
def scfopen(atoms,F0,nalpha,nbeta,**kwargs): "SCF procedure for open-shell molecules" verbose = kwargs.get('verbose') D = get_guess_D(atoms) Da = 0.5*D Db = 0.5*D Eold = 0 for i in xrange(10): F1a = get_F1_open(atoms,Da,Db) F1b = get_F1_open(atoms,Db,Da) F2a = get_F2_open(atoms,Da,Db) F2b = get_F2_open(atoms,Db,Da) Fa = F0+F1a+F2a Fb = F0+F1b+F2b Eel = 0.5*trace2(Da,F0+Fa)+0.5*trace2(Db,F0+Fb) if verbose: print i,Eel if abs(Eel-Eold) < 0.001: break Eold = Eel orbea,orbsa = eigh(Fa) orbeb,orbsb = eigh(Fb) Da = mkdens(orbsa,0,nalpha) Db = mkdens(orbsb,0,nbeta) return Eel
def scfclosed(atoms,F0,nclosed,**kwargs): "SCF procedure for closed-shell molecules" verbose = kwargs.get('verbose') do_avg = kwargs.get('avg',settings.MINDOAveraging) maxiter = kwargs.get('maxiter',settings.MaxIter) D = get_guess_D(atoms) Eold = 0 if do_avg: avg = SimpleAverager(do_avg) for i in xrange(maxiter): if do_avg: D = avg.getD(D) F1 = get_F1(atoms,D) F2 = get_F2(atoms,D) F = F0+F1+F2 Eel = 0.5*trace2(D,F0+F) if verbose: print i+1,Eel,get_Hf(atoms,Eel) #if verbose: print i+1,Eel if abs(Eel-Eold) < 0.001: if verbose: print "Exiting because converged",i+1,Eel,Eold break Eold = Eel orbe,orbs = eigh(F) D = 2*mkdens(orbs,0,nclosed) return Eel
def udft_fixed_occ(atoms, occa, occb, **kwargs): """\ occa and occb represent the orbital occupation arrays for the calculating spin orbitals with holes udft(atoms,**kwargs) - Unrestricted spin DFT driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- verbose False Output terse information to stdout (default) True Print out additional information ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS for accelerated convergence (default) False No convergence acceleration ETemp False Use ETemp value for finite temperature DFT (default) float Use (float) for the electron temperature bfs None The basis functions to use. List of CGBF's 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 orbs None If not none, the guess orbitals functional SVWN Use the SVWN (LDA) DFT functional (default) S0 Use the Slater Xalpha DFT functional BLYP Use the BLYP GGA DFT functional PBE Use the PBE DFT functional grid_nrad 32 Number of radial shells per atom grid_fineness 1 Radial shell fineness. 0->coarse, 1->medium, 2->fine """ verbose = kwargs.get('verbose', False) ConvCriteria = kwargs.get('ConvCriteria', 1e-4) MaxIter = kwargs.get('MaxIter', 20) DoAveraging = kwargs.get('DoAveraging', True) averaging = kwargs.get('averaging', 0.5) ETemp = kwargs.get('ETemp', False) functional = kwargs.get('functional', 'LDA') #default to LDA which has no correlation since that is easier kwargs['do_grad_dens'] = need_gradients[functional] kwargs['do_spin_polarized'] = True bfs = kwargs.get('bfs', None) if not bfs: basis_data = kwargs.get('basis_data', None) bfs = getbasis(atoms, basis_data) integrals = kwargs.get('integrals', None) if integrals: S, h, Ints = integrals else: S, h, Ints = getints(bfs, atoms) nel = atoms.get_nel() enuke = atoms.get_enuke() # default medium mesh grid_nrad = kwargs.get('grid_nrad', 32) grid_fineness = kwargs.get('grid_fineness', 1) gr = MolecularGrid(atoms, grid_nrad, grid_fineness, **kwargs) gr.set_bf_amps(bfs) # It would be nice to have a more intelligent treatment of the guess # so that I could pass in a density rather than a set of orbs. orbs = kwargs.get('orbs', None) if not orbs: orbe, orbs = geigh(h, S) orbsa = orbsb = orbs nalpha, nbeta = atoms.get_alphabeta() if verbose: print "UDFT calculation on %s using functional %s" % (atoms.name, functional) print "Nbf = %d" % len(bfs) print "Nalpha = %d" % nalpha print "Nbeta = %d" % nbeta eold = 0. # Converge the LDA density for the system: print "Optimization of DFT density" for i in xrange(MaxIter): Da = mk_auger_dens(orbsa, occa) Db = mk_auger_dens(orbsb, occb) Dab = Da + Db 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) #remember we must use a functional that has no correlation energy gr.setdens(Da, Db) exca, XCa, XCb = getXC(gr, nel, **kwargs) Fa = h + Ja + Jb + XCa Fb = h + Ja + Jb + XCb orbea, orbsa = geigh(Fa, S) orbeb, orbsb = geigh(Fb, S) Eone = trace2(Dab, h) Ej = 0.5 * trace2(Dab, Ja + Jb) Exc = 0.5 * exca + 0.5 * excb energy = Eone + Ej + Exc + enuke print i + 1, " ", energy, " ", Ej, " ", Exc if verbose: print "%d %10.4f %10.4f %10.4f" % (i, energy, Ej, Exc) if abs(energy - eold) < ConvCriteria: break eold = energy print "Final U%s energy for system %s is %f" % (functional, atoms.name, energy) return energy, (orbea, orbeb), (orbsa, orbsb)
def udft(atoms,**kwargs): """\ udft(atoms,**kwargs) - Unrestricted spin DFT driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- verbose False Output terse information to stdout (default) True Print out additional information ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS for accelerated convergence (default) False No convergence acceleration ETemp False Use ETemp value for finite temperature DFT (default) float Use (float) for the electron temperature bfs None The basis functions to use. List of CGBF's 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 orbs None If not none, the guess orbitals functional SVWN Use the SVWN (LDA) DFT functional (default) S0 Use the Slater Xalpha DFT functional BLYP Use the BLYP GGA DFT functional PBE Use the PBE DFT functional grid_nrad 32 Number of radial shells per atom grid_fineness 1 Radial shell fineness. 0->coarse, 1->medium, 2->fine """ verbose = kwargs.get('verbose') ConvCriteria = kwargs.get('ConvCriteria',settings.DFTConvergenceCriteria) MaxIter = kwargs.get('MaxIter',settings.MaxIter) DoAveraging = kwargs.get('DoAveraging',settings.DFTAveraging) ETemp = kwargs.get('ETemp',settings.DFT.ElectronTemperature) functional = kwargs.get('functional',settings.DFTFunctional) kwargs['do_grad_dens'] = need_gradients[functional] kwargs['do_spin_polarized'] = True bfs = getbasis(atoms,**kwargs) S,h,Ints = getints(bfs,atoms,**kwargs) nel = atoms.get_nel() enuke = atoms.get_enuke() # default medium mesh grid_nrad = kwargs.get('grid_nrad',settings.DFTGridRadii) grid_fineness = kwargs.get('grid_fineness',settings.DFTGridFineness) gr = MolecularGrid(atoms,grid_nrad,grid_fineness,**kwargs) gr.set_bf_amps(bfs) # It would be nice to have a more intelligent treatment of the guess # so that I could pass in a density rather than a set of orbs. orbs = kwargs.get('orbs') if not orbs: orbe,orbs = geigh(h,S) orbsa = orbsb = orbs nalpha,nbeta = atoms.get_alphabeta() if verbose: print "UDFT calculation on %s using functional %s" \ % (atoms.name,functional) print "Nbf = %d" % len(bfs) print "Nalpha = %d" % nalpha print "Nbeta = %d" % nbeta eold = 0. # Converge the LDA density for the system: if verbose: print "Optimization of DFT density" for i in xrange(MaxIter): Da = mkdens(orbsa,0,nalpha) Db = mkdens(orbsb,0,nbeta) gr.setdens(Da,Db) Ja = getJ(Ints,Da) Jb = getJ(Ints,Db) Exc,XCa,XCb = getXC(gr,nel,**kwargs) Fa = h+Ja+Jb-Ka Fb = h+Ja+Jb-Kb orbea,orbsa = geigh(Fa,S) orbeb,orbsb = geigh(Fb,S) Eja = trace2(D,Ja) Ejb = trace2(D,Jb) Eone = 2*trace2(D,h) energy = Eone + Eja + Ejb + Exc + enuke if verbose: print "%d %10.4f %10.4f %10.4f %10.4f %10.4f" % ( i,energy,Eone,Eja+Ejb,Exc,enuke) if abs(energy-eold) < ConvCriteria: break eold = energy print "Final U%s energy for system %s is %f" % ( functional,atoms.name,energy) return energy,orbe,orbs
def udft_fixed_occ(atoms,occa, occb, **kwargs): """\ occa and occb represent the orbital occupation arrays for the calculating spin orbitals with holes udft(atoms,**kwargs) - Unrestricted spin DFT driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- verbose False Output terse information to stdout (default) True Print out additional information ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS for accelerated convergence (default) False No convergence acceleration ETemp False Use ETemp value for finite temperature DFT (default) float Use (float) for the electron temperature bfs None The basis functions to use. List of CGBF's 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 orbs None If not none, the guess orbitals functional SVWN Use the SVWN (LDA) DFT functional (default) S0 Use the Slater Xalpha DFT functional BLYP Use the BLYP GGA DFT functional PBE Use the PBE DFT functional grid_nrad 32 Number of radial shells per atom grid_fineness 1 Radial shell fineness. 0->coarse, 1->medium, 2->fine """ verbose = kwargs.get('verbose',False) ConvCriteria = kwargs.get('ConvCriteria',1e-4) MaxIter = kwargs.get('MaxIter',20) DoAveraging = kwargs.get('DoAveraging',True) averaging = kwargs.get('averaging',0.5) ETemp = kwargs.get('ETemp',False) functional = kwargs.get('functional','LDA') #default to LDA which has no correlation since that is easier kwargs['do_grad_dens'] = need_gradients[functional] kwargs['do_spin_polarized'] = True bfs = kwargs.get('bfs',None) if not bfs: basis_data = kwargs.get('basis_data',None) bfs = getbasis(atoms,basis_data) integrals = kwargs.get('integrals',None) if integrals: S,h,Ints = integrals else: S,h,Ints = getints(bfs,atoms) nel = atoms.get_nel() enuke = atoms.get_enuke() # default medium mesh grid_nrad = kwargs.get('grid_nrad',32) grid_fineness = kwargs.get('grid_fineness',1) gr = MolecularGrid(atoms,grid_nrad,grid_fineness,**kwargs) gr.set_bf_amps(bfs) # It would be nice to have a more intelligent treatment of the guess # so that I could pass in a density rather than a set of orbs. orbs = kwargs.get('orbs',None) if not orbs: orbe,orbs = geigh(h,S) orbsa = orbsb = orbs nalpha,nbeta = atoms.get_alphabeta() if verbose: print "UDFT calculation on %s using functional %s" % ( atoms.name,functional) print "Nbf = %d" % len(bfs) print "Nalpha = %d" % nalpha print "Nbeta = %d" % nbeta eold = 0. # Converge the LDA density for the system: print "Optimization of DFT density" for i in xrange(MaxIter): Da = mk_auger_dens(orbsa, occa) Db = mk_auger_dens(orbsb, occb) Dab = Da + Db 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) #remember we must use a functional that has no correlation energy gr.setdens(Da,Db) exca,XCa,XCb = getXC(gr,nel,**kwargs) Fa = h+Ja+Jb+XCa Fb = h+Ja+Jb+XCb orbea,orbsa = geigh(Fa,S) orbeb,orbsb = geigh(Fb,S) Eone = trace2(Dab,h) Ej = 0.5*trace2(Dab,Ja+Jb) Exc = 0.5*exca + 0.5*excb energy = Eone + Ej + Exc + enuke print i+1," ",energy," ",Ej," ",Exc if verbose: print "%d %10.4f %10.4f %10.4f" % (i,energy,Ej,Exc) if abs(energy-eold) < ConvCriteria: break eold = energy print "Final U%s energy for system %s is %f" % ( functional,atoms.name,energy) return energy,(orbea,orbeb),(orbsa,orbsb)
def dft_fixed_occ(atoms,occs,**kwargs): """\ dft(atoms,**kwargs) - DFT driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- verbose False Output terse information to stdout (default) True Print out additional information ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS for accelerated convergence (default) False No convergence acceleration ETemp False Use ETemp value for finite temperature DFT (default) float Use (float) for the electron temperature bfs None The basis functions to use. List of CGBF's 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 orbs None If not none, the guess orbitals functional SVWN Use the SVWN (LDA) DFT functional (default) S0 Use the Slater Xalpha DFT functional BLYP Use the BLYP GGA DFT functional PBE Use the PBE DFT functional grid_nrad 32 Number of radial shells per atom grid_fineness 1 Radial shell fineness. 0->coarse, 1->medium, 2->fine spin_type A Average occupation method for open shell (default) R Restricted open shell (not implemented yet) U Unrestricted open shell (aka spin-polarized dft) Only A works now. Stay tuned. """ verbose = kwargs.get('verbose',False) ConvCriteria = kwargs.get('ConvCriteria',1e-4) MaxIter = kwargs.get('MaxIter',20) DoAveraging = kwargs.get('DoAveraging',True) ETemp = kwargs.get('ETemp',False) functional = kwargs.get('functional','SVWN') kwargs['do_grad_dens'] = need_gradients[functional] bfs = kwargs.get('bfs',None) if not bfs: basis_data = kwargs.get('basis_data',None) bfs = getbasis(atoms,basis_data) integrals = kwargs.get('integrals',None) if integrals: S,h,Ints = integrals else: S,h,Ints = getints(bfs,atoms) nel = atoms.get_nel() enuke = atoms.get_enuke() # default medium mesh grid_nrad = kwargs.get('grid_nrad',32) grid_fineness = kwargs.get('grid_fineness',1) gr = MolecularGrid(atoms,grid_nrad,grid_fineness,**kwargs) gr.set_bf_amps(bfs) # It would be nice to have a more intelligent treatment of the guess # so that I could pass in a density rather than a set of orbs. orbs = kwargs.get('orbs',None) if orbs is None: orbe,orbs = geigh(h,S) nclosed,nopen = atoms.get_closedopen() if verbose: print "DFT calculation on %s using functional %s" % ( atoms.name,functional) print "Nbf = %d" % len(bfs) print "Nclosed = %d" % nclosed print "Nopen = %d" % nclosed if nopen: print "Using spin-averaged dft for open shell calculation" eold = 0. if DoAveraging: print "Using DIIS averaging" avg=DIIS(S) # Converge the LDA density for the system: if verbose: print "Optimization of DFT density" for i in xrange(MaxIter): #print "SCF Iteration:",i,"Starting Energy:",eold #save the starting orbitals oldorbs=orbs if ETemp: efermi = get_efermi(nel,orbe,ETemp) occs = get_fermi_occs(efermi,orbe,ETemp) D = mkdens_occs(orbs,occs) entropy = get_entropy(occs,ETemp) else: D = mk_auger_dens(orbs, occs) #D = mkdens_spinavg(orbs,nclosed,nopen) gr.setdens(D) J = getJ(Ints,D) Exc,XC = getXC(gr,nel,**kwargs) F = h+2*J+XC if DoAveraging: F = avg.getF(F,D) orbe,orbs = geigh(F,S) #pad_out(orbs) #save the new eigenstates of the fock operator F neworbs=orbs #send oldorbs and neworbs to get biorthogonalized method #orbs = biorthog(neworbs, oldorbs, S, nel) Ej = 2*trace2(D,J) Eone = 2*trace2(D,h) energy = Eone + Ej + Exc + enuke print i+1," ",energy," ",Ej," ",Exc," ",enuke if ETemp: energy += entropy if verbose: print "%d %10.4f %10.4f %10.4f %10.4f %10.4f" % ( i,energy,Eone,Ej,Exc,enuke) if abs(energy-eold) < ConvCriteria: break eold = energy print "Final %s energy for system %s is %f" % (functional,atoms.name,energy) return energy,orbe,orbs
def get_energy(h,F,D,enuke=0.,**opts): "Form the total energy of the closed-shell wave function." eone = trace2(D,h) etwo = trace2(D,F) #print "eone,etwo,enuke",(2*eone),(etwo-eone),enuke return eone+etwo+enuke
def uhf_fixed_occ(atoms,occa, occb,**opts): """\ occa and occb represent the orbital occupation arrays for the calculating spin orbitals with holes uhf(atoms,**opts) - Unrestriced Open Shell Hartree Fock atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS averaging for convergence acceleration bfs None The basis functions to use. List of CGBF's 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 orbs None If not None, the guess orbitals """ from biorthogonal import biorthogonalize,pad_out ConvCriteria = opts.get('ConvCriteria',1e-5) MaxIter = opts.get('MaxIter',40) DoAveraging = opts.get('DoAveraging',True) averaging = opts.get('averaging',0.5) ETemp = opts.get('ETemp',False) bfs = opts.get('bfs',None) if not bfs: basis_data = opts.get('basis_data',None) bfs = getbasis(atoms,basis_data) 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() #pass in opts for multiplicity S,h,Ints = getints(bfs,atoms) orbsa = opts.get('orbsa',None) orbsb = opts.get('orbsb',None) if (orbsa!=None and orbsb!=None): orbsa = orbsa orbsb = orbsb else: orbe,orbs = geigh(h,S) orbea = orbeb = orbe orbsa = orbsb = orbs #print "A Trial Orbital Energies:\n", orbea print "A Trial Orbitals:\n" pad_out(orbsa) #print "B Trial Orbital Energies:\n",orbeb print "B Trial Orbitals:\n" pad_out(orbsb) enuke = atoms.get_enuke() eold = 0. for i in xrange(MaxIter): print "SCF Iteration:",i,"Starting Energy:",eold #save the starting orbitals oldorbs_a=orbsa oldorbs_b=orbsb Da = mk_auger_dens(orbsa,occa) Db = mk_auger_dens(orbsb,occb) #Da_std = mkdens(orbsa,0,nalpha) #Db_std = mkdens(orbsb,0,nbeta) #pad_out(Da - Da_std ) #use to test mk_aug_dens with ground state occupations #pad_out(Db - Db_std ) 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 orbea,orbsa = geigh(Fa,S) orbeb,orbsb = geigh(Fb,S) #save the new orbitals neworbs_a=orbsa neworbs_b=orbsb #now we biorthogonalize the new orbitals to the old ones #to setup occupation arrays for the next scf cycle orbsa = biorthogonalize(neworbs_a,oldorbs_a,S,nalpha,occa) orbsb = biorthogonalize(neworbs_b,oldorbs_b,S,nbeta,occb) energya = get_energy(h,Fa,Da) energyb = get_energy(h,Fb,Db) energy = (energya+energyb)/2+enuke Dab = Da+Db Eone = trace2(Dab,h) Ej = 0.5*trace2(Dab,Ja+Jb) Ek = -0.5*(trace2(Da,Ka)+trace2(Db,Kb)) #print "%d %f %f %f %f" % (i,energy,Eone,Ej,Ek) logging.debug("%d %f %f %f %f" % (i,energy,Eone,Ej,Ek)) if abs(energy-eold) < ConvCriteria: break eold = energy if i==(MaxIter-1): print "Warning: Reached maximum number of SCF cycles may want to rerun calculation with more SCF cycles" logger.info("Final UHF energy for system %s is %f" % (atoms.name,energy)) return energy,(orbea,orbeb),(orbsa,orbsb)
def uhf(atoms, **kwargs): """\ uhf(atoms,**kwargs) - Unrestriced Open Shell Hartree Fock atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS averaging for convergence acceleration bfs None The basis functions to use. List of CGBF's 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 orbs None If not None, the guess orbitals """ ConvCriteria = kwargs.get('ConvCriteria', settings.ConvergenceCriteria) MaxIter = kwargs.get('MaxIter', settings.MaxIters) DoAveraging = kwargs.get('DoAveraging', settings.Averaging) averaging = kwargs.get('averaging', settings.MixingFraction) ETemp = kwargs.get('ETemp', settings.ElectronTemperature) verbose = kwargs.get('verbose') bfs = getbasis(atoms, **kwargs) S, h, Ints = getints(bfs, atoms, **kwargs) nel = atoms.get_nel() nalpha, nbeta = atoms.get_alphabeta() #pass in kwargs for multiplicity orbs = kwargs.get('orbs') if orbs != None: #orbsa = orbsb = orbs orbsa = orbs[0] orbsb = orbs[1] else: orbe, orbs = geigh(h, S) orbea = orbeb = orbe orbsa = orbsb = orbs enuke = atoms.get_enuke() eold = 0. logger.info("UHF calculation on %s" % atoms.name) logger.info("Nbf = %d" % len(bfs)) logger.info("Nalpha = %d" % nalpha) logger.info("Nbeta = %d" % nbeta) logger.info("Averaging = %s" % DoAveraging) logging.debug("Optimization of HF orbitals") for i in xrange(MaxIter): if verbose: print "SCF Iteration:", i, "Starting Energy:", eold if ETemp: # We have to multiply nalpha and nbeta by 2 # to get the Fermi energies to come out correct: efermia = get_efermi(2.0 * nalpha, orbea, ETemp) occsa = get_fermi_occs(efermia, orbea, ETemp) #print "occsa = ",occsa Da = mkdens_occs(orbsa, occsa) efermib = get_efermi(2.0 * nbeta, orbeb, ETemp) occsb = get_fermi_occs(efermib, orbeb, ETemp) #print "occsb = ",occsb 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) 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 orbea, orbsa = geigh(Fa, S) orbeb, orbsb = geigh(Fb, S) energya = get_energy(h, Fa, Da) energyb = get_energy(h, Fb, Db) energy = (energya + energyb) / 2 + enuke Dab = Da + Db Eone = trace2(Dab, h) Ej = 0.5 * trace2(Dab, Ja + Jb) Ek = -0.5 * (trace2(Da, Ka) + trace2(Db, Kb)) if ETemp: energy += entropy logger.debug("%d %f %f %f %f" % (i, energy, Eone, Ej, Ek)) if abs(energy - eold) < ConvCriteria: break eold = energy logger.info("Final UHF energy for system %s is %f" % (atoms.name, energy)) return energy, (orbea, orbeb), (orbsa, orbsb)
def dft_fixed_occ(atoms, occs, **kwargs): """\ dft(atoms,**kwargs) - DFT driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- verbose False Output terse information to stdout (default) True Print out additional information ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS for accelerated convergence (default) False No convergence acceleration ETemp False Use ETemp value for finite temperature DFT (default) float Use (float) for the electron temperature bfs None The basis functions to use. List of CGBF's 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 orbs None If not none, the guess orbitals functional SVWN Use the SVWN (LDA) DFT functional (default) S0 Use the Slater Xalpha DFT functional BLYP Use the BLYP GGA DFT functional PBE Use the PBE DFT functional grid_nrad 32 Number of radial shells per atom grid_fineness 1 Radial shell fineness. 0->coarse, 1->medium, 2->fine spin_type A Average occupation method for open shell (default) R Restricted open shell (not implemented yet) U Unrestricted open shell (aka spin-polarized dft) Only A works now. Stay tuned. """ verbose = kwargs.get('verbose', False) ConvCriteria = kwargs.get('ConvCriteria', 1e-4) MaxIter = kwargs.get('MaxIter', 20) DoAveraging = kwargs.get('DoAveraging', True) ETemp = kwargs.get('ETemp', False) functional = kwargs.get('functional', 'SVWN') kwargs['do_grad_dens'] = need_gradients[functional] bfs = kwargs.get('bfs', None) if not bfs: basis_data = kwargs.get('basis_data', None) bfs = getbasis(atoms, basis_data) integrals = kwargs.get('integrals', None) if integrals: S, h, Ints = integrals else: S, h, Ints = getints(bfs, atoms) nel = atoms.get_nel() enuke = atoms.get_enuke() # default medium mesh grid_nrad = kwargs.get('grid_nrad', 32) grid_fineness = kwargs.get('grid_fineness', 1) gr = MolecularGrid(atoms, grid_nrad, grid_fineness, **kwargs) gr.set_bf_amps(bfs) # It would be nice to have a more intelligent treatment of the guess # so that I could pass in a density rather than a set of orbs. orbs = kwargs.get('orbs', None) if orbs is None: orbe, orbs = geigh(h, S) nclosed, nopen = atoms.get_closedopen() if verbose: print "DFT calculation on %s using functional %s" % (atoms.name, functional) print "Nbf = %d" % len(bfs) print "Nclosed = %d" % nclosed print "Nopen = %d" % nclosed if nopen: print "Using spin-averaged dft for open shell calculation" eold = 0. if DoAveraging: print "Using DIIS averaging" avg = DIIS(S) # Converge the LDA density for the system: if verbose: print "Optimization of DFT density" for i in xrange(MaxIter): #print "SCF Iteration:",i,"Starting Energy:",eold #save the starting orbitals oldorbs = orbs if ETemp: efermi = get_efermi(nel, orbe, ETemp) occs = get_fermi_occs(efermi, orbe, ETemp) D = mkdens_occs(orbs, occs) entropy = get_entropy(occs, ETemp) else: D = mk_auger_dens(orbs, occs) #D = mkdens_spinavg(orbs,nclosed,nopen) gr.setdens(D) J = getJ(Ints, D) Exc, XC = getXC(gr, nel, **kwargs) F = h + 2 * J + XC if DoAveraging: F = avg.getF(F, D) orbe, orbs = geigh(F, S) #pad_out(orbs) #save the new eigenstates of the fock operator F neworbs = orbs #send oldorbs and neworbs to get biorthogonalized method #orbs = biorthog(neworbs, oldorbs, S, nel) Ej = 2 * trace2(D, J) Eone = 2 * trace2(D, h) energy = Eone + Ej + Exc + enuke print i + 1, " ", energy, " ", Ej, " ", Exc, " ", enuke if ETemp: energy += entropy if verbose: print "%d %10.4f %10.4f %10.4f %10.4f %10.4f" % (i, energy, Eone, Ej, Exc, enuke) if abs(energy - eold) < ConvCriteria: break eold = energy print "Final %s energy for system %s is %f" % (functional, atoms.name, energy) return energy, orbe, orbs
def get_energy(h, F, D, enuke=0., **kwargs): "Form the total energy of the closed-shell wave function." eone = trace2(D, h) etwo = trace2(D, F) #print "eone,etwo,enuke",(2*eone),(etwo-eone),enuke return eone + etwo + enuke
def uhf_fixed_occ(atoms, occa, occb, **kwargs): """\ occa and occb represent the orbital occupation arrays for the calculating spin orbitals with holes uhf(atoms,**kwargs) - Unrestriced Open Shell Hartree Fock atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS averaging for convergence acceleration bfs None The basis functions to use. List of CGBF's 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 orbs None If not None, the guess orbitals """ from biorthogonal import biorthogonalize, pad_out ConvCriteria = kwargs.get('ConvCriteria', settings.ConvergenceCriteria) MaxIter = kwargs.get('MaxIter', settings.MaxIters) DoAveraging = kwargs.get('DoAveraging', settings.Averaging) averaging = kwargs.get('averaging', settings.MixingFraction) ETemp = kwargs.get('ETemp', settings.ElectronTemperature) bfs = getbasis(atoms, **kwargs) S, h, Ints = getints(bfs, atoms, **kwargs) nel = atoms.get_nel() nalpha, nbeta = atoms.get_alphabeta() #pass in kwargs for multiplicity orbsa = kwargs.get('orbsa') orbsb = kwargs.get('orbsb') if (orbsa == None or orbsb == None): orbe, orbs = geigh(h, S) orbea = orbeb = orbe orbsa = orbsb = orbs #print "A Trial Orbital Energies:\n", orbea print "A Trial Orbitals:\n" pad_out(orbsa) #print "B Trial Orbital Energies:\n",orbeb print "B Trial Orbitals:\n" pad_out(orbsb) enuke = atoms.get_enuke() eold = 0. for i in xrange(MaxIter): print "SCF Iteration:", i, "Starting Energy:", eold #save the starting orbitals oldorbs_a = orbsa oldorbs_b = orbsb Da = mk_auger_dens(orbsa, occa) Db = mk_auger_dens(orbsb, occb) #Da_std = mkdens(orbsa,0,nalpha) #Db_std = mkdens(orbsb,0,nbeta) #pad_out(Da - Da_std ) #use to test mk_aug_dens with ground state occupations #pad_out(Db - Db_std ) 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 orbea, orbsa = geigh(Fa, S) orbeb, orbsb = geigh(Fb, S) #save the new orbitals neworbs_a = orbsa neworbs_b = orbsb #now we biorthogonalize the new orbitals to the old ones #to setup occupation arrays for the next scf cycle orbsa = biorthogonalize(neworbs_a, oldorbs_a, S, nalpha, occa) orbsb = biorthogonalize(neworbs_b, oldorbs_b, S, nbeta, occb) energya = get_energy(h, Fa, Da) energyb = get_energy(h, Fb, Db) energy = (energya + energyb) / 2 + enuke Dab = Da + Db Eone = trace2(Dab, h) Ej = 0.5 * trace2(Dab, Ja + Jb) Ek = -0.5 * (trace2(Da, Ka) + trace2(Db, Kb)) #print "%d %f %f %f %f" % (i,energy,Eone,Ej,Ek) logging.debug("%d %f %f %f %f" % (i, energy, Eone, Ej, Ek)) if abs(energy - eold) < ConvCriteria: break eold = energy if i == (MaxIter - 1): print "Warning: Reached maximum number of SCF cycles may want to rerun calculation with more SCF cycles" logger.info("Final UHF energy for system %s is %f" % (atoms.name, energy)) return energy, (orbea, orbeb), (orbsa, orbsb)
def udft(atoms, **kwargs): """\ udft(atoms,**kwargs) - Unrestricted spin DFT driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- verbose False Output terse information to stdout (default) True Print out additional information ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS for accelerated convergence (default) False No convergence acceleration ETemp False Use ETemp value for finite temperature DFT (default) float Use (float) for the electron temperature bfs None The basis functions to use. List of CGBF's 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 orbs None If not none, the guess orbitals functional SVWN Use the SVWN (LDA) DFT functional (default) S0 Use the Slater Xalpha DFT functional BLYP Use the BLYP GGA DFT functional PBE Use the PBE DFT functional grid_nrad 32 Number of radial shells per atom grid_fineness 1 Radial shell fineness. 0->coarse, 1->medium, 2->fine """ verbose = kwargs.get('verbose') ConvCriteria = kwargs.get('ConvCriteria', settings.DFTConvergenceCriteria) MaxIter = kwargs.get('MaxIter', settings.MaxIter) DoAveraging = kwargs.get('DoAveraging', settings.DFTAveraging) ETemp = kwargs.get('ETemp', settings.DFT.ElectronTemperature) functional = kwargs.get('functional', settings.DFTFunctional) kwargs['do_grad_dens'] = need_gradients[functional] kwargs['do_spin_polarized'] = True bfs = getbasis(atoms, **kwargs) S, h, Ints = getints(bfs, atoms, **kwargs) nel = atoms.get_nel() enuke = atoms.get_enuke() # default medium mesh grid_nrad = kwargs.get('grid_nrad', settings.DFTGridRadii) grid_fineness = kwargs.get('grid_fineness', settings.DFTGridFineness) gr = MolecularGrid(atoms, grid_nrad, grid_fineness, **kwargs) gr.set_bf_amps(bfs) # It would be nice to have a more intelligent treatment of the guess # so that I could pass in a density rather than a set of orbs. orbs = kwargs.get('orbs') if not orbs: orbe, orbs = geigh(h, S) orbsa = orbsb = orbs nalpha, nbeta = atoms.get_alphabeta() if verbose: print "UDFT calculation on %s using functional %s" \ % (atoms.name,functional) print "Nbf = %d" % len(bfs) print "Nalpha = %d" % nalpha print "Nbeta = %d" % nbeta eold = 0. # Converge the LDA density for the system: if verbose: print "Optimization of DFT density" for i in xrange(MaxIter): Da = mkdens(orbsa, 0, nalpha) Db = mkdens(orbsb, 0, nbeta) gr.setdens(Da, Db) Ja = getJ(Ints, Da) Jb = getJ(Ints, Db) Exc, XCa, XCb = getXC(gr, nel, **kwargs) Fa = h + Ja + Jb - Ka Fb = h + Ja + Jb - Kb orbea, orbsa = geigh(Fa, S) orbeb, orbsb = geigh(Fb, S) Eja = trace2(D, Ja) Ejb = trace2(D, Jb) Eone = 2 * trace2(D, h) energy = Eone + Eja + Ejb + Exc + enuke if verbose: print "%d %10.4f %10.4f %10.4f %10.4f %10.4f" % ( i, energy, Eone, Eja + Ejb, Exc, enuke) if abs(energy - eold) < ConvCriteria: break eold = energy print "Final U%s energy for system %s is %f" % (functional, atoms.name, energy) return energy, orbe, orbs
def uhf(atoms,**opts): """\ uhf(atoms,**opts) - Unrestriced Open Shell Hartree Fock atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- ConvCriteria 1e-4 Convergence Criteria MaxIter 20 Maximum SCF iterations DoAveraging True Use DIIS averaging for convergence acceleration bfs None The basis functions to use. List of CGBF's 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 orbs None If not None, the guess orbitals """ ConvCriteria = opts.get('ConvCriteria',1e-5) MaxIter = opts.get('MaxIter',40) DoAveraging = opts.get('DoAveraging',True) averaging = opts.get('averaging',0.5) ETemp = opts.get('ETemp',False) verbose = opts.get('verbose',False) bfs = opts.get('bfs',None) if not bfs: basis_data = opts.get('basis_data',None) bfs = getbasis(atoms,basis_data) 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() #pass in opts for multiplicity S,h,Ints = getints(bfs,atoms) orbs = opts.get('orbs',None) if orbs!=None: #orbsa = orbsb = orbs orbsa = orbs[0] orbsb = orbs[1] else: orbe,orbs = geigh(h,S) orbea = orbeb = orbe orbsa = orbsb = orbs enuke = atoms.get_enuke() eold = 0. logger.info("UHF calculation on %s" % atoms.name) logger.info("Nbf = %d" % len(bfs)) logger.info("Nalpha = %d" % nalpha) logger.info("Nbeta = %d" % nbeta) logger.info("Averaging = %s" % DoAveraging) logging.debug("Optimization of HF orbitals") for i in xrange(MaxIter): if verbose: print "SCF Iteration:",i,"Starting Energy:",eold if ETemp: # We have to multiply nalpha and nbeta by 2 # to get the Fermi energies to come out correct: efermia = get_efermi(2.0*nalpha,orbea,ETemp) occsa = get_fermi_occs(efermia,orbea,ETemp) #print "occsa = ",occsa Da = mkdens_occs(orbsa,occsa) efermib = get_efermi(2.0*nbeta,orbeb,ETemp) occsb = get_fermi_occs(efermib,orbeb,ETemp) #print "occsb = ",occsb 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) 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 orbea,orbsa = geigh(Fa,S) orbeb,orbsb = geigh(Fb,S) energya = get_energy(h,Fa,Da) energyb = get_energy(h,Fb,Db) energy = (energya+energyb)/2+enuke Dab = Da+Db Eone = trace2(Dab,h) Ej = 0.5*trace2(Dab,Ja+Jb) Ek = -0.5*(trace2(Da,Ka)+trace2(Db,Kb)) if ETemp: energy += entropy logger.debug("%d %f %f %f %f" % (i,energy,Eone,Ej,Ek)) if abs(energy-eold) < ConvCriteria: break eold = energy logger.info("Final UHF energy for system %s is %f" % (atoms.name,energy)) return energy,(orbea,orbeb),(orbsa,orbsb)