Пример #1
0
 def get_energy(self,b):
     self.iter += 1
     ba = b[:self.nbf]
     bb = b[self.nbf:]
     self.Hoepa = get_Hoep(ba,self.H0,self.Gij)
     self.Hoepb = get_Hoep(bb,self.H0,self.Gij)
     self.orbea,self.orbsa = geigh(self.Hoepa,self.S)
     self.orbeb,self.orbsb = geigh(self.Hoepb,self.S)
     if self.etemp:
         self.Da,entropya = mkdens_fermi(2*self.nalpha,self.orbea,self.orbsa,
                                         self.etemp)
         self.Db,entropyb = mkdens_fermi(2*self.nbeta,self.orbeb,self.orbsb,
                                         self.etemp)
         self.entropy = 0.5*(entropya+entropyb)
     else:
         self.Da = mkdens(self.orbsa,0,self.nalpha)
         self.Db = mkdens(self.orbsb,0,self.nbeta)
         self.entropy=0
     J = getJ(self.Ints,self.Da+self.Db)
     Ka = getK(self.Ints,self.Da)
     Kb = getK(self.Ints,self.Db)
     self.Fa = self.h + J - Ka
     self.Fb = self.h + J - Kb
     self.energy = 0.5*(trace2(self.h+self.Fa,self.Da) +
                        trace2(self.h+self.Fb,self.Db))\
                        + self.Enuke + self.entropy
     if self.iter == 1 or self.iter % 10 == 0:
         logging.debug("%4d %10.5f %10.5f" % (self.iter,self.energy,dot(b,b)))
     return self.energy
Пример #2
0
 def get_energy(self, b):
     self.iter += 1
     ba = b[:self.nbf]
     bb = b[self.nbf:]
     self.Hoepa = get_Hoep(ba, self.H0, self.Gij)
     self.Hoepb = get_Hoep(bb, self.H0, self.Gij)
     self.orbea, self.orbsa = geigh(self.Hoepa, self.S)
     self.orbeb, self.orbsb = geigh(self.Hoepb, self.S)
     if self.etemp:
         self.Da, entropya = mkdens_fermi(2 * self.nalpha, self.orbea,
                                          self.orbsa, self.etemp)
         self.Db, entropyb = mkdens_fermi(2 * self.nbeta, self.orbeb,
                                          self.orbsb, self.etemp)
         self.entropy = 0.5 * (entropya + entropyb)
     else:
         self.Da = mkdens(self.orbsa, 0, self.nalpha)
         self.Db = mkdens(self.orbsb, 0, self.nbeta)
         self.entropy = 0
     J = getJ(self.Ints, self.Da + self.Db)
     Ka = getK(self.Ints, self.Da)
     Kb = getK(self.Ints, self.Db)
     self.Fa = self.h + J - Ka
     self.Fb = self.h + J - Kb
     self.energy = 0.5*(trace2(self.h+self.Fa,self.Da) +
                        trace2(self.h+self.Fb,self.Db))\
                        + self.Enuke + self.entropy
     if self.iter == 1 or self.iter % 10 == 0:
         logging.debug("%4d %10.5f %10.5f" %
                       (self.iter, self.energy, dot(b, b)))
     return self.energy
