예제 #1
0
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
예제 #2
0
def test():
    from Ints import getbasis, getints, get2JmK
    from hartree_fock import get_nel, get_enuke, get_energy
    from LA2 import geigh, mkdens
    from IO import mtx2file
    from Molecule import Molecule

    ConvCriteria = 0.00001
    MaxIt = 30
    h2o = Molecule("h2o", [(8, (0, 0, 0)), (1, (1.0, 0, 0)), (1, (0, 1.0, 0))], units="Angstrom")
    bfs = getbasis(h2o)
    S, h, Ints = getints(bfs, h2o)
    orbe, orbs = geigh(h, S)
    nel = get_nel(h2o)
    nocc = int(nel / 2)
    enuke = get_enuke(h2o)
    eold = 0.0
    avg = DIIS2(S)
    for i in range(30):
        D = mkdens(orbs, 0, nocc)
        mtx2file(D)
        G = get2JmK(Ints, D)
        F = h + G
        F = avg.getF(F, D)  # do the DIIS extrapolation
        orbe, orbs = geigh(F, S)
        energy = get_energy(h, F, D, enuke)
        print i + 1, energy
        if abs(energy - eold) < ConvCriteria:
            break
        eold = energy

    return
예제 #3
0
def test():
    from Ints import getbasis, getints, get2JmK
    from hartree_fock import get_nel, get_enuke, get_energy
    from LA2 import geigh, mkdens
    from IO import mtx2file
    from Molecule import Molecule

    ConvCriteria = 0.00001
    MaxIt = 30
    h2o = Molecule('h2o', [(8, (0, 0, 0)), (1, (1., 0, 0)), (1, (0, 1., 0))],
                   units='Angstrom')
    bfs = getbasis(h2o)
    S, h, Ints = getints(bfs, h2o)
    orbe, orbs = geigh(h, S)
    nel = get_nel(h2o)
    nocc = int(nel / 2)
    enuke = get_enuke(h2o)
    eold = 0.
    avg = DIIS2(S)
    for i in xrange(30):
        D = mkdens(orbs, 0, nocc)
        mtx2file(D)
        G = get2JmK(Ints, D)
        F = h + G
        F = avg.getF(F, D)  # do the DIIS extrapolation
        orbe, orbs = geigh(F, S)
        energy = get_energy(h, F, D, enuke)
        print i + 1, energy
        if abs(energy - eold) < ConvCriteria: break
        eold = energy

    return
예제 #4
0
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
예제 #5
0
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
예제 #6
0
def mkdens_occs(c,occs,**kwargs):
    "Density matrix from a set of occupations (e.g. from FD expression)."
    tol = kwargs.get('tol',settings.FDOccTolerance)
    verbose = kwargs.get('verbose')
    # Determine how many orbs have occupations greater than 0
    norb = 0
    for fi in occs:
        if fi < tol: break
        norb += 1
    if verbose:
        print "mkdens_occs: %d occupied orbitals found" % norb
    # Determine how many doubly occupied orbitals we have
    nclosed = 0
    for i in xrange(norb):
        if abs(1.-occs[i]) > tol: break
        nclosed += 1
    if verbose:
        print "mkdens_occs: %d closed-shell orbitals found" % nclosed
    D = mkdens(c,0,nclosed)
    for i in xrange(nclosed,norb):
        D = D + occs[i]*matrixmultiply(c[:,i:i+1],transpose(c[:,i:i+1]))
    return D
예제 #7
0
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
예제 #8
0
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',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]
    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:
    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
예제 #9
0
def rhf(atoms,**opts):
    """\
    rhf(atoms,**opts) - 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 = opts.get('ConvCriteria',1e-10)
    MaxIter = opts.get('MaxIter',20)
    DoAveraging = opts.get('DoAveraging',False)
    ETemp = opts.get('ETemp',False)
    
    logger.info("RHF calculation on %s" % atoms.name)

    bfs = opts.get('bfs',None)
    if not bfs:
        basis_data = opts.get('basis_data',None)
        bfs = getbasis(atoms,basis_data)

    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)

    integrals = opts.get('integrals', None)
    if integrals:
        S,h,Ints = integrals
    else:
        S,h,Ints = getints(bfs,atoms)

    nel = atoms.get_nel()

    orbs = opts.get('orbs',None)
    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
예제 #10
0
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)
예제 #11
0
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
예제 #12
0
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)
예제 #13
0
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', 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]
    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:
    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