Example #1
0
def lanczos_minmax(F,S=None,**kwargs):
    "Estimate the min/max evals of F using a few iters of Lanczos"
    doS = S is not None
    niter = kwargs.get('niter',8)
    N = F.shape[0]
    niter = min(N,niter)
    x = zeros(N,'d')
    x[0] = 1
    q = x
    avals = []
    bvals = []
    if doS:
        r = matrixmultiply(S,q)
    else:
        r = q
    beta = sqrt(matrixmultiply(q,r))
    wold = zeros(N,'d')
    for i in xrange(niter):
        w = r/beta
        v = q/beta
        r = matrixmultiply(F,v)
        r = r - wold*beta
        alpha = matrixmultiply(v,r)
        avals.append(alpha)
        r = r-w*alpha
        if doS:
            q = solve(S,r)
        else:
            q = r
        beta = sqrt(matrixmultiply(q,r))
        bvals.append(beta)
        wold = w
    E,V = eigh(tridiagmat(avals,bvals))
    return min(E),max(E)
Example #2
0
def lanczos_minmax(F, S=None, **kwargs):
    "Estimate the min/max evals of F using a few iters of Lanczos"
    doS = S is not None
    niter = kwargs.get('niter', settings.DMPLanczosMinmaxIters)
    N = F.shape[0]
    niter = min(N, niter)
    x = zeros(N, 'd')
    x[0] = 1
    q = x
    avals = []
    bvals = []
    if doS:
        r = matrixmultiply(S, q)
    else:
        r = q
    beta = sqrt(matrixmultiply(q, r))
    wold = zeros(N, 'd')
    for i in xrange(niter):
        w = r / beta
        v = q / beta
        r = matrixmultiply(F, v)
        r = r - wold * beta
        alpha = matrixmultiply(v, r)
        avals.append(alpha)
        r = r - w * alpha
        if doS:
            q = solve(S, r)
        else:
            q = r
        beta = sqrt(matrixmultiply(q, r))
        bvals.append(beta)
        wold = w
    E, V = eigh(tridiagmat(avals, bvals))
    return min(E), max(E)
Example #3
0
 def update(self):
     D2 = matrixmultiply(self.D,self.D)
     D3 = matrixmultiply(self.D,D2)
     cn = trace(D2-D3)/trace(self.D-D2)
     if cn < 0.5:
         self.D = ((1.0-2.0*cn)*self.D+(1.0+cn)*D2-D3)/(1.0-cn)
     else:
         self.D = ((1+cn)*D2-D3)/cn
     return
Example #4
0
 def update(self):
     D2 = matrixmultiply(self.D, self.D)
     D3 = matrixmultiply(self.D, D2)
     cn = trace(D2 - D3) / trace(self.D - D2)
     if cn < 0.5:
         self.D = ((1.0 - 2.0 * cn) * self.D +
                   (1.0 + cn) * D2 - D3) / (1.0 - cn)
     else:
         self.D = ((1 + cn) * D2 - D3) / cn
     return
Example #5
0
def get_exx_gradient(b, nbf, nel, nocc, ETemp, Enuke, S, h, Ints, H0, Gij,
                     **opts):
    """Computes the gradient for the OEP/HF functional.

    return_flag    0   Just return gradient
                   1   Return energy,gradient 
                   2   Return energy,gradient,orbe,orbs 
    """
    # Dump the gradient every 10 steps so we can restart...
    global gradcall
    gradcall += 1
    #if gradcall % 5 == 0: logging.debug("B vector:\n%s" % b)

    # Form the new potential and the new orbitals
    energy, orbe, orbs, F = get_exx_energy(b,
                                           nbf,
                                           nel,
                                           nocc,
                                           ETemp,
                                           Enuke,
                                           S,
                                           h,
                                           Ints,
                                           H0,
                                           Gij,
                                           return_flag=2)

    Fmo = matrixmultiply(transpose(orbs), matrixmultiply(F, orbs))

    norb = nbf
    bp = zeros(nbf, 'd')  # dE/db

    for g in xrange(nbf):
        # Transform Gij[g] to MOs. This is done over the whole
        #  space rather than just the parts we need. I can speed
        #  this up later by only forming the i,a elements required
        Gmo = matrixmultiply(transpose(orbs), matrixmultiply(Gij[g], orbs))

        # Now sum the appropriate terms to get the b gradient
        for i in xrange(nocc):
            for a in xrange(nocc, norb):
                bp[g] = bp[g] + Fmo[i, a] * Gmo[i, a] / (orbe[i] - orbe[a])

    #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
    return_flag = opts.get('return_flag', 0)
    if return_flag == 1:
        return energy, bp
    elif return_flag == 2:
        return energy, bp, orbe, orbs
    return bp
