Пример #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', 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)
Пример #2
0
 def __init__(self, solver):
     # Solver is a pointer to a HF or a DFT calculation that has
     #  already converged
     self.solver = solver
     self.bfs = self.solver.bfs
     self.nbf = len(self.bfs)
     self.S = self.solver.S
     self.h = self.solver.h
     self.Ints = self.solver.Ints
     self.molecule = self.solver.molecule
     self.nel = self.molecule.get_nel()
     self.nclosed, self.nopen = self.molecule.get_closedopen()
     self.Enuke = self.molecule.get_enuke()
     self.norb = self.nbf
     self.orbs = self.solver.orbs
     self.orbe = self.solver.orbe
     self.Gij = []
     for g in xrange(self.nbf):
         gmat = zeros((self.nbf, self.nbf), 'd')
         self.Gij.append(gmat)
         gbf = self.bfs[g]
         for i in xrange(self.nbf):
             ibf = self.bfs[i]
             for j in xrange(i + 1):
                 jbf = self.bfs[j]
                 gij = three_center(ibf, gbf, jbf)
                 gmat[i, j] = gij
                 gmat[j, i] = gij
     D0 = mkdens(self.orbs, 0, self.nclosed)
     J0 = getJ(self.Ints, D0)
     Vfa = (2.0 * (self.nel - 1.0) / self.nel) * J0
     self.H0 = self.h + Vfa
     self.b = zeros(self.nbf, 'd')
     return
Пример #3
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)
Пример #4
0
 def __init__(self,solver):
     # Solver is a pointer to a HF or a DFT calculation that has
     #  already converged
     self.solver = solver
     self.bfs = self.solver.bfs
     self.nbf = len(self.bfs)
     self.S = self.solver.S
     self.h = self.solver.h
     self.Ints = self.solver.Ints
     self.molecule = self.solver.molecule
     self.nel = self.molecule.get_nel()
     self.nclosed, self.nopen = self.molecule.get_closedopen()
     self.Enuke = self.molecule.get_enuke()
     self.norb = self.nbf
     self.orbs = self.solver.orbs
     self.orbe = self.solver.orbe
     self.Gij = []
     for g in range(self.nbf):
         gmat = zeros((self.nbf,self.nbf),'d')
         self.Gij.append(gmat)
         gbf = self.bfs[g]
         for i in range(self.nbf):
             ibf = self.bfs[i]
             for j in range(i+1):
                 jbf = self.bfs[j]
                 gij = three_center(ibf,gbf,jbf)
                 gmat[i,j] = gij
                 gmat[j,i] = gij
     D0 = mkdens(self.orbs,0,self.nclosed)
     J0 = getJ(self.Ints,D0)
     Vfa = (2.0*(self.nel-1.0)/self.nel)*J0
     self.H0 = self.h + Vfa
     self.b = zeros(self.nbf,'d')
     return
Пример #5
0
def CPBE(dens,gamma):
    "PBE Correlation Functional"
    npts = len(dens)
    ec = zeros(npts,'d')
    vc = zeros(npts,'d')
    for i in xrange(npts):
        rho = 0.5*float(dens[i]) # Density of the alpha spin
        gam = 0.25*gamma[i]
        ecab,vca,vcb = cpbe(rho,rho,gam,gam,gam)
        ec[i] = ecab
        vc[i] = vca
    return ec,vc
Пример #6
0
def XPBE(dens,gamma):
    "PBE Exchange Functional"
    npts = len(dens)
    assert len(gamma) == npts
    ex = zeros(npts,'d')
    vx = zeros(npts,'d')
    for i in xrange(npts):
        rho = 0.5*float(dens[i])  # Density of the alpha spin
        gam = 0.25*gamma[i]
        exa,vxa = xpbe(rho,gam)
        ex[i] = 2*exa
        vx[i] = vxa
    return ex,vx
Пример #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 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
Пример #8
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
Пример #9
0
def get1ints(bfs,atoms):
    "Form the overlap S and h=t+vN one-electron Hamiltonian matrices"
    nbf = len(bfs)
    S = zeros((nbf,nbf),'d')
    h = zeros((nbf,nbf),'d')

    for i in xrange(nbf):
        bfi = bfs[i]
        for j in xrange(nbf):
            bfj = bfs[j]
            S[i,j] = bfi.overlap(bfj)
            h[i,j] = bfi.kinetic(bfj)
            for atom in atoms:
                h[i,j] = h[i,j] + atom.Z*bfi.nuclear(bfj,atom.pos())
    return S,h