Пример #3
0
def pyq1_dft(atomtuples=[(2, (0, 0, 0))],
             basis='6-31G**',
             maxit=10,
             xcname='SVWN'):
    from PyQuante import Ints, settings, Molecule
    from PyQuante.dft import getXC
    from PyQuante.MG2 import MG2 as MolecularGrid
    from PyQuante.LA2 import mkdens, geigh, trace2
    from PyQuante.Ints import getJ

    print("PyQ1 DFT run")
    atoms = Molecule('Pyq1', atomlist=atomtuples)

    bfs = Ints.getbasis(atoms, basis=basis)
    S, h, Ints = Ints.getints(bfs, atoms)

    nclosed, nopen = nel // 2, nel % 2
    assert nopen == 0
    enuke = atoms.get_enuke()

    grid_nrad = settings.DFTGridRadii
    grid_fineness = settings.DFTGridFineness

    gr = MolecularGrid(atoms, grid_nrad, grid_fineness)
    gr.set_bf_amps(bfs)

    orbe, orbs = geigh(h, S)
    eold = 0

    for i in range(maxit):
        D = mkdens(orbs, 0, nclosed)
        gr.setdens(D)

        J = getJ(Ints, D)

        Exc, Vxc = getXC(gr, nel, functional=xcname)

        F = h + 2 * J + Vxc
        orbe, orbs = geigh(F, S)

        Ej = 2 * trace2(D, J)
        Eone = 2 * trace2(D, h)
        energy = Eone + Ej + Exc + enuke

        print(i, energy, Eone, Ej, Exc, enuke)
        if np.isclose(energy, eold):
            break
        eold = energy
    return energy
Пример #4
0
 def solve(self, H, **kwargs):
     from PyQuante.LA2 import geigh
     from PyQuante.fermi_dirac import mkdens_fermi
     self.orbe, self.orbs = geigh(H, self.S)
     self.D, self.entropy = mkdens_fermi(self.nel, self.orbe, self.orbs,
                                         self.etemp)
     return self.D, self.entropy
Пример #5
0
 def solve(self,H,**opts):
     from PyQuante.LA2 import geigh
     from PyQuante.fermi_dirac import mkdens_fermi
     self.orbe,self.orbs = geigh(H,self.S)
     self.D,self.entropy = mkdens_fermi(self.nel,self.orbe,
                                        self.orbs,self.etemp)
     return self.D,self.entropy
Пример #6
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
Пример #7
0
def rohf_wag(atoms,noccsh=None,f=None,a=None,b=None,**kwargs):
    """\
    rohf(atoms,noccsh=None,f=None,a=None,b=None,**kwargs):
        Restricted open shell HF driving routine

    atoms      A Molecule object containing the system of interest
    """
    ConvCriteria = kwargs.get('ConvCriteria',settings.ConvergenceCriteria)
    MaxIter = kwargs.get('MaxIter',settings.MaxIter)
    DoAveraging = kwargs.get('DoAveraging',settings.Averaging)
    verbose = kwargs.get('verbose')

    bfs = getbasis(atoms,**kwargs)

    S,h,Ints = getints(bfs,atoms,**kwargs)

    nel = atoms.get_nel()

    orbs = kwargs.get('orbs')
    if orbs is None:
        orbe,orbs = geigh(h,nS)

    nclosed,nopen = atoms.get_closedopen()
    nocc = nopen+nclosed
    if not noccsh: noccsh = get_noccsh(nclosed,nopen)
    nsh = len(noccsh)
    nbf = norb = len(bfs)
    if not f:
        f,a,b = get_fab(nclosed,nopen)

    if verbose:
        print "ROHF calculation"
        print "nsh = ",nsh
        print "noccsh = ",noccsh
        print "f = ",f
        print "a_ij: "
        for i in xrange(nsh):
            for j in xrange(i+1):
                print a[i,j],
            print
        print "b_ij: "
        for i in xrange(nsh):
            for j in xrange(i+1):
                print b[i,j],
            print
    enuke = atoms.get_enuke()
    energy = eold = 0.
    for i in xrange(MaxIter):
        Ds = get_os_dens(orbs,f,noccsh)
        Hs = get_os_hams(Ints,Ds)
        orbs = rotion(orbs,h,Hs,f,a,b,noccsh)
        orbe,orbs = ocbse(orbs,h,Hs,f,a,b,noccsh)
        orthogonalize(orbs,S)
        # Compute the energy
        eone = sum(f[ish]*trace2(Ds[ish],h) for ish in xrange(nsh))
        energy = enuke+eone+sum(orbe[:nocc])
        print energy,eone
        if abs(energy-eold) < ConvCriteria: break
        eold = energy
    return energy,orbe,orbs