Example #6
0
    def getF(self, F, D):
        n, m = F.shape
        err = matrixmultiply(F,matrixmultiply(D,self.S)) -\
              matrixmultiply(self.S,matrixmultiply(D,F))
        err = ravel(err)
        maxerr = max(abs(err))
        self.maxerr = maxerr

        if maxerr < self.errcutoff and not self.started:
            if VERBOSE: print "Starting DIIS: Max Err = ", maxerr
            self.started = 1

        if not self.started:
            # Do simple averaging until DIIS starts
            if self.Fold != None:
                Freturn = 0.5 * F + 0.5 * self.Fold
                self.Fold = F
            else:
                self.Fold = F
                Freturn = F
            return Freturn

        self.Fs.append(F)
        self.Errs.append(err)
        nit = len(self.Errs)
        a = zeros((nit + 1, nit + 1), 'd')
        b = zeros(nit + 1, 'd')
        for i in xrange(nit):
            for j in xrange(nit):
                a[i, j] = dot(self.Errs[i], self.Errs[j])
        for i in xrange(nit):
            a[nit, i] = a[i, nit] = -1.0
            b[i] = 0
        #mtx2file(a,'A%d.dat' % nit)
        a[nit, nit] = 0
        b[nit] = -1.0

        # The try loop makes this a bit more stable.
        #  Thanks to John Kendrick!
        try:
            c = solve(a, b)
        except:
            self.Fold = F
            return F

        F = zeros((n, m), 'd')
        for i in xrange(nit):
            F += c[i] * self.Fs[i]
        return F
Example #7
0
    def getF(self, F, D):
        n, m = F.shape
        err = matrixmultiply(F, matrixmultiply(D, self.S)) - matrixmultiply(self.S, matrixmultiply(D, F))
        err = ravel(err)
        maxerr = max(abs(err))
        self.maxerr = maxerr

        if maxerr < self.errcutoff and not self.started:
            if VERBOSE:
                print "Starting DIIS: Max Err = ", maxerr
            self.started = 1

        if not self.started:
            # Do simple averaging until DIIS starts
            if self.Fold != None:
                Freturn = 0.5 * F + 0.5 * self.Fold
                self.Fold = F
            else:
                self.Fold = F
                Freturn = F
            return Freturn

        self.Fs.append(F)
        self.Errs.append(err)
        nit = len(self.Errs)
        a = zeros((nit + 1, nit + 1), "d")
        b = zeros(nit + 1, "d")
        for i in range(nit):
            for j in range(nit):
                a[i, j] = dot(self.Errs[i], self.Errs[j])
        for i in range(nit):
            a[nit, i] = a[i, nit] = -1.0
            b[i] = 0
        # mtx2file(a,'A%d.dat' % nit)
        a[nit, nit] = 0
        b[nit] = -1.0

        # The try loop makes this a bit more stable.
        #  Thanks to John Kendrick!
        try:
            c = solve(a, b)
        except:
            self.Fold = F
            return F

        F = zeros((n, m), "d")
        for i in range(nit):
            F += c[i] * self.Fs[i]
        return F
Example #8
0
 def update(self):
     D2 = matrixmultiply(self.D, self.D)
     Df = matrixmultiply(D2, 4 * self.D - 3 * D2)
     trf = trace(Df)
     Dp = self.I - self.D
     Dp2 = matrixmultiply(Dp, Dp)
     Dg = matrixmultiply(D2, Dp2)
     trg = trace(Dg)
     gamma = (self.Ne - trf) / trg
     if gamma > 2:
         self.D = 2 * self.D - D2
     elif gamma < 0:
         self.D = D2
     else:
         self.D = Df - gamma * Dg
     return
