Ejemplo n.º 1
0
def get_exx_energy(b,nbf,nel,nocc,ETemp,Enuke,S,h,Ints,H0,Gij,**opts):
    """Computes the energy for the OEP/HF functional

    Options:
    return_flag    0   Just return the energy
                   1   Return energy, orbe, orbs
                   2   Return energy, orbe, orbs, F
    """
    return_flag = opts.get('return_flag',0)
    Hoep = get_Hoep(b,H0,Gij)
    orbe,orbs = geigh(Hoep,S)
        
    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)
        
    F = get_fock(D,Ints,h)
    energy = trace2(h+F,D)+Enuke
    if ETemp: energy += entropy
    iref = nel/2
    gap = 627.51*(orbe[iref]-orbe[iref-1])

    logging.debug("EXX Energy, B, Gap: %10.5f %10.5f %10.5f"
                  % (energy,sqrt(dot(b,b)),gap))
    #logging.debug("%s" % orbe)
    if return_flag == 1:
        return energy,orbe,orbs
    elif return_flag == 2:
        return energy,orbe,orbs,F
    return energy
Ejemplo n.º 2
0
def get_exx_energy(b, nbf, nel, nocc, ETemp, Enuke, S, h, Ints, H0, Gij,
                   **opts):
    """Computes the energy for the OEP/HF functional

    Options:
    return_flag    0   Just return the energy
                   1   Return energy, orbe, orbs
                   2   Return energy, orbe, orbs, F
    """
    return_flag = opts.get('return_flag', 0)
    Hoep = get_Hoep(b, H0, Gij)
    orbe, orbs = geigh(Hoep, S)

    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)

    F = get_fock(D, Ints, h)
    energy = trace2(h + F, D) + Enuke
    if ETemp: energy += entropy
    iref = nel / 2
    gap = 627.51 * (orbe[iref] - orbe[iref - 1])

    logging.debug("EXX Energy, B, Gap: %10.5f %10.5f %10.5f" %
                  (energy, sqrt(dot(b, b)), gap))
    #logging.debug("%s" % orbe)
    if return_flag == 1:
        return energy, orbe, orbs
    elif return_flag == 2:
        return energy, orbe, orbs, F
    return energy
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)