Пример #8
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
Пример #9
0
def rohf_wag(atoms, noccsh=None, f=None, a=None, b=None, **kwargs):
    """\
    rohf(atoms,noccsh=None,f=None,a=None,b=None,**kwargs):
        Restricted open shell HF driving routine

    atoms      A Molecule object containing the system of interest
    """
    ConvCriteria = kwargs.get('ConvCriteria', settings.ConvergenceCriteria)
    MaxIter = kwargs.get('MaxIter', settings.MaxIter)
    DoAveraging = kwargs.get('DoAveraging', settings.Averaging)
    verbose = kwargs.get('verbose')

    bfs = getbasis(atoms, **kwargs)

    S, h, Ints = getints(bfs, atoms, **kwargs)

    nel = atoms.get_nel()

    orbs = kwargs.get('orbs')
    if orbs is None:
        orbe, orbs = geigh(h, nS)

    nclosed, nopen = atoms.get_closedopen()
    nocc = nopen + nclosed
    if not noccsh: noccsh = get_noccsh(nclosed, nopen)
    nsh = len(noccsh)
    nbf = norb = len(bfs)
    if not f:
        f, a, b = get_fab(nclosed, nopen)

    if verbose:
        print "ROHF calculation"
        print "nsh = ", nsh
        print "noccsh = ", noccsh
        print "f = ", f
        print "a_ij: "
        for i in xrange(nsh):
            for j in xrange(i + 1):
                print a[i, j],
            print
        print "b_ij: "
        for i in xrange(nsh):
            for j in xrange(i + 1):
                print b[i, j],
            print
    enuke = atoms.get_enuke()
    energy = eold = 0.
    for i in xrange(MaxIter):
        Ds = get_os_dens(orbs, f, noccsh)
        Hs = get_os_hams(Ints, Ds)
        orbs = rotion(orbs, h, Hs, f, a, b, noccsh)
        orbe, orbs = ocbse(orbs, h, Hs, f, a, b, noccsh)
        orthogonalize(orbs, S)
        # Compute the energy
        eone = sum(f[ish] * trace2(Ds[ish], h) for ish in xrange(nsh))
        energy = enuke + eone + sum(orbe[:nocc])
        print energy, eone
        if abs(energy - eold) < ConvCriteria: break
        eold = energy
    return energy, orbe, orbs
Пример #10
0
def pyq1_dft(atomtuples=[(2,(0,0,0))],basis = '6-31G**',maxit=10,
             xcname='SVWN'):
    from PyQuante import Ints,settings,Molecule
    from PyQuante.dft import getXC
    from PyQuante.MG2 import MG2 as MolecularGrid
    from PyQuante.LA2 import mkdens,geigh,trace2
    from PyQuante.Ints import getJ
    
    print ("PyQ1 DFT run")
    atoms = Molecule('Pyq1',atomlist=atomtuples)

    bfs = Ints.getbasis(atoms,basis=basis)
    S,h,Ints = Ints.getints(bfs,atoms)

    nclosed,nopen = nel//2,nel%2
    assert nopen==0
    enuke = atoms.get_enuke()

    grid_nrad = settings.DFTGridRadii
    grid_fineness = settings.DFTGridFineness

    gr = MolecularGrid(atoms,grid_nrad,grid_fineness) 
    gr.set_bf_amps(bfs)

    orbe,orbs = geigh(h,S)
    eold = 0

    for i in range(maxit):
        D = mkdens(orbs,0,nclosed)
        gr.setdens(D)

        J = getJ(Ints,D)

        Exc,Vxc = getXC(gr,nel,functional=xcname)

        F = h+2*J+Vxc
        orbe,orbs = geigh(F,S)
        
        Ej = 2*trace2(D,J)
        Eone = 2*trace2(D,h)
        energy = Eone + Ej + Exc + enuke
        
        print (i,energy,Eone,Ej,Exc,enuke)
        if np.isclose(energy,eold):
            break
        eold = energy
    return energy