Example #9
0
 def update(self):
     D2 = matrixmultiply(self.DS, self.D)
     if self.Ne_curr < self.Ne:
         self.D = 2 * self.D - D2
     else:
         self.D = D2
     return
Example #10
0
 def update(self):
     D2 = matrixmultiply(self.D,self.D)
     Df = matrixmultiply(D2,4*self.D-3*D2)
     trf = trace(Df)
     Dp = self.I-self.D
     Dp2 = matrixmultiply(Dp,Dp)
     Dg = matrixmultiply(D2,Dp2)
     trg = trace(Dg)
     gamma = (self.Ne-trf)/trg
     if gamma > 2:
         self.D = 2*self.D-D2
     elif gamma < 0:
         self.D = D2
     else:
         self.D = Df-gamma*Dg
     return
Example #11
0
 def update(self):
     D2 = matrixmultiply(self.DS,self.D)
     if self.Ne_curr < self.Ne:
         self.D = 2*self.D-D2
     else:
         self.D = D2
     return
Example #12
0
    def getF(self, F, D):
        n, m = F.shape
        err = matrixmultiply(F,matrixmultiply(D,self.S)) -\
              matrixmultiply(self.S,matrixmultiply(D,F))
        err = ravel(err)
        maxerr = max(abs(err))

        if maxerr < self.errcutoff and not self.started:
            if VERBOSE: print "Starting DIIS: Max Err = ", maxerr
            self.started = 1

        if not self.started:
            # Do simple averaging until DIIS starts
            if self.Fold:
                Freturn = 0.5 * F + 0.5 * self.Fold
            else:
                Freturn = F
            self.Fold = F
            return Freturn
        elif not self.errold:
            Freturn = 0.5 * F + 0.5 * self.Fold
            self.errold = err
            return Freturn

        a = zeros((3, 3), 'd')
        b = zeros(3, 'd')
        a[0, 0] = dot(self.errold, self.errold)
        a[1, 0] = dot(self.errold, err)
        a[0, 1] = a[1, 0]
        a[1, 1] = dot(err, err)
        a[:, 2] = -1
        a[2, :] = -1
        a[2, 2] = 0
        b[2] = -1
        c = solve(a, b)

        # Handle a few special cases:
        alpha = c[1]
        print alpha, c
        #if alpha < 0: alpha = 0
        #if alpha > 1: alpha = 1

        F = (1 - alpha) * self.Fold + alpha * F
        self.errold = err
        self.Fold = F
        return F
Example #13
0
def geigh(H, A, **opts):
    """\
    Generalized eigenproblem using a symmetric matrix H.
    """
    X = SymOrthCutoff(A)
    val, vec = eigh(simx(H, X))
    vec = matrixmultiply(X, vec)
    return val, vec
Example #14
0
    def getF(self, F, D):
        n, m = F.shape
        err = matrixmultiply(F, matrixmultiply(D, self.S)) - matrixmultiply(self.S, matrixmultiply(D, F))
        err = ravel(err)
        maxerr = max(abs(err))

        if maxerr < self.errcutoff and not self.started:
            if VERBOSE:
                print "Starting DIIS: Max Err = ", maxerr
            self.started = 1

        if not self.started:
            # Do simple averaging until DIIS starts
            if self.Fold:
                Freturn = 0.5 * F + 0.5 * self.Fold
            else:
                Freturn = F
            self.Fold = F
            return Freturn
        elif not self.errold:
            Freturn = 0.5 * F + 0.5 * self.Fold
            self.errold = err
            return Freturn

        a = zeros((3, 3), "d")
        b = zeros(3, "d")
        a[0, 0] = dot(self.errold, self.errold)
        a[1, 0] = dot(self.errold, err)
        a[0, 1] = a[1, 0]
        a[1, 1] = dot(err, err)
        a[:, 2] = -1
        a[2, :] = -1
        a[2, 2] = 0
        b[2] = -1
        c = solve(a, b)

        # Handle a few special cases:
        alpha = c[1]
        print alpha, c
        # if alpha < 0: alpha = 0
        # if alpha > 1: alpha = 1

        F = (1 - alpha) * self.Fold + alpha * F
        self.errold = err
        self.Fold = F
        return F