Пример #10
0
    def get_gradient(self, b):
        energy = self.get_energy(b)
        Fmoa = simx(self.Fa, self.orbsa)
        Fmob = simx(self.Fb, self.orbsb)

        bp = zeros(2 * self.nbf, 'd')

        for g in xrange(self.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 = simx(self.Gij[g], self.orbsa)

            # Now sum the appropriate terms to get the b gradient
            for i in xrange(self.nalpha):
                for a in xrange(self.nalpha, self.norb):
                    bp[g] += Fmoa[i, a] * Gmo[i, a] / (self.orbea[i] -
                                                       self.orbea[a])

        for g in xrange(self.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 = simx(self.Gij[g], self.orbsb)

            # Now sum the appropriate terms to get the b gradient
            for i in xrange(self.nbeta):
                for a in xrange(self.nbeta, self.norb):
                    bp[self.nbf +
                       g] += Fmob[i, a] * Gmo[i, a] / (self.orbeb[i] -
                                                       self.orbeb[a])

        #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
        return bp
Пример #11
0
def get_rot(h,Hs,f,a,b,noccsh):
    nocc = sum(noccsh)
    nsh = len(noccsh)
    rot = zeros((nocc,nocc),'d')
    for i in xrange(nocc):
        ish = get_sh(i,noccsh)
        for j in xrange(nocc):
            jsh = get_sh(j,noccsh)
            if jsh == ish: continue
            Wij = -0.5*(h[i,j]+Hs[0][i,j])
            Wii = -0.5*(h[i,i]+Hs[0][i,i])
            Wjj = -0.5*(h[j,j]+Hs[0][j,j])
            for k in xrange(nsh):
                Wij = Wij - 0.5*Hs[2*i+1][i,j]
                Wii = Wij - 0.5*Hs[2*i+1][i,i]
                Wjj = Wij - 0.5*Hs[2*i+1][j,j]
            Jij = Hs[2*jsh][i,i]
            Kij = Hs[2*jsh+1][i,i]
            gamma = Kij-0.5*(Kij+Jij)
            Xij = -Wij
            Bij = Wii-Wjj+gamma
            if Bij > 0:
                Rij = -Xij/Bij
            else:
                Rij = Xij/Bij
            rot[i,j] = rot[j,i] = Rij
    return rot
Пример #12
0
 def inertial(self):
     "Transform to inertial coordinates"
     from PyQuante.NumWrap import zeros,eigh
     rcom = self.com()
     print "Translating to COM: ",rcom
     self.translate(-rcom)
     I = zeros((3,3),'d')
     for atom in self:
         m = atom.mass()
         x,y,z = atom.pos()
         x2,y2,z2 = x*x,y*y,z*z
         I[0,0] += m*(y2+z2)
         I[1,1] += m*(x2+z2)
         I[2,2] += m*(x2+y2)
         I[0,1] -= m*x*y
         I[1,0] = I[0,1]
         I[0,2] -= m*x*z
         I[2,0] = I[0,2]
         I[1,2] -= m*y*z
         I[2,1] = I[1,2]
     E,U = eigh(I)
     print "Moments of inertial ",E
     self.urotate(U)
     print "New coordinates: "
     print self
     return
Пример #13
0
 def inertial(self):
     "Transform to inertial coordinates"
     from PyQuante.NumWrap import zeros, eigh
     rcom = self.com()
     print "Translating to COM: ", rcom
     self.translate(-rcom)
     I = zeros((3, 3), 'd')
     for atom in self:
         m = atom.mass()
         x, y, z = atom.pos()
         x2, y2, z2 = x * x, y * y, z * z
         I[0, 0] += m * (y2 + z2)
         I[1, 1] += m * (x2 + z2)
         I[2, 2] += m * (x2 + y2)
         I[0, 1] -= m * x * y
         I[1, 0] = I[0, 1]
         I[0, 2] -= m * x * z
         I[2, 0] = I[0, 2]
         I[1, 2] -= m * y * z
         I[2, 1] = I[1, 2]
     E, U = eigh(I)
     print "Moments of inertial ", E
     self.urotate(U)
     print "New coordinates: "
     print self
     return
Пример #14
0
    def get_gradient(self,b):
        energy = self.get_energy(b)
        Fmoa = simx(self.Fa,self.orbsa)
        Fmob = simx(self.Fb,self.orbsb)

        bp = zeros(2*self.nbf,'d')

        for g in range(self.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 = simx(self.Gij[g],self.orbsa)

            # Now sum the appropriate terms to get the b gradient
            for i in range(self.nalpha):
                for a in range(self.nalpha,self.norb):
                    bp[g] += Fmoa[i,a]*Gmo[i,a]/(self.orbea[i]-self.orbea[a])

        for g in range(self.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 = simx(self.Gij[g],self.orbsb)

            # Now sum the appropriate terms to get the b gradient
            for i in range(self.nbeta):
                for a in range(self.nbeta,self.norb):
                    bp[self.nbf+g] += Fmob[i,a]*Gmo[i,a]/(self.orbeb[i]-self.orbeb[a])

        #logging.debug("EXX  Grad: %10.5f" % (sqrt(dot(bp,bp))))
        return bp
Пример #15
0
def fetch_kints(Ints,i,j,nbf):
    temp = zeros(nbf*nbf,'d')
    kl = 0
    for k in xrange(nbf):
        for l in xrange(nbf):
            temp[kl] = Ints[intindex(i,k,j,l)]
            kl += 1
    return temp
Пример #16
0
def tridiagmat(alpha, beta):
    N = len(alpha)
    A = zeros((N, N), 'd')
    for i in xrange(N):
        A[i, i] = alpha[i]
        if i < N - 1:
            A[i, i + 1] = A[i + 1, i] = beta[i]
    return A
Пример #17
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
Пример #18
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
Пример #19
0
def tridiagmat(alpha,beta):
    N = len(alpha)
    A = zeros((N,N),'d')
    for i in xrange(N):
        A[i,i] = alpha[i]
        if i < N-1:
            A[i,i+1] = A[i+1,i] = beta[i]
    return A
Пример #20
0
def appendColumn(A, newVec):
    """\
    Append a column vector onto matrix A; this creates a new
    matrix and does the relevant copying.
    """
    n, m = A.shape
    Anew = zeros((n, m + 1), 'd')
    Anew[:, :m] = A
    Anew[:, m] = newVec
    return Anew
Пример #21
0
def appendColumn(A,newVec):
    """\
    Append a column vector onto matrix A; this creates a new
    matrix and does the relevant copying.
    """
    n,m = A.shape
    Anew = zeros((n,m+1),'d')
    Anew[:,:m] = A
    Anew[:,m] = newVec
    return Anew
Пример #22
0
 def com(self):
     "Compute the center of mass of the molecule"
     from PyQuante.NumWrap import zeros
     rcom = zeros((3,),'d')
     mtot = 0
     for atom in self:
         m = atom.mass()
         rcom += m*atom.r
         mtot += m
     rcom /= mtot
     return rcom
Пример #23
0
def getV(bfs,atoms):
    "Form the nuclear attraction matrix V"
    nbf = len(bfs)
    V = zeros((nbf,nbf),'d')
    for i in xrange(nbf):
        bfi = bfs[i]
        for j in xrange(nbf):
            bfj = bfs[j]
            for atom in atoms:
                V[i,j] = V[i,j] + atom.atno*bfi.nuclear(bfj,atom.pos())
    return V
Пример #24
0
def getS(bfs):
    "Form the overlap matrix"
    nbf = len(bfs)
    S = zeros((nbf,nbf),'d')

    for i in xrange(nbf):
        bfi = bfs[i]
        for j in xrange(nbf):
            bfj = bfs[j]
            S[i,j] = bfi.overlap(bfj)
    return S
Пример #25
0
def getT(bfs):
    "Form the kinetic energy matrix"
    nbf = len(bfs)
    T = zeros((nbf,nbf),'d')

    for i in xrange(nbf):
        bfi = bfs[i]
        for j in xrange(nbf):
            bfj = bfs[j]
            T[i,j] = bfi.kinetic(bfj)
    return T
Пример #26
0
 def com(self):
     "Compute the center of mass of the molecule"
     from PyQuante.NumWrap import zeros
     rcom = zeros((3, ), 'd')
     mtot = 0
     for atom in self:
         m = atom.mass()
         rcom += m * atom.r
         mtot += m
     rcom /= mtot
     return rcom
Пример #27
0
def get_X_C(gr,FX = 1.0, FC = 1.0,**kwargs):
	"Form the exchange-correlation matrix"
	
	functional = kwargs.get('functional','SVWN')
	
	gr.floor_density()  # Insure that the values of the density don't underflow
	
	dens = gr.dens()
	weight = gr.weights()
	gamma = gr.get_gamma()
	npts = len(dens)
	
	if gr.version == 1:
	    amdens = zeros((2,npts),'d')
	    amgamma = zeros((3,npts),'d')
	    amdens[0,:] = amdens[1,:] = 0.5*dens
	    if gamma is not None:
	        amgamma[0,:] = amgamma[1,:] = amgamma[2,:] = 0.25*gamma
	elif gr.version == 2:
	    amdens = gr.density.T
	    amgamma = gr.gamma.T
	
	#fxc,dfxcdna,dfxcdnb,dfxcdgaa,dfxcdgab,dfxcdgbb = XC(amdens,amgamma,**kwargs)
	fx,dfxdna,dfxdnb,dfxdgaa,dfxdgab,dfxdgbb = Exch(amdens,amgamma,**kwargs)
	fc,dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb = Corr(amdens,amgamma,**kwargs)
	fxc = FX*fx+FC*fc
	dfxcdna = FX*dfxdna + FC*dfcdna
	

	Exc = dot(weight,fxc)
	
	wva = weight*dfxcdna  # Combine w*v in a vector for multiplication by bfs
	
	# First do the part that doesn't depend upon gamma
	nbf = gr.get_nbf()
	Fxca = zeros((nbf,nbf),'d')
	for i in xrange(nbf):
	    wva_i = wva*gr.bfgrid[:,i] 
	    for j in xrange(nbf):
	        Fxca[i,j] = dot(wva_i,gr.bfgrid[:,j])
	return Exc,Fxca
Пример #28
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
Пример #29
0
def VWN(dens,gamma=None):
    """
    Vosko-Wilk-Nusair correlation functional for vectors of
    spin up and spin down densities. From 'Accurate spin-dependent 
    electron liquid correlation energies for local spin density 
    calculations: a critical analysis.' SH Vosko, L Wilk, M Nusair, 
    Can J Phys, 58, 1200 (1980).

    Note that gamma is ignored, and is only included for consistency
    with the other XC functionals.

    AEM June 2006.
    """
    npts = len(dens[0])
    assert len(dens[1]) == npts
    fc = zeros(npts,'d')
    dfcdna = zeros(npts,'d')
    dfcdnb = zeros(npts,'d')
    dfcdgaa = zeros(npts,'d')
    dfcdgab = zeros(npts,'d')
    dfcdgbb = zeros(npts,'d')
    for i in xrange(npts):
        na = float(dens[0][i]) # Density of the alpha spin
	nb = float(dens[1][i]) # Density of the beta spin
        fcab,vca,vcb = cvwn(na,nb)
        fc[i] = fcab
	dfcdna[i] = vca
        dfcdnb[i] = vcb
    return fc,dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb
Пример #30
0
def LYP(dens,gamma):
    """Transformed version of LYP. See 'Results obtained with correlation
    energy density functionals of Becke and Lee, Yang, and Parr.' Miehlich,
    Savin, Stoll and Preuss. CPL 157, 200 (1989).
    AEM June 2006.
    """
    npts = len(dens[0])
    assert len(dens[1]) == npts
    assert len(gamma[0]) == npts
    assert len(gamma[1]) == npts
    assert len(gamma[2]) == npts
    fc = zeros(npts,'d')
    dfcdna = zeros(npts,'d')
    dfcdnb = zeros(npts,'d')
    dfcdgaa = zeros(npts,'d')
    dfcdgab = zeros(npts,'d')
    dfcdgbb = zeros(npts,'d')
    for i in xrange(npts):
        na = float(dens[0][i]) # Density of the alpha spin
	nb = float(dens[1][i]) # Density of the beta spin
        gamaa = gamma[0][i]
	gamab = gamma[1][i]
        gambb = gamma[2][i]
        fcab,fcna,fcnb,fcgaa,fcgab,fcgbb = clyp(na,nb,gamaa,gamab,gambb,
                                                return_flag=1)
        fc[i] = fcab
	dfcdna[i] = fcna
        dfcdnb[i] = fcnb
        dfcdgaa[i] = fcgaa
	dfcdgab[i] = fcgab
        dfcdgbb[i] = fcgbb
    return fc,dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb
Пример #31
0
def S(dens,gamma=None):
    """
    Slater exchange functional for vectors of spin-up and spin-down densities. 
    Based upon the classic Slater exchange (which actually came from Dirac). 
    See JC Slater 'The self consistent field for molecules and solids',
    McGraw Hill, New York, 1974.

    Note that gamma is ignored, and is only included for consistency
    with the other XC functionals.

    Also note that this exchange is written as a sum but doesn't use the
    spin-scaling relationship used for 'physics' exchange (LDA, PBE, PW91).

    AEM June 2006.
    """
    npts = len(dens[0])
    assert len(dens[1]) == npts
    fx = zeros(npts,'d')
    dfxdna = zeros(npts,'d')
    dfxdnb = zeros(npts,'d')
    dfxdgaa = zeros(npts,'d')
    dfxdgab = zeros(npts,'d')
    dfxdgbb = zeros(npts,'d')
    for i in xrange(npts):
        na = float(dens[0][i]) # Density of the alpha spin
	nb = float(dens[1][i]) # Density of the beta spin
        fxa,vxa = xs(na)
	fxb,vxb = xs(nb)
        fx[i] = fxa + fxb
        dfxdna[i] = vxa
	dfxdnb[i] = vxb
    return fx,dfxdna,dfxdnb,dfxdgaa,dfxdgab,dfxdgbb
Пример #32
0
def AM05(dens,gamma):
    """Armiento and Mattsson functional from 2005. (note: no spin)
    Rickard Armiento and Ann E Mattsson, PRB 72, 085108 (2005).
    AEM June 2006.
    """
    npts = len(dens[0])
    assert len(dens[1]) == npts
    assert len(gamma[0]) == npts
    assert len(gamma[1]) == npts
    assert len(gamma[2]) == npts
    fxc = zeros(npts,'d')
    dfxcdna = zeros(npts,'d')
    dfxcdnb = zeros(npts,'d')
    dfxcdgaa = zeros(npts,'d')
    dfxcdgab = zeros(npts,'d')
    dfxcdgbb = zeros(npts,'d')
    for i in xrange(npts):
        rho = float(dens[0][i]+dens[1][i]) # Total density 
        gam = gamma[0][i]+gamma[2][i] + 2.0*gamma[1][i] # Total gamma
        fpnt,dfdrho,dfdgamma = am05xc(rho,gam)
        fxc[i] = fpnt
        dfxcdna[i] = dfdrho 
	dfxcdnb[i] = dfdrho
	dfxcdgaa[i] = dfdgamma
	dfxcdgab[i] = 2.0*dfdgamma
        dfxcdgbb[i] = dfdgamma
    return fxc,dfxcdna,dfxcdnb,dfxcdgaa,dfxcdgab,dfxcdgbb    
Пример #33
0
def PW(dens,gamma=None):
    """
    Perdew-Wang correlation functional for vectors of
    spin up and spin down densities. From 'Accurate and simple 
    analytical representation of the electron-gas correlation energy' 
    John P. Perdew and Yue Wang, Phys. Rev. B 45, 13244 (1992).

    Note that gamma is ignored, and is only included for consistency
    with the other XC functionals.

    AEM June 2006.
    """
    npts = len(dens[0])
    assert len(dens[1]) == npts
    fc = zeros(npts,'d')
    dfcdna = zeros(npts,'d')
    dfcdnb = zeros(npts,'d')
    dfcdgaa = zeros(npts,'d')
    dfcdgab = zeros(npts,'d')
    dfcdgbb = zeros(npts,'d')
    for i in xrange(npts):
        na = float(dens[0][i]) # Density of the alpha spin
	nb = float(dens[1][i]) # Density of the beta spin
        fcab,vca,vcb = pw(na,nb)
        fc[i] = fcab
	dfcdna[i] = vca
        dfcdnb[i] = vcb
    return fc,dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb
Пример #34
0
def B(dens,gamma):
    """
    Becke 1988 Exchange Functional. From 'Density-functional exchange
    energy approximation with correct asymptotic behavior.' AD Becke,
    PRA 38, 3098 (1988).
    Chemistry way.
    AEM June 2006.
    """
    npts = len(dens[0])
    assert len(dens[1]) == npts
    assert len(gamma[0]) == npts
    assert len(gamma[1]) == npts
    assert len(gamma[2]) == npts
    fx = zeros(npts,'d')
    dfxdna = zeros(npts,'d')
    dfxdnb = zeros(npts,'d')
    dfxdgaa = zeros(npts,'d')
    dfxdgab = zeros(npts,'d')
    dfxdgbb = zeros(npts,'d')
    for i in xrange(npts):
        na = float(dens[0][i])  # Density of the alpha spin
	nb = float(dens[1][i])  # Density of the beta spin
        gamaa = gamma[0][i]
	gambb = gamma[2][i]
        fxa,fxna,fxgaa = xb(na,gamaa,return_flag = 1)
	fxb,fxnb,fxgbb = xb(nb,gambb,return_flag = 1)
        fx[i] = fxa + fxb
        dfxdna[i] = fxna
	dfxdnb[i] = fxnb
        dfxdgaa[i] = fxgaa
        dfxdgbb[i] = fxgbb
    return fx,dfxdna,dfxdnb,dfxdgaa,dfxdgab,dfxdgbb
Пример #35
0
def XC(dens,gamma,**opts):
    """\
    New top level routine for all XC functionals.
    dens is a two x npts component matrix with spin-up and spin-down 
    densities.
    gamma is a three x npts component matrix with grad(n1)*grad(n2) 
    with n1 and n2 being (spin-up, spin-up), (spin-up, spin-down), 
    and (spin-down,spin-down) densities. Should contain the right 
    number of elements (for example zeros) even if gradients are not needed.
    For non-spin calculations set 
    spin-up density = spin-down density = density/2 and
    gammaupup=gammaupdown=gammadowndown = |grad(rho)|**2/4.
    For non-spin we should get dfxcdna=dfxcdnb and dfxcdgaa=dfxcdgbb.
    dfxdgab = 0 always, it's included for consistency with dfcdgab.
    AEM June 2006.
    """
    functional = opts.get('functional','SVWN')
    derivative = opts.get('derivative','analyt')
    assert functional in xfuncs.keys() and functional in cfuncs.keys()
    #that npts is the same for all 5 vectors should be checked elsewhere    
    npts = len(dens[0]) 
    fxc = zeros(npts,'d')
    dfxcdna = zeros(npts,'d')
    dfxcdnb = zeros(npts,'d')
    dfxcdgaa = zeros(npts,'d')
    dfxcdgab = zeros(npts,'d')
    dfxcdgbb = zeros(npts,'d')
    if xfuncs[functional]:
        if derivative == 'analyt' and analyt[functional]:
            fx,dfxdna,dfxdnb,dfxdgaa,dfxdgab,dfxdgbb = \
	                      xfuncs[functional](dens,gamma)
        else:
	    fx,dfxdna,dfxdnb,dfxdgaa,dfxdgab,dfxdgbb = \
	                      xfuncs[functional](dens,gamma)	
	    dfxdna,dfxdnb,dfxdgaa,dfxdgab,dfxdgbb = \
	                      numder('x',functional,dens,gamma)
        fxc = fxc + fx
	dfxcdna = dfxcdna + dfxdna
        dfxcdnb = dfxcdnb + dfxdnb
        dfxcdgaa = dfxcdgaa + dfxdgaa
        dfxcdgab = dfxcdgab + dfxdgab
        dfxcdgbb = dfxcdgbb + dfxdgbb
    if cfuncs[functional]:
        if derivative == 'analyt' and analyt[functional]:
            fc,dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb = \
	                      cfuncs[functional](dens,gamma)
        else:
            fc,dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb = \
	                      cfuncs[functional](dens,gamma)
	    dfcdna,dfcdnb,dfcdgaa,dfcdgab,dfcdgbb = \
	                      numder('c',functional,dens,gamma)
        fxc = fxc + fc
	dfxcdna = dfxcdna + dfcdna
        dfxcdnb = dfxcdnb + dfcdnb
        dfxcdgaa = dfxcdgaa + dfcdgaa
        dfxcdgab = dfxcdgab + dfcdgab
        dfxcdgbb = dfxcdgbb + dfcdgbb
    return fxc,dfxcdna,dfxcdnb,dfxcdgaa,dfxcdgab,dfxcdgbb
Пример #36
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
Пример #37
0
def getJ(Ints,D):
    "Form the Coulomb operator corresponding to a density matrix D"
    nbf = D.shape[0]
    D1d = reshape(D,(nbf*nbf,)) #1D version of Dens
    J = zeros((nbf,nbf),'d')
    for i in xrange(nbf):
        for j in xrange(i+1):
            if sorted:
                temp = jints[i,j]
            else:
                temp = fetch_jints(Ints,i,j,nbf)
            J[i,j] = dot(temp,D1d)
            J[j,i] = J[i,j]
    return J
Пример #38
0
def getK(Ints,D):
    "Form the exchange operator corresponding to a density matrix D"
    nbf = D.shape[0]
    D1d = reshape(D,(nbf*nbf,)) #1D version of Dens
    K = zeros((nbf,nbf),'d')
    for i in xrange(nbf):
        for j in xrange(i+1):
            if sorted:
                temp = kints[i,j]
            else:
                temp = fetch_kints(Ints,i,j,nbf)
            K[i,j] = dot(temp,D1d)
            K[j,i] = K[i,j]
    return K
Пример #39
0
def get2JmK(Ints,D):
    "Form the 2J-K integrals corresponding to a density matrix D"
    nbf = D.shape[0]
    D1d = reshape(D,(nbf*nbf,)) #1D version of Dens
    G = zeros((nbf,nbf),'d')
    for i in xrange(nbf):
        for j in xrange(i+1):
            if sorted:
                temp = 2*jints[i,j]-kints[i,j]
            else:
                temp = 2*fetch_jints(Ints,i,j,nbf)-fetch_kints(Ints,i,j,nbf)
            G[i,j] = dot(temp,D1d)
            G[j,i] = G[i,j]
    return G
Пример #40
0
 def __init__(self, solver):
     # Solver is a pointer to a UHF calculation that has
     #  already converged
     self.solver = solver
     self.bfs = self.solver.bfs
     self.nbf = len(self.bfs)
     self.S = self.solver.S
     self.h = self.solver.h
     self.Ints = self.solver.Ints
     self.molecule = self.solver.molecule
     self.nel = self.molecule.get_nel()
     self.nalpha, self.nbeta = self.molecule.get_alphabeta()
     self.Enuke = self.molecule.get_enuke()
     self.norb = self.nbf
     self.orbsa = self.solver.orbsa
     self.orbsb = self.solver.orbsb
     self.orbea = self.solver.orbea
     self.orbeb = self.solver.orbeb
     self.Gij = []
     for g in xrange(self.nbf):
         gmat = zeros((self.nbf, self.nbf), 'd')
         self.Gij.append(gmat)
         gbf = self.bfs[g]
         for i in xrange(self.nbf):
             ibf = self.bfs[i]
             for j in xrange(i + 1):
                 jbf = self.bfs[j]
                 gij = three_center(ibf, gbf, jbf)
                 gmat[i, j] = gij
                 gmat[j, i] = gij
     D0 = mkdens(self.orbsa, 0, self.nalpha) + mkdens(
         self.orbsb, 0, self.nbeta)
     J0 = getJ(self.Ints, D0)
     Vfa = ((self.nel - 1.) / self.nel) * J0
     self.H0 = self.h + Vfa
     self.b = zeros(2 * self.nbf, 'd')
     return
Пример #41
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
Пример #42
0
def parse_orbs(lines,nbf):
    sympat = re.compile('^Sym\s*=\s*(\S+)\s*$')
    enepat = re.compile('^Ene\s*=\s*(\S+)$')
    spinpat = re.compile('^Spin\s*=\s*(\S+)$')
    occpat = re.compile('^Occup\s*=\s*(\S+)$')
    coefpat = re.compile('\s*(\d+)\s*(\S+)$')

    orbs = []
    sym,ene,spin,occ,coefs = None,None,None,None,[]

    for line in lines:
        if sympat.search(line):
            if sym: orbs.append((sym,ene,spin,occ,coefs))
            sym,ene,spin,occ,coefs = None,None,None,None,[]
            sym = sympat.search(line).groups()[0]
        elif enepat.search(line):
            ene = float(enepat.search(line).groups()[0])
        elif spinpat.search(line):
            spin = spinpat.search(line).groups()[0]
        elif occpat.search(line):
            occ = float(occpat.search(line).groups()[0])
        elif coefpat.search(line):
            a,b = coefpat.search(line).groups()
            iorb,coef = int(a),float(b)
            coefs.append((iorb,coef))
    #print_orbs(orbs)
    norb = len(orbs)
    orbmtx = zeros((nbf,norb),'d')
    orbe = zeros(norb,'d')
    occs = zeros(norb,'d')
    for i in xrange(norb):
        sym,ene,spin,occ,coefs = orbs[i]
        occs[i] = occ
        orbe[i] = ene
        for ibf,coef in coefs:
            orbmtx[ibf-1,i] = coef
    return occs,orbe,orbmtx
Пример #43
0
def get_fab(nclosed,nopen):
    f = []
    iopen_start = 0
    if nclosed:
        f.append(1.0)
        iopen_start = 1
    if nopen:
        f.append(0.5)
    nsh = len(f)
    a = zeros((nsh,nsh),'d')
    b = zeros((nsh,nsh),'d')

    for i in xrange(nsh):
        for j in xrange(nsh):
            a[i,j] = 2.*f[i]*f[j]
            b[i,j] = -f[i]*f[j]

    if nopen == 1:
        a[iopen_start,iopen_start] = 0
        b[iopen_start,iopen_start] = 0
    elif nopen > 1:
        b[iopen_start,iopen_start] = -0.5

    return f,a,b
Пример #44
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
Пример #45
0
def jacobi(A, **kwargs):
    """\
    E,V = jacobi(A,**kwargs) - Solve the eigenvalues/vectors of matrix
                             A using Jacobi's method.
    Options:
    Name        Default  Definition
    tol         1e-10    The tolerance for an element to be declared zero
    max_sweeps  200      Maximum number of sweeps through the matrix
    """
    max_sweeps = kwargs.get('max_sweeps', settings.JacobiSweeps)
    tol = kwargs.get('tol', settings.JacobiTolerance)
    n = len(A)
    V = identity(n, 'd')
    b = diagonal(A)
    d = diagonal(A)
    z = zeros(n, 'd')
    nrot = 0
    for irot in xrange(max_sweeps):
        sm = 0
        for ip in xrange(n - 1):
            for iq in xrange(ip + 1, n):
                sm += abs(A[ip, iq])
        if sm < tol:
            # Normal return
            return evsort(b, V)

        thresh = 0
        if irot < 3: thresh = 0.2 * sm / n / n

        for ip in xrange(n - 1):
            for iq in xrange(ip + 1, n):
                g = 100 * abs(A[ip, iq])
                if irot > 3 and g < tol:
                    A[ip, iq] = 0
                elif abs(A[ip, iq]) > thresh:
                    h = d[iq] - d[ip]
                    if g < tol:
                        t = A[ip, iq] / h  # t = 1/(2\theta)
                    else:
                        theta = 0.5 * h / A[ip, iq]  #  eq 11.1.10
                        t = 1. / (abs(theta) + sqrt(1. + theta * theta))
                        if theta < 0: t = -t
                    c = 1.0 / sqrt(1 + t * t)
                    s = t * c
                    tau = s / (1.0 + c)
                    h = t * A[ip, iq]
                    z[ip] -= h
                    z[iq] += h
                    d[ip] -= h
                    d[iq] += h
                    A[ip, iq] = 0
                    for j in xrange(ip):
                        A[j, ip], A[j, iq] = rotate(A[j, ip], A[j, iq], s, tau)
                    for j in xrange(ip + 1, iq):
                        A[ip, j], A[j, iq] = rotate(A[ip, j], A[j, iq], s, tau)
                    for j in xrange(iq + 1, n):
                        A[ip, j], A[iq, j] = rotate(A[ip, j], A[iq, j], s, tau)
                    for j in xrange(n):
                        V[j, ip], V[j, iq] = rotate(V[j, ip], V[j, iq], s, tau)
                    nrot += 1
        for ip in xrange(n):
            b[ip] += z[ip]
            d[ip] = b[ip]
            z[ip] = 0
    else:
        print "Too many iterations"
    return None
Пример #46
0
def oep(atoms, orbs, energy_func, grad_func=None, **opts):
    """oep - Form the optimized effective potential for a given energy expression

    oep(atoms,orbs,energy_func,grad_func=None,**opts)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals
    energy_func The function that returns the energy for the given method
    grad_func   The function that returns the force for the given method

    Options
    -------
    verbose       False   Output terse information to stdout (default)
                  True    Print out additional information 
    ETemp         False   Use ETemp value for finite temperature DFT (default)
                  float   Use (float) for the electron temperature
    bfs           None    The basis functions to use. List of CGBF's
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    verbose = opts.get('verbose', False)
    ETemp = opts.get('ETemp', False)
    opt_method = opts.get('opt_method', 'BFGS')

    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 = fminBFGS(energy_func,
                 b,
                 grad_func,
                 (nbf, nel, nocc, ETemp, Enuke, S, h, Ints, H0, Gij),
                 logger=logging)

    energy, orbe, orbs = energy_func(b,
                                     nbf,
                                     nel,
                                     nocc,
                                     ETemp,
                                     Enuke,
                                     S,
                                     h,
                                     Ints,
                                     H0,
                                     Gij,
                                     return_flag=1)
    return energy, orbe, orbs
Пример #47
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
Пример #48
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)
Пример #49
0
def get1ints_mpi(bfs, atoms, rank, comm, _debug_=False):

    "Form the overlap S and h=t+vN one-electron Hamiltonian matrices"
    nbf = len(bfs)

    # determine which orbitals we will compute
    npp = nbf / comm.size
    if rank < comm.size - 1:
        terms = range(rank * npp, (rank + 1) * npp)
    else:
        terms = range(rank * npp, nbf)

    nterm = len(terms)
    S = zeros((nterm, nbf))
    h = zeros((nterm, nbf))

    # print for debugging
    if _debug_:
        comm.Barrier()
        if rank == 0:
            print '\t Computing the 1electron integrals on %d procs' % comm.size
            print '\t There is %d basis functions in the system' % (len(bfs))
            print '\t',
            print '-' * 50
        print '\t [%03d] computes %d terms ' % (rank, nterm)

    # Compute the terms
    ilocal = 0
    for i in terms:
        bfi = bfs[i]
        for j in xrange(nbf):
            bfj = bfs[j]
            S[ilocal, j] = bfi.overlap(bfj)
            h[ilocal, j] = bfi.kinetic(bfj)
            for atom in atoms:
                h[ilocal,
                  j] = h[ilocal, j] + atom.Z * bfi.nuclear(bfj, atom.pos())
        ilocal += 1

##########################################
# Start communication between nodes
# to gather the total matrix on 0
##########################################

# wait for everyone to be here
    comm.barrier()

    # Create the receive buffers
    # only rank = 0 will receive
    if rank == 0:
        Stot = np.zeros((nbf, nbf))
        htot = np.zeros((nbf, nbf))
        Stot[0:npp, :] = S
        htot[0:npp] = h
    else:
        htot = None
        Stot = None

    if rank == 0 and _debug_:
        print '\n\t Procs 0 Gather all 1electron matrix'
    # exchange the 1 electron matrix
    if rank == 0:
        for iC in range(1, comm.size):
            if iC < comm.size - 1:
                recvbuff = np.zeros((npp, nbf))
                comm.Recv(recvbuff, source=iC)
                htot[npp * iC:npp * (iC + 1), :] = recvbuff
                if _debug_:
                    print '\t\t\t Proc [%03d] : data received from [%03d]' % (
                        0, iC)
            else:
                recvbuff = np.zeros((nbf - iC * npp, nbf))
                comm.Recv(recvbuff, source=iC)
                htot[npp * iC:, :] = recvbuff
                if _debug_:
                    print '\t\t\t Proc [%03d] : data received from [%03d]' % (
                        0, iC)
    else:
        comm.Send(h, dest=0)

    comm.Barrier()
    if rank == 0 and _debug_:
        print '\n\t Procs 0 Gather all overlap matrix'
    # exchange the overlap matrix
    if rank == 0:
        for iC in range(1, comm.size):
            if iC < comm.size - 1:
                recvbuff = np.zeros((npp, nbf))
                comm.Recv(recvbuff, source=iC)
                Stot[npp * iC:npp * (iC + 1), :] = recvbuff
                if _debug_:
                    print '\t\t\t Proc [%03d] : data received from [%03d]' % (
                        0, iC)
            else:
                recvbuff = np.zeros((nbf - iC * npp, nbf))
                comm.Recv(recvbuff, source=iC)
                Stot[npp * iC:, :] = recvbuff
                if _debug_:
                    print '\t\t\t Proc [%03d] : data received from [%03d]' % (
                        0, iC)
    else:
        comm.Send(S, dest=0)

    # done
    return Stot, htot
Пример #50
0
def get_orbs(orbs,orbs_in_shell):
    "This should do the same thing as take(orbs,orbs_in_shell,1)"
    A = zeros((orbs.shape[0],len(orbs_in_shell)),'d')
    for i,iorb in enumerate(orbs_in_shell):
        A[:,i] = orbs[:,iorb]
    return A