Пример #11
0
    def update(self, **kwargs):
        from PyQuante.Ints import getJ, getK
        from PyQuante.LA2 import geigh, mkdens
        from PyQuante.rohf import ao2mo
        from PyQuante.hartree_fock import get_energy
        from PyQuante.NumWrap import eigh, matrixmultiply

        if self.orbs is None:
            self.orbe, self.orbs = geigh(self.h, self.S)
        Da = mkdens(self.orbs, 0, self.nalpha)
        Db = mkdens(self.orbs, 0, self.nbeta)

        Ja = getJ(self.ERI, Da)
        Jb = getJ(self.ERI, Db)
        Ka = getK(self.ERI, Da)
        Kb = getK(self.ERI, Db)
        Fa = self.h + Ja + Jb - Ka
        Fb = self.h + Ja + Jb - Kb
        energya = get_energy(self.h, Fa, Da)
        energyb = get_energy(self.h, Fb, Db)
        self.energy = (energya + energyb) / 2 + self.Enuke

        Fa = ao2mo(Fa, self.orbs)
        Fb = ao2mo(Fb, self.orbs)

        # Building the approximate Fock matrices in the MO basis
        F = 0.5 * (Fa + Fb)
        K = Fb - Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0, self.nbeta)
        so = slice(self.nbeta, self.nalpha)
        uo = slice(self.nalpha, self.norbs)
        F[do, do] -= K[do, do]
        F[uo, uo] += K[uo, uo]
        F[do, so] += 0.5 * K[do, so]
        F[so, do] += 0.5 * K[so, do]
        F[so, uo] -= 0.5 * K[so, uo]
        F[uo, so] -= 0.5 * K[uo, so]

        self.orbe, mo_orbs = eigh(F)
        self.orbs = matrixmultiply(self.orbs, mo_orbs)

        return
Пример #12
0
    def update(self,**opts):
        from PyQuante.Ints import getJ,getK
        from PyQuante.LA2 import geigh,mkdens
        from PyQuante.rohf import ao2mo
        from PyQuante.hartree_fock import get_energy
        from PyQuante.NumWrap import eigh,matrixmultiply

        if self.orbs is None:
            self.orbe,self.orbs = geigh(self.h, self.S)
        Da = mkdens(self.orbs,0,self.nalpha)
        Db = mkdens(self.orbs,0,self.nbeta)

        Ja = getJ(self.ERI,Da)
        Jb = getJ(self.ERI,Db)
        Ka = getK(self.ERI,Da)
        Kb = getK(self.ERI,Db)
        Fa = self.h+Ja+Jb-Ka
        Fb = self.h+Ja+Jb-Kb
        energya = get_energy(self.h,Fa,Da)
        energyb = get_energy(self.h,Fb,Db)
        self.energy = (energya+energyb)/2 + self.Enuke

        Fa = ao2mo(Fa,self.orbs)
        Fb = ao2mo(Fb,self.orbs)

        # Building the approximate Fock matrices in the MO basis
        F = 0.5*(Fa+Fb)
        K = Fb-Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0,self.nbeta)
        so = slice(self.nbeta,self.nalpha)
        uo = slice(self.nalpha,self.norbs)
        F[do,do] -= K[do,do]
        F[uo,uo] += K[uo,uo]
        F[do,so] += 0.5*K[do,so]
        F[so,do] += 0.5*K[so,do]
        F[so,uo] -= 0.5*K[so,uo]
        F[uo,so] -= 0.5*K[uo,so]

        self.orbe,mo_orbs = eigh(F)
        self.orbs = matrixmultiply(self.orbs,mo_orbs)
        
        return