Example #15
0
def geigh(H,A,**opts):
    """\
    Generalized eigenproblem using a symmetric matrix H.
    """
    X = SymOrthCutoff(A)
    val,vec = eigh(simx(H,X))
    vec = matrixmultiply(X,vec)
    return val,vec
Example #16
0
def rotion(orbs,h,Hs,f,a,b,noccsh):
    nsh = len(noccsh)
    nocc = sum(noccsh)
    if nsh == 1: return orbs # No effect for closed shell systems
    rot = get_rot(h,Hs,f,a,b,noccsh)
    print "Rotation matrix:\n",rot
    erot = expmat(rot)
    print "Exp rotation matrix:\n",erot
    T = matrixmultiply(orbs[:,:nocc],erot)
    orbs[:,:nocc] = T
    return orbs
Example #17
0
def davidson(A, nroots, **kwargs):
    etol = kwargs.get('etol', settings.DavidsonEvecTolerance
                      )  # tolerance on the eigenval convergence
    ntol = kwargs.get('ntol', settings.DavidsonNormTolerance
                      )  # tolerance on the vector norms for addn
    n, m = A.shape
    ninit = max(nroots, 2)
    B = zeros((n, ninit), 'd')
    for i in xrange(ninit):
        B[i, i] = 1.

    nc = 0  # number of converged roots
    eigold = 1e10
    for iter in xrange(n):
        if nc >= nroots: break
        D = matrixmultiply(A, B)
        S = matrixmultiply(transpose(B), D)
        m = len(S)
        eval, evec = eigh(S)

        bnew = zeros(n, 'd')
        for i in xrange(m):
            bnew += evec[i, nc] * (D[:, i] - eval[nc] * B[:, i])

        for i in xrange(n):
            denom = max(eval[nc] - A[i, i],
                        1e-8)  # Maximum amplification factor
            bnew[i] /= denom

        norm = orthog(bnew, B)
        bnew = bnew / norm

        if abs(eval[nc] - eigold) < etol:
            nc += 1
        eigold = eval[nc]
        if norm > ntol: B = appendColumn(B, bnew)

    E = eval[:nroots]
    nv = len(evec)
    V = matrixmultiply(B[:, :nv], evec)
    return E, V
Example #18
0
 def update(self):
     Ne_curr = trace(self.D)
     D2 = matrixmultiply(self.D, self.D)
     Ne2 = trace(D2)
     self.Ne_curr = Ne_curr
     # Anders claims this works better; I didn't see a difference
     #if abs(2*Ne_curr-Ne2-self.Ne) < abs(Ne2-self.Ne):
     if Ne_curr < self.Ne:
         self.D = 2 * self.D - D2
     else:
         self.D = D2
     return
Example #19
0
 def update(self):
     Ne_curr = trace(self.D)
     D2 = matrixmultiply(self.D,self.D)
     Ne2 = trace(D2)
     self.Ne_curr = Ne_curr
     # Anders claims this works better; I didn't see a difference
     #if abs(2*Ne_curr-Ne2-self.Ne) < abs(Ne2-self.Ne):
     if Ne_curr < self.Ne:
         self.D = 2*self.D-D2
     else:
         self.D = D2
     return
