def rhf(atoms, **kwargs): """\ rhf(atoms,**kwargs) - Closed-shell HF driving routine atoms A Molecule object containing the molecule Options: Value Description -------- ----- ----------- 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 """ ConvCriteria = kwargs.get('ConvCriteria', settings.ConvergenceCriteria) MaxIter = kwargs.get('MaxIter', settings.MaxIter) DoAveraging = kwargs.get('DoAveraging', settings.Averaging) ETemp = kwargs.get('ETemp', settings.ElectronTemperature) logger.info("RHF calculation on %s" % atoms.name) bfs = getbasis(atoms, **kwargs) nclosed, nopen = atoms.get_closedopen() nocc = nclosed assert (nopen == 0), "SCF currently only works for closed-shell systems" logger.info("Nbf = %d" % len(bfs)) logger.info("Nclosed = %d" % nclosed) S, h, Ints = getints(bfs, atoms, **kwargs) nel = atoms.get_nel() orbs = kwargs.get('orbs') if orbs is None: orbe, orbs = geigh(h, S) enuke = atoms.get_enuke() eold = 0. if DoAveraging: logger.info("Using DIIS averaging") avg = DIIS(S) logging.debug("Optimization of HF orbitals") for i in xrange(MaxIter): 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 = mkdens(orbs, 0, nocc) G = get2JmK(Ints, D) F = h + G if DoAveraging: F = avg.getF(F, D) orbe, orbs = geigh(F, S) energy = get_energy(h, F, D, enuke) if ETemp: energy += entropy logging.debug("%d %f" % (i, energy)) if abs(energy - eold) < ConvCriteria: break logger.info("Iteration: %d Energy: %f EnergyVar: %f" % (i, energy, abs(energy - eold))) eold = energy if i < MaxIter: logger.info("PyQuante converged in %d iterations" % i) else: logger.warning("PyQuante failed to converge after %d iterations" % MaxIter) logger.info("Final HF energy for system %s is %f" % (atoms.name, energy)) return energy, orbe, orbs
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