Пример #13
0
 def get_energy(self,b):
     self.iter += 1
     self.Hoep = get_Hoep(b,self.H0,self.Gij)
     self.orbe,self.orbs = geigh(self.Hoep,self.S)
     if self.etemp:
         self.D,self.entropy = mkdens_fermi(self.nel,self.orbe,self.orbs,
                                            self.etemp)
     else:
         self.D = mkdens(self.orbs,0,self.nclosed)
         self.entropy=0
     self.F = get_fock(self.D,self.Ints,self.h)
     self.energy = trace2(self.h+self.F,self.D)+self.Enuke + self.entropy
     if self.iter == 1 or self.iter % 10 == 0:
         logging.debug("%4d %10.5f %10.5f" % (self.iter,self.energy,dot(b,b)))
     return self.energy
Пример #14
0
 def solve(self,H,**opts):
     from PyQuante.LA2 import mkdens_spinavg,simx,geigh
     from PyQuante.NumWrap import matrixmultiply,eigh
     if self.first_iteration:
         self.first_iteration = False
         self.orbe,self.orbs = geigh(H,self.S)
     else:
         Ht = simx(H,self.orbs)
         if self.pass_nroots:
             self.orbe,orbs = self.solver(Ht,self.nroots)
         else:
             self.orbe,orbs = self.solver(Ht)
         self.orbs = matrixmultiply(self.orbs,orbs)
     self.D = mkdens_spinavg(self.orbs,self.nclosed,self.nopen)
     self.entropy = 0
     return self.D,self.entropy
Пример #15
0
 def solve(self, H, **kwargs):
     from PyQuante.LA2 import mkdens_spinavg, simx, geigh
     from PyQuante.NumWrap import matrixmultiply, eigh
     if self.first_iteration:
         self.first_iteration = False
         self.orbe, self.orbs = geigh(H, self.S)
     else:
         Ht = simx(H, self.orbs)
         if self.pass_nroots:
             self.orbe, orbs = self.solver(Ht, self.nroots)
         else:
             self.orbe, orbs = self.solver(Ht)
         self.orbs = matrixmultiply(self.orbs, orbs)
     self.D = mkdens_spinavg(self.orbs, self.nclosed, self.nopen)
     self.entropy = 0
     return self.D, self.entropy
Пример #16
0
 def get_energy(self, b):
     self.iter += 1
     self.Hoep = get_Hoep(b, self.H0, self.Gij)
     self.orbe, self.orbs = geigh(self.Hoep, self.S)
     if self.etemp:
         self.D, self.entropy = mkdens_fermi(self.nel, self.orbe, self.orbs,
                                             self.etemp)
     else:
         self.D = mkdens(self.orbs, 0, self.nclosed)
         self.entropy = 0
     self.F = get_fock(self.D, self.Ints, self.h)
     self.energy = trace2(self.h + self.F,
                          self.D) + self.Enuke + self.entropy
     if self.iter == 1 or self.iter % 10 == 0:
         logging.debug("%4d %10.5f %10.5f" %
                       (self.iter, self.energy, dot(b, b)))
     return self.energy