Example #20
0
def get_exx_gradient(b,nbf,nel,nocc,ETemp,Enuke,S,h,Ints,H0,Gij,**opts):
    """Computes the gradient for the OEP/HF functional.

    return_flag    0   Just return gradient
                   1   Return energy,gradient 
                   2   Return energy,gradient,orbe,orbs 
    """
    # Dump the gradient every 10 steps so we can restart...
    global gradcall
    gradcall += 1
    #if gradcall % 5 == 0: logging.debug("B vector:\n%s" % b)

    # Form the new potential and the new orbitals
    energy,orbe,orbs,F = get_exx_energy(b,nbf,nel,nocc,ETemp,Enuke,
                                        S,h,Ints,H0,Gij,return_flag=2)

    Fmo = matrixmultiply(transpose(orbs),matrixmultiply(F,orbs))

    norb = nbf
    bp = zeros(nbf,'d') # dE/db

    for g in range(nbf):
        # Transform Gij[g] to MOs. This is done over the whole
        #  space rather than just the parts we need. I can speed
        #  this up later by only forming the i,a elements required
        Gmo = matrixmultiply(transpose(orbs),matrixmultiply(Gij[g],orbs))

        # Now sum the appropriate terms to get the b gradient
        for i in range(nocc):
            for a in range(nocc,norb):
                bp[g] = bp[g] + Fmo[i,a]*Gmo[i,a]/(orbe[i]-orbe[a])

    #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
    return_flag = opts.get('return_flag',0)
    if return_flag == 1:
        return energy,bp
    elif return_flag == 2:
        return energy,bp,orbe,orbs
    return bp
Example #21
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
Example #22
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
Example #23
0
def expmat(A,**kwargs):
    nmax = kwargs.get('nmax',12)
    cut = kwargs.get('cut',1e-8)
    E = identity(A.shape[0],'d')
    D = E
    for i in xrange(1,nmax):
        D = matrixmultiply(D,A)/i
        E += D
        maxel = D.max()
        if abs(maxel) < cut:
            break
    else:
        print "Warning: expmat unconverged after %d iters: %g" % (nmax,maxel)
    return E
Example #24
0
def davidson(A,nroots,**kwargs):
    etol = kwargs.get('etol',settings.DavidsonEvecTolerance) # tolerance on the eigenval convergence
    ntol = kwargs.get('ntol',settings.DavidsonNormTolerance) # tolerance on the vector norms for addn
    n,m = A.shape
    ninit = max(nroots,2)
    B = zeros((n,ninit),'d')
    for i in xrange(ninit): B[i,i] = 1.

    nc = 0 # number of converged roots
    eigold = 1e10
    for iter in xrange(n):
        if nc >= nroots: break
        D = matrixmultiply(A,B)
        S = matrixmultiply(transpose(B),D)
        m = len(S)
        eval,evec = eigh(S)

        bnew = zeros(n,'d')
        for i in xrange(m):
            bnew += evec[i,nc]*(D[:,i] - eval[nc]*B[:,i])

        for i in xrange(n):
            denom = max(eval[nc]-A[i,i],1e-8) # Maximum amplification factor
            bnew[i] /= denom

        norm = orthog(bnew,B)
        bnew = bnew / norm

        if abs(eval[nc]-eigold) < etol:
            nc += 1
        eigold = eval[nc]
        if norm > ntol: B = appendColumn(B,bnew)

    E = eval[:nroots]
    nv = len(evec)
    V = matrixmultiply(B[:,:nv],evec)
    return E,V
Example #25
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
Example #26
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
Example #27
0
def ocbse(orbs,h,Hs,f,a,b,noccsh):
    # Need to write this so that we don't need the orbs 3 times!
    nsh = len(noccsh)
    nbf = norb = h.shape[0]
    orbe = zeros(norb,'d')
    for ish in xrange(nsh):
        orbs_in_shell = get_orbs_in_shell(ish,noccsh,norb)
        F = get_os_fock(ish,nsh,f,a,b,h,Hs)
        # form the orbital space of all of the orbs in ish plus the virts
        T = orbs.take(orbs_in_shell,1)
        #print "take worked? ",(T==get_orbs(orbs,orbs_in_shell)).all()
        # Transform to MO space
        Fmo = ao2mo(F,T)
        mo_orbe,mo_orbs = eigh(Fmo)
        T = matrixmultiply(T,mo_orbs)
        # Insert orbital energies into the right place
        update_orbe(orbs_in_shell,orbe,mo_orbe)
        update_orbs(orbs_in_shell,orbs,T)
    return orbe,orbs
