Esempio n. 1
0
def compute_F(P, Hcore, X, Ints, mu=0):

    # get the matrix of 2J-K for a given fixed P
    # P is here given in the non- orthonormal basis
    G = get2JmK(Ints, P)

    # pass the G matrix in the orthonormal basis
    Gp = simx(G, X, 'T')

    # form the Fock matrix in the orthonomral basis
    F = Hcore + _ee_inter_ * Gp + mu

    return F
Esempio n. 2
0
def simple_hf(atoms,S,h,Ints):
    from PyQuante.LA2 import mkdens
    from PyQuante.hartree_fock import get_energy
    orbe,orbs = geigh(h,S)
    nclosed,nopen = atoms.get_closedopen()
    enuke = atoms.get_enuke()
    nocc = nclosed
    eold = 0
    for i in range(15):
        D = mkdens(orbs,0,nocc)
        G = get2JmK(Ints,D)
        F = h+G
        orbe,orbs = geigh(F,S)
        energy = get_energy(h,F,D,enuke)
        print "%d %f" % (i,energy)
        if abs(energy-eold) < 1e-4: break
        eold = energy
    print "Final HF energy for system %s is %f" % (atoms.name,energy)
    return energy,orbe,orbs
Esempio n. 3
0
def simple_hf(atoms, S, h, Ints):
    from PyQuante.LA2 import mkdens
    from PyQuante.hartree_fock import get_energy
    orbe, orbs = geigh(h, S)
    nclosed, nopen = atoms.get_closedopen()
    enuke = atoms.get_enuke()
    nocc = nclosed
    eold = 0
    for i in range(15):
        D = mkdens(orbs, 0, nocc)
        G = get2JmK(Ints, D)
        F = h + G
        orbe, orbs = geigh(F, S)
        energy = get_energy(h, F, D, enuke)
        print "%d %f" % (i, energy)
        if abs(energy - eold) < 1e-4: break
        eold = energy
    print "Final HF energy for system %s is %f" % (atoms.name, energy)
    return energy, orbe, orbs
Esempio n. 4
0
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
Esempio n. 5
0
def rhf(mol,
        bfs,
        S,
        Hcore,
        Ints,
        mu=0,
        MaxIter=100,
        eps_SCF=1E-4,
        _diis_=True):

    ##########################################################
    ##					Get the system information
    ##########################################################

    # size
    nbfs = len(bfs)

    # get the nuclear energy
    enuke = mol.get_enuke()

    # determine the number of electrons
    # and occupation numbers
    nelec = mol.get_nel()
    nclosed, nopen = mol.get_closedopen()
    nocc = nclosed

    # orthogonalization matrix
    X = SymOrthCutoff(S)

    if _ee_inter_ == 0:
        print '\t\t ==================================================='
        print '\t\t == Electrons-Electrons interactions desactivated =='
        print '\t\t ==================================================='

    if nopen != 0:
        print '\t\t ================================================================='
        print '\t\t Warning : using restricted HF with open shell is not recommended'
        print "\t\t Use only if you know what you're doing"
        print '\t\t ================================================================='

    # get a first DM
    #D = np.zeros((nbfs,nbfs))
    L, C = scla.eigh(Hcore, b=S)
    D = mkdens(C, 0, nocc)

    # initialize the old energy
    eold = 0.

    # initialize the DIIS
    if _diis_:
        avg = DIIS(S)

    #print '\t SCF Calculations'
    for iiter in range(MaxIter):

        # form the G matrix from the
        # density matrix and  the 2electron integrals
        G = get2JmK(Ints, D)

        # form the Fock matrix
        F = Hcore + _ee_inter_ * G + mu

        # if DIIS
        if _diis_:
            F = avg.getF(F, D)

        # orthogonalize the Fock matrix
        Fp = np.dot(X.T, np.dot(F, X))

        # diagonalize the Fock matrix
        Lp, Cp = scla.eigh(Fp)

        # form the density matrix in the OB
        if nopen == 0:
            Dp = mkdens(Cp, 0, nocc)
        else:
            Dp = mkdens_spinavg(Cp, nclosed, nopen)

        # pass the eigenvector back to the AO
        C = np.dot(X, Cp)

        # form the density matrix in the AO
        if nopen == 0:
            D = mkdens(C, 0, nocc)
        #else:
        #	D = mkdens_spinavg(C,nclosed,nopen)

        # compute the total energy
        e = np.sum(D * (Hcore + F)) + enuke

        print "\t\t Iteration: %d    Energy: %f    EnergyVar: %f" % (
            iiter, e.real, np.abs((e - eold).real))

        # stop if done
        if (np.abs(e - eold) < eps_SCF):
            break
        else:
            eold = e

    if iiter < MaxIter:
        print(
            "\t\t SCF for HF has converged in %d iterations, Final energy %1.3f Ha\n"
            % (iiter, e.real))

    else:
        print("\t\t SCF for HF has failed to converge after %d iterations")

    # compute the density matrix in the
    # eigenbasis of F
    P = np.dot(Cp.T, np.dot(Dp, Cp))
    #print D

    return Lp, C, Cp, F, Fp, D, Dp, P, X
Esempio n. 6
0
from PyQuante.Ints import get2JmK,getbasis,getints
from PyQuante.Convergence import DIIS
from PyQuante.hartree_fock import get_energy

bfs = getbasis(h2,basis="3-21g")
nclosed,nopen = h2.get_closedopen()
nocc = nclosed
nel = h2.get_nel()
S,h,Ints = getints(bfs,h2)

orbe,orbs = geigh(h,S)

enuke = h2.get_enuke()
eold = 0

avg = DIIS(S)

for i in range(20):
    D = mkdens(orbs,0,nocc)
    G = get2JmK(Ints,D)
    F = h+G
    F = avg.getF(F,D)
    orbe,orbs = geigh(F,S)
    energy = get_energy(h,F,D,enuke)
    print i,energy,energy-eold
    if abs(energy-eold)<1e-5:
        break
    eold = energy
print "Converged"
print energy, "(benchmark = -1.122956)"
Esempio n. 7
0
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