Пример #17
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)
Пример #18
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
Пример #19
0
def pyq1_rohf(atomtuples=[(2, (0, 0, 0))], basis='6-31G**', maxit=10, mult=3):
    from PyQuante import Ints, settings, Molecule
    from PyQuante.hartree_fock import get_energy
    from PyQuante.MG2 import MG2 as MolecularGrid
    from PyQuante.LA2 import mkdens, geigh, trace2, simx
    from PyQuante.Ints import getJ, getK

    print("PyQ1 ROHF run")
    atoms = Molecule('Pyq1', atomlist=atomtuples, multiplicity=mult)

    bfs = Ints.getbasis(atoms, basis=basis)
    S, h, I2e = Ints.getints(bfs, atoms)

    nbf = norbs = len(bfs)
    nel = atoms.get_nel()

    nalpha, nbeta = atoms.get_alphabeta()

    enuke = atoms.get_enuke()
    orbe, orbs = geigh(h, S)
    eold = 0

    for i in range(maxit):
        Da = mkdens(orbs, 0, nalpha)
        Db = mkdens(orbs, 0, nbeta)
        Ja = getJ(I2e, Da)
        Jb = getJ(I2e, Db)
        Ka = getK(I2e, Da)
        Kb = getK(I2e, Db)

        Fa = h + Ja + Jb - Ka
        Fb = h + Ja + Jb - Kb
        energya = get_energy(h, Fa, Da)
        energyb = get_energy(h, Fb, Db)
        eone = (trace2(Da, h) + trace2(Db, h)) / 2
        etwo = (trace2(Da, Fa) + trace2(Db, Fb)) / 2
        energy = (energya + energyb) / 2 + enuke
        print(i, energy, eone, etwo, enuke)
        if abs(energy - eold) < 1e-5: break
        eold = energy

        Fa = simx(Fa, orbs)
        Fb = simx(Fb, orbs)
        # Building the approximate Fock matrices in the MO basis
        F = 0.5 * (Fa + Fb)
        K = Fb - Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0, nbeta)
        so = slice(nbeta, nalpha)
        uo = slice(nalpha, norbs)
        F[do, do] -= K[do, do]
        F[uo, uo] += K[uo, uo]
        F[do, so] += 0.5 * K[do, so]
        F[so, do] += 0.5 * K[so, do]
        F[so, uo] -= 0.5 * K[so, uo]
        F[uo, so] -= 0.5 * K[uo, so]

        orbe, mo_orbs = np.linalg.eigh(F)
        orbs = np.dot(orbs, mo_orbs)
    return energy, orbe, orbs
Пример #20
0
def pyq1_rohf(atomtuples=[(2,(0,0,0))],basis = '6-31G**',maxit=10,mult=3):
    from PyQuante import Ints,settings,Molecule
    from PyQuante.hartree_fock import get_energy
    from PyQuante.MG2 import MG2 as MolecularGrid
    from PyQuante.LA2 import mkdens,geigh,trace2,simx
    from PyQuante.Ints import getJ,getK
    
    print ("PyQ1 ROHF run")
    atoms = Molecule('Pyq1',atomlist=atomtuples,multiplicity=mult)

    bfs = Ints.getbasis(atoms,basis=basis)
    S,h,I2e = Ints.getints(bfs,atoms)

    nbf = norbs = len(bfs)
    nel = atoms.get_nel()

    nalpha,nbeta = atoms.get_alphabeta()

    enuke = atoms.get_enuke()
    orbe,orbs = geigh(h,S)
    eold = 0

    for i in range(maxit):
        Da = mkdens(orbs,0,nalpha)
        Db = mkdens(orbs,0,nbeta)
        Ja = getJ(I2e,Da)
        Jb = getJ(I2e,Db)
        Ka = getK(I2e,Da)
        Kb = getK(I2e,Db)

        Fa = h+Ja+Jb-Ka
        Fb = h+Ja+Jb-Kb
        energya = get_energy(h,Fa,Da)
        energyb = get_energy(h,Fb,Db)
        eone = (trace2(Da,h) + trace2(Db,h))/2
        etwo = (trace2(Da,Fa) + trace2(Db,Fb))/2
        energy = (energya+energyb)/2 + enuke
        print (i,energy,eone,etwo,enuke)
        if abs(energy-eold) < 1e-5: break
        eold = energy

        Fa = simx(Fa,orbs)
        Fb = simx(Fb,orbs)
        # Building the approximate Fock matrices in the MO basis
        F = 0.5*(Fa+Fb)
        K = Fb-Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0,nbeta)
        so = slice(nbeta,nalpha)
        uo = slice(nalpha,norbs)
        F[do,do] -= K[do,do]
        F[uo,uo] += K[uo,uo]
        F[do,so] += 0.5*K[do,so]
        F[so,do] += 0.5*K[so,do]
        F[so,uo] -= 0.5*K[so,uo]
        F[uo,so] -= 0.5*K[uo,so]

        orbe,mo_orbs = np.linalg.eigh(F)
        orbs = np.dot(orbs,mo_orbs)
    return energy,orbe,orbs