Example #28
0
 def converged(self):
     self.DS = matrixmultiply(self.D, self.S)
     self.Ne_curr = trace(self.DS)
     return abs(self.Ne_curr - self.Ne) < self.tol
Example #29
0
def mo2ao(M,C,S):
    SC = matrixmultiply(S,C)
    return simx(M,SC,'t')
Example #30
0
 def update(self):
     D2 = matrixmultiply(self.D, self.D)
     self.D = 3 * D2 - 2 * matrixmultiply(self.D, D2)
     return
Example #31
0
 def update(self):
     D2 = matrixmultiply(self.D,self.D)
     self.D = 3*D2-2*matrixmultiply(self.D,D2)
     return
Example #32
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
Example #33
0
def H2O_Molecule(tst,info,auX,auZ):
    H2O = Molecule('H2O',
           [('O',  ( 0.0,  0.0, 0.0)),
            ('H',  ( auX,  0.0, auZ)),
            ('H',  (-auX,  0.0, auZ))],
           units='Bohr')

    # Get a better energy estimate
    if dft:
        print "# info=%s A.U.=(%g,%g) " % (info,auX,auZ)
        edft,orbe2,orbs2 = dft(H2O,functional='SVWN')

    bfs= getbasis(H2O,basis_data=basis_data) 
    #S is overlap of 2 basis funcs 
    #h is (kinetic+nucl) 1 body term 
    #ints is 2 body terms 
    S,h,ints=getints(bfs,H2O) 


    #enhf is the Hartee-Fock energy 
    #orbe is the orbital energies 
    #orbs is the orbital overlaps 
    enhf,orbe,orbs=rhf(H2O,integrals=(S,h,ints))
    enuke   = Molecule.get_enuke(H2O)

    # print "orbe=%d" % len(orbe)

    temp = matrixmultiply(h,orbs) 
    hmol = matrixmultiply(transpose(orbs),temp) 

    MOInts = TransformInts(ints,orbs) 

    if single:
         print "h = \n",h
         print "S = \n",S
         print "ints = \n",ints
         print "orbe = \n",orbe
         print "orbs = \n",orbs
         print ""
         print "Index 0: 1 or 2 in the paper, Index 1: 3 or 4 in the paper (for pqrs)"
         print ""
         print "hmol = \n",hmol
         print "MOInts:"
         print "I,J,K,L = PQRS order: Cre1,Cre2,Ann1,Ann2"

    if 1:
        print "tst=%d info=%s nuc=%.9f Ehf=%.9f" % (tst,info,enuke,enhf),

    cntOrbs    = 0
    maxOrb    = 0
    npts    = len(hmol[:])
    for i in xrange(npts):
        for j in range(i,npts):
            if abs(hmol[i,j]) > 1.0e-7:
                print "%d,%d=%.9f" % (i,j,hmol[i,j]),
        cntOrbs += 1
        if i > maxOrb: maxOrb = i
        if j > maxOrb: maxOrb = j

    nbf,nmo    = orbs.shape
    mos        = range(nmo)
    for i in mos:
        for j in xrange(i+1):
            ij      = i*(i+1)/2+j
            for k in mos:
                for l in xrange(k+1):
                    kl = k*(k+1)/2+l
                    if ij >= kl:
                        ijkl = ijkl2intindex(i,j,k,l)
                        if abs(MOInts[ijkl]) > 1.0e-7:
                            print "%d,%d,%d,%d=%.9f" % (l,i,j,k,MOInts[ijkl]),
            cntOrbs += 1
            if i > maxOrb: maxOrb = i
            if j > maxOrb: maxOrb = j
    print ""

    return (maxOrb,cntOrbs)
Example #34
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)
Example #35
0
 def converged(self):
     self.DS = matrixmultiply(self.D,self.S)
     self.Ne_curr = trace(self.DS)
     return abs(self.Ne_curr - self.Ne) < self.tol
Example #36
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
Example #37
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
Example #38
0
 def urotate(self,U):
     "Rotate molecule by the unitary matrix U"
     from PyQuante.NumWrap import matrixmultiply
     #self.r = matrixmultiply(self.r,U)
     self.r = matrixmultiply(U,self.r)
     return