Пример #21
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
Пример #22
0
 def solve(self,H,**opts):
     from PyQuante.LA2 import geigh,mkdens_spinavg
     self.orbe,self.orbs = geigh(H,self.S)
     self.D = mkdens_spinavg(self.orbs,self.nclosed,self.nopen)
     self.entropy = 0
     return self.D,self.entropy
Пример #23
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)
Пример #24
0
 def solve(self, H, **kwargs):
     from PyQuante.LA2 import geigh, mkdens_spinavg
     self.orbe, self.orbs = geigh(H, self.S)
     self.D = mkdens_spinavg(self.orbs, self.nclosed, self.nopen)
     self.entropy = 0
     return self.D, self.entropy
Пример #25
0
def rohf(atoms,**opts):
    """\
    rohf(atoms,**opts) - Restriced Open Shell Hartree Fock
    atoms       A Molecule object containing the molecule
    """

    ConvCriteria = opts.get('ConvCriteria',1e-5)
    MaxIter = opts.get('MaxIter',40)
    DoAveraging = opts.get('DoAveraging',True)
    averaging = opts.get('averaging',0.95)
    verbose = opts.get('verbose',True)

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

    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()
    S,h,Ints = getints(bfs,atoms)

    orbs = opts.get('orbs',None)
    if orbs is None:
        orbe,orbs = geigh(h,S)
    norbs = nbf

    enuke = atoms.get_enuke()
    eold = 0.

    if verbose: print "ROHF calculation on %s" % atoms.name
    if verbose: print "Nbf = %d" % nbf
    if verbose: print "Nalpha = %d" % nalpha
    if verbose: print "Nbeta = %d" % nbeta
    if verbose: print "Averaging = %s" % DoAveraging
    print "Optimization of HF orbitals"

    for i in xrange(MaxIter):
        if verbose: print "SCF Iteration:",i,"Starting Energy:",eold
        Da = mkdens(orbs,0,nalpha)
        Db = mkdens(orbs,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
        energya = get_energy(h,Fa,Da)
        energyb = get_energy(h,Fb,Db)
        eone = (trace2(Da,h) + trace2(Db,h))/2
        etwo = (trace2(Da,Fa) + trace2(Db,Fb))/2
        energy = (energya+energyb)/2 + enuke
        print i,energy,eone,etwo,enuke
        if abs(energy-eold) < ConvCriteria: break
        eold = energy

        Fa = ao2mo(Fa,orbs)
        Fb = ao2mo(Fb,orbs)

        # Building the approximate Fock matrices in the MO basis
        F = 0.5*(Fa+Fb)
        K = Fb-Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0,nbeta)
        so = slice(nbeta,nalpha)
        uo = slice(nalpha,norbs)
        F[do,do] -= K[do,do]
        F[uo,uo] += K[uo,uo]
        F[do,so] += 0.5*K[do,so]
        F[so,do] += 0.5*K[so,do]
        F[so,uo] -= 0.5*K[so,uo]
        F[uo,so] -= 0.5*K[uo,so]

        orbe,mo_orbs = eigh(F)
        orbs = matrixmultiply(orbs,mo_orbs)
        
    if verbose:
        print "Final ROHF energy for system %s is %f" % (atoms.name,energy)
    return energy,orbe,orbs
Пример #26
0
from PyQuante.TestMolecules import h2
from PyQuante.LA2 import geigh,mkdens
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"