Example #39
0
 def urotate(self, U):
     "Rotate molecule by the unitary matrix U"
     from PyQuante.NumWrap import matrixmultiply
     #self.r = matrixmultiply(self.r,U)
     self.r = matrixmultiply(U, self.r)
     return
Example #40
0
def H2O_Molecule(tst, info, auX, auZ):
    H2O = Molecule('H2O', [('O', (0.0, 0.0, 0.0)), ('H', (auX, 0.0, auZ)),
                           ('H', (-auX, 0.0, auZ))],
                   units='Bohr')

    # Get a better energy estimate
    if dft:
        print "# info=%s A.U.=(%g,%g) " % (info, auX, auZ)
        edft, orbe2, orbs2 = dft(H2O, functional='SVWN')

    bfs = getbasis(H2O, basis_data=basis_data)
    #S is overlap of 2 basis funcs
    #h is (kinetic+nucl) 1 body term
    #ints is 2 body terms
    S, h, ints = getints(bfs, H2O)

    #enhf is the Hartee-Fock energy
    #orbe is the orbital energies
    #orbs is the orbital overlaps
    enhf, orbe, orbs = rhf(H2O, integrals=(S, h, ints))
    enuke = Molecule.get_enuke(H2O)

    # print "orbe=%d" % len(orbe)

    temp = matrixmultiply(h, orbs)
    hmol = matrixmultiply(transpose(orbs), temp)

    MOInts = TransformInts(ints, orbs)

    if single:
        print "h = \n", h
        print "S = \n", S
        print "ints = \n", ints
        print "orbe = \n", orbe
        print "orbs = \n", orbs
        print ""
        print "Index 0: 1 or 2 in the paper, Index 1: 3 or 4 in the paper (for pqrs)"
        print ""
        print "hmol = \n", hmol
        print "MOInts:"
        print "I,J,K,L = PQRS order: Cre1,Cre2,Ann1,Ann2"

    if 1:
        print "tst=%d info=%s nuc=%.9f Ehf=%.9f" % (tst, info, enuke, enhf),

    cntOrbs = 0
    maxOrb = 0
    npts = len(hmol[:])
    for i in xrange(npts):
        for j in range(i, npts):
            if abs(hmol[i, j]) > 1.0e-7:
                print "%d,%d=%.9f" % (i, j, hmol[i, j]),
        cntOrbs += 1
        if i > maxOrb: maxOrb = i
        if j > maxOrb: maxOrb = j

    nbf, nmo = orbs.shape
    mos = range(nmo)
    for i in mos:
        for j in xrange(i + 1):
            ij = i * (i + 1) / 2 + j
            for k in mos:
                for l in xrange(k + 1):
                    kl = k * (k + 1) / 2 + l
                    if ij >= kl:
                        ijkl = ijkl2intindex(i, j, k, l)
                        if abs(MOInts[ijkl]) > 1.0e-7:
                            print "%d,%d,%d,%d=%.9f" % (l, i, j, k,
                                                        MOInts[ijkl]),
            cntOrbs += 1
            if i > maxOrb: maxOrb = i
            if j > maxOrb: maxOrb = j
    print ""

    return (maxOrb, cntOrbs)
Example #41
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)
Example #42
0
#calculate two electron integrals
elecRepulsion = Ints.get2ints(basisSet)

#Section 3############################
#Calculate Transformation Matrix X from Overlap matrix
X = linalg.SymOrth(S)

#Section 4############################
#guess density matrix from Core Hamiltonian

#diagnolize Hamiltonian and transform hamiltonian to get guess orbitals
eVal, eVec = eigh(linalg.simx(Hcore, X))

#transform orbitals from AO to MO basis
orbitals = matrixmultiply(Hcore, X)

#guess Density from guess orbitals and number of closed electron shells
D = HF.mkdens(orbitals, 0, molecule.get_closedopen()[0])

#Start of SCF Procedures############################
#init variables for SCF
cycle = 0
energy = [float("-inf")]

while (cycle < maxCycle):
    #while max. number of cycles not reached
    #continues with SCF iterations

    #Start of SCF Procedures############################