def MP2(aoints,orbs,orbe,nclosed,nvirt): #moints = TransformInts(aoints,orbs) moints = TransformIntsMP2(aoints,orbs,nclosed) occs = range(nclosed) unoccs = range(nclosed,nclosed+nvirt) nocc = len(occs) Epairs = zeros((nocc,nocc),'d') Emp2 = 0 for a in occs: for b in occs: for r in unoccs: for s in unoccs: arbs = moints[ijkl2intindex(a,r,b,s)] asbr = moints[ijkl2intindex(a,s,b,r)] Epairs[a,b] += arbs*(2*arbs-asbr)/\ (orbe[a]+orbe[b]-orbe[r]-orbe[s]) if VERBOSE: print "MP2 pair energies" for a in range(nocc): for b in range(a): print a,b,Epairs[a,b]+Epairs[b,a] print a,a,Epairs[a,a] return sum(sum(Epairs))
def MP2(aoints, orbs, orbe, nclosed, nvirt): #moints = TransformInts(aoints,orbs) moints = TransformIntsMP2(aoints, orbs, nclosed) occs = range(nclosed) unoccs = range(nclosed, nclosed + nvirt) nocc = len(occs) Epairs = zeros((nocc, nocc), 'd') Emp2 = 0 for a in occs: for b in occs: for r in unoccs: for s in unoccs: arbs = moints[ijkl2intindex(a, r, b, s)] asbr = moints[ijkl2intindex(a, s, b, r)] Epairs[a,b] += arbs*(2*arbs-asbr)/\ (orbe[a]+orbe[b]-orbe[r]-orbe[s]) if VERBOSE: print "MP2 pair energies" for a in xrange(nocc): for b in xrange(a): print a, b, Epairs[a, b] + Epairs[b, a] print a, a, Epairs[a, a] return sum(sum(Epairs))
def derK(D, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa): #modified from Ints.py -> getK "Form the exchange operator corresponding to a density matrix D" nbf = D.shape[0] D1d = reshape(D, (nbf * nbf, )) #1D version of Dens dKx = zeros((nbf, nbf), 'd') dKy = zeros((nbf, nbf), 'd') dKz = zeros((nbf, nbf), 'd') for i in xrange(nbf): for j in xrange(i + 1): xtemp = zeros(nbf * nbf, 'd') ytemp = zeros(nbf * nbf, 'd') ztemp = zeros(nbf * nbf, 'd') kl = 0 for k in xrange(nbf): for l in xrange(nbf): index_k1 = ijkl2intindex(i, k, j, l) index_k2 = ijkl2intindex(i, l, k, j) xtemp[kl] = 0.5 * (d2Ints_dXa[index_k1] + d2Ints_dXa[index_k2]) ytemp[kl] = 0.5 * (d2Ints_dYa[index_k1] + d2Ints_dYa[index_k2]) ztemp[kl] = 0.5 * (d2Ints_dZa[index_k1] + d2Ints_dZa[index_k2]) kl += 1 dKx[i, j] = dot(xtemp, D1d) dKx[j, i] = dKx[i, j] dKy[i, j] = dot(ytemp, D1d) dKy[j, i] = dKy[i, j] dKz[i, j] = dot(ztemp, D1d) dKz[j, i] = dKz[i, j] return dKx, dKy, dKz
def derK(D,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa): #modified from Ints.py -> getK "Form the exchange operator corresponding to a density matrix D" nbf = D.shape[0] D1d = reshape(D,(nbf*nbf,)) #1D version of Dens dKx = zeros((nbf,nbf),'d') dKy = zeros((nbf,nbf),'d') dKz = zeros((nbf,nbf),'d') for i in xrange(nbf): for j in xrange(i+1): xtemp = zeros(nbf*nbf,'d') ytemp = zeros(nbf*nbf,'d') ztemp = zeros(nbf*nbf,'d') kl = 0 for k in xrange(nbf): for l in xrange(nbf): index_k1 = ijkl2intindex(i,k,j,l) index_k2 = ijkl2intindex(i,l,k,j) xtemp[kl] = 0.5*(d2Ints_dXa[index_k1]+d2Ints_dXa[index_k2]) ytemp[kl] = 0.5*(d2Ints_dYa[index_k1]+d2Ints_dYa[index_k2]) ztemp[kl] = 0.5*(d2Ints_dZa[index_k1]+d2Ints_dZa[index_k2]) kl += 1 dKx[i,j] = dot(xtemp,D1d) dKx[j,i] = dKx[i,j] dKy[i,j] = dot(ytemp,D1d) dKy[j,i] = dKy[i,j] dKz[i,j] = dot(ztemp,D1d) dKz[j,i] = dKz[i,j] return dKx,dKy,dKz
def TransformInts(Ints,orbs): """O(N^5) 4-index transformation of the two-electron integrals. Not as efficient as it could be, since it inflates to the full rectangular matrices rather than keeping them compressed. But at least it gets the correct result.""" from time import time t0 = time() nbf,nmo = orbs.shape totlen = nmo*(nmo+1)*(nmo*nmo+nmo+2)/8 temp = zeros((nbf,nbf,nbf,nmo),'d') tempvec = zeros(nbf,'d') temp2 = zeros((nbf,nbf,nmo,nmo),'d') mos = range(nmo) # preform so we don't form inside loops bfs = range(nbf) # Start with (mu,nu|sigma,eta) # Unpack aoints and transform eta -> l for mu in bfs: for nu in bfs: for sigma in bfs: for l in mos: for eta in bfs: tempvec[eta] = Ints[ijkl2intindex(mu,nu,sigma,eta)] temp[mu,nu,sigma,l] = dot(orbs[:,l],tempvec) # Transform sigma -> k for mu in bfs: for nu in bfs: for l in mos: for k in mos: temp2[mu,nu,k,l] = dot(orbs[:,k],temp[mu,nu,:,l]) # Transform nu -> j for mu in bfs: for k in mos: for l in mos: for j in mos: temp[mu,j,k,l] = dot(orbs[:,j],temp2[mu,:,k,l]) # Transform mu -> i and repack integrals: MOInts = zeros(totlen,'d') 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) MOInts[ijkl] = dot(orbs[:,i],temp[:,j,k,l]) del temp,temp2,tempvec #force garbage collection now return MOInts
def TransformInts(Ints, orbs): """O(N^5) 4-index transformation of the two-electron integrals. Not as efficient as it could be, since it inflates to the full rectangular matrices rather than keeping them compressed. But at least it gets the correct result.""" from time import time t0 = time() nbf, nmo = orbs.shape totlen = nmo * (nmo + 1) * (nmo * nmo + nmo + 2) / 8 temp = zeros((nbf, nbf, nbf, nmo), 'd') tempvec = zeros(nbf, 'd') temp2 = zeros((nbf, nbf, nmo, nmo), 'd') mos = range(nmo) # preform so we don't form inside loops bfs = range(nbf) # Start with (mu,nu|sigma,eta) # Unpack aoints and transform eta -> l for mu in bfs: for nu in bfs: for sigma in bfs: for l in mos: for eta in bfs: tempvec[eta] = Ints[ijkl2intindex(mu, nu, sigma, eta)] temp[mu, nu, sigma, l] = dot(orbs[:, l], tempvec) # Transform sigma -> k for mu in bfs: for nu in bfs: for l in mos: for k in mos: temp2[mu, nu, k, l] = dot(orbs[:, k], temp[mu, nu, :, l]) # Transform nu -> j for mu in bfs: for k in mos: for l in mos: for j in mos: temp[mu, j, k, l] = dot(orbs[:, j], temp2[mu, :, k, l]) # Transform mu -> i and repack integrals: MOInts = zeros(totlen, 'd') 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) MOInts[ijkl] = dot(orbs[:, i], temp[:, j, k, l]) del temp, temp2, tempvec #force garbage collection now return MOInts
def TransformIntsMP2(Ints, orbs, nclosed): """\ O(N^5) 4-index transformation of the two-electron integrals. Only transform the ones needed for MP2, which reduces the scaling to O(nN^4), where n are the occs (<<N). """ from time import time t0 = time() nbf, nmo = orbs.shape totlen = nmo * (nmo + 1) * (nmo * nmo + nmo + 2) / 8 occs = range(nclosed) mos = range(nmo) bfs = range(nbf) # Start with (mu,nu|sigma,eta) # Unpack aoints and transform sigma -> b temp = zeros((nbf, nbf, nclosed, nbf), 'd') tempvec = zeros(nbf, 'd') for mu in bfs: for nu in bfs: for eta in bfs: for b in occs: for sigma in bfs: tempvec[sigma] = Ints[ijkl2intindex( mu, nu, sigma, eta)] temp[mu, nu, b, eta] = dot(orbs[:, b], tempvec) temp2 = zeros((nclosed, nbf, nclosed, nbf), 'd') for nu in bfs: for eta in bfs: for b in occs: for a in occs: temp2[a, nu, b, eta] = dot(orbs[:, a], temp[:, nu, b, eta]) temp = zeros((nclosed, nbf, nclosed, nmo), 'd') for a in occs: for nu in bfs: for b in occs: for j in mos: temp[a, nu, b, j] = dot(orbs[:, j], temp2[a, nu, b, :]) # Transform mu -> i and repack integrals: MOInts = zeros(totlen, 'd') for a in occs: for j in mos: for b in occs: for i in mos: aibj = ijkl2intindex(a, i, b, j) MOInts[aibj] = dot(orbs[:, i], temp[a, :, b, j]) #print "Integral transform time = ",time()-t0 del temp, temp2, tempvec #force garbage collection now return MOInts
def TransformIntsMP2(Ints,orbs,nclosed): """\ O(N^5) 4-index transformation of the two-electron integrals. Only transform the ones needed for MP2, which reduces the scaling to O(nN^4), where n are the occs (<<N). """ from time import time t0 = time() nbf,nmo = orbs.shape totlen = nmo*(nmo+1)*(nmo*nmo+nmo+2)/8 occs = range(nclosed) mos = range(nmo) bfs = range(nbf) # Start with (mu,nu|sigma,eta) # Unpack aoints and transform sigma -> b temp = zeros((nbf,nbf,nclosed,nbf),'d') tempvec = zeros(nbf,'d') for mu in bfs: for nu in bfs: for eta in bfs: for b in occs: for sigma in bfs: tempvec[sigma] = Ints[ijkl2intindex(mu,nu,sigma,eta)] temp[mu,nu,b,eta] = dot(orbs[:,b],tempvec) temp2 = zeros((nclosed,nbf,nclosed,nbf),'d') for nu in bfs: for eta in bfs: for b in occs: for a in occs: temp2[a,nu,b,eta] = dot(orbs[:,a],temp[:,nu,b,eta]) temp = zeros((nclosed,nbf,nclosed,nmo),'d') for a in occs: for nu in bfs: for b in occs: for j in mos: temp[a,nu,b,j] = dot(orbs[:,j],temp2[a,nu,b,:]) # Transform mu -> i and repack integrals: MOInts = zeros(totlen,'d') for a in occs: for j in mos: for b in occs: for i in mos: aibj = ijkl2intindex(a,i,b,j) MOInts[aibj] = dot(orbs[:,i],temp[a,:,b,j]) #print "Integral transform time = ",time()-t0 del temp,temp2,tempvec #force garbage collection now return MOInts
def TransformInts(Ints, orbs1, orbs2, nocc): nbf, nmo = orbs1.shape totlen = nmo * nmo * nmo * nmo occs = range(nocc) mos = range(nmo) bfs = range(nbf) # Start with (mu,nu|sigma,eta) # Unpack aoints and transform sigma -> b # Here sigma, b, nu, j are of first same spin group, # others of second same spin group temp = zeros((nbf, nbf, nbf, nbf), 'd') tempvec = zeros(nbf, 'd') for mu in bfs: for nu in bfs: for eta in bfs: for b in bfs: for sigma in bfs: tempvec[sigma] = Ints[ijkl2intindex( mu, nu, sigma, eta)] temp[mu, nu, b, eta] = dot(orbs1[b, :], tempvec) temp2 = zeros((nbf, nbf, nbf, nbf), 'd') for nu in bfs: for eta in bfs: for b in bfs: for a in bfs: temp2[a, nu, b, eta] = dot(orbs2[a, :], temp[:, nu, b, eta]) temp = zeros((nbf, nbf, nbf, nbf), 'd') for a in bfs: for nu in bfs: for b in bfs: for j in bfs: temp[a, nu, b, j] = dot(orbs1[j, :], temp2[a, nu, b, :]) # Transform mu -> i and repack integrals: MOInts = zeros(totlen, 'd') for a in bfs: for j in bfs: for b in bfs: for i in bfs: aibj = ijkl2intindex(a, i, b, j) MOInts[aibj] = dot(orbs2[i, :], temp[a, :, b, j]) del temp, temp2, tempvec #force garbage collection now return MOInts, nbf
def TransformInts(Ints,orbs1,orbs2, nocc): nbf,nmo = orbs1.shape totlen = nmo*nmo*nmo*nmo occs = range(nocc) mos = range(nmo) bfs = range(nbf) # Start with (mu,nu|sigma,eta) # Unpack aoints and transform sigma -> b # Here sigma, b, nu, j are of first same spin group, # others of second same spin group temp = zeros((nbf,nbf,nbf,nbf),'d') tempvec = zeros(nbf,'d') for mu in bfs: for nu in bfs: for eta in bfs: for b in bfs: for sigma in bfs: tempvec[sigma] = Ints[ijkl2intindex(mu,nu,sigma,eta)] temp[mu,nu,b,eta] = dot(orbs1[b,:],tempvec) temp2 = zeros((nbf,nbf,nbf,nbf),'d') for nu in bfs: for eta in bfs: for b in bfs: for a in bfs: temp2[a,nu,b,eta] = dot(orbs2[a,:],temp[:,nu,b,eta]) temp = zeros((nbf,nbf,nbf,nbf),'d') for a in bfs: for nu in bfs: for b in bfs: for j in bfs: temp[a,nu,b,j] = dot(orbs1[j,:],temp2[a,nu,b,:]) # Transform mu -> i and repack integrals: MOInts = zeros(totlen,'d') for a in bfs: for j in bfs: for b in bfs: for i in bfs: aibj = ijkl2intindex(a,i,b,j) MOInts[aibj] = dot(orbs2[i,:],temp[a,:,b,j]) del temp,temp2,tempvec #force garbage collection now return MOInts, nbf
def derJ(D, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa): #modified from Ints.py -> getJ "Form the Coulomb operator corresponding to a density matrix D" nbf = D.shape[0] D1d = reshape(D, (nbf * nbf, )) #1D version of Dens dJx = zeros((nbf, nbf), 'd') dJy = zeros((nbf, nbf), 'd') dJz = zeros((nbf, nbf), 'd') for i in xrange(nbf): for j in xrange(i + 1): xtemp = zeros(nbf * nbf, 'd') ytemp = zeros(nbf * nbf, 'd') ztemp = zeros(nbf * nbf, 'd') kl = 0 for k in xrange(nbf): for l in xrange(nbf): index = ijkl2intindex(i, j, k, l) xtemp[kl] = d2Ints_dXa[index] ytemp[kl] = d2Ints_dYa[index] ztemp[kl] = d2Ints_dZa[index] kl += 1 dJx[i, j] = dot(xtemp, D1d) dJx[j, i] = dJx[i, j] dJy[i, j] = dot(ytemp, D1d) dJy[j, i] = dJy[i, j] dJz[i, j] = dot(ztemp, D1d) dJz[j, i] = dJz[i, j] return dJx, dJy, dJz
def derJ(D,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa): #modified from Ints.py -> getJ "Form the Coulomb operator corresponding to a density matrix D" nbf = D.shape[0] D1d = reshape(D,(nbf*nbf,)) #1D version of Dens dJx = zeros((nbf,nbf),'d') dJy = zeros((nbf,nbf),'d') dJz = zeros((nbf,nbf),'d') for i in xrange(nbf): for j in xrange(i+1): xtemp = zeros(nbf*nbf,'d') ytemp = zeros(nbf*nbf,'d') ztemp = zeros(nbf*nbf,'d') kl = 0 for k in xrange(nbf): for l in xrange(nbf): index = ijkl2intindex(i,j,k,l) xtemp[kl] = d2Ints_dXa[index] ytemp[kl] = d2Ints_dYa[index] ztemp[kl] = d2Ints_dZa[index] kl += 1 dJx[i,j] = dot(xtemp,D1d) dJx[j,i] = dJx[i,j] dJy[i,j] = dot(ytemp,D1d) dJy[j,i] = dJy[i,j] dJz[i,j] = dot(ztemp,D1d) dJz[j,i] = dJz[i,j] return dJx,dJy,dJz
def eval0(self, i, E): # just do the simple approximation, S/A eqs 7.44-7.46 term = 0. occs = range(self.nocc) virts = range(self.nocc, self.norb) for a in occs: for r in virts: for s in virts: iras = self.moints[ijkl2intindex(i, r, a, s)] isar = self.moints[ijkl2intindex(i, s, a, r)] term += iras * (2 * iras - isar) / ( E + self.e0[a] - self.e0[r] - self.e0[s]) for a in occs: for b in occs: for r in virts: iabr = self.moints[ijkl2intindex(i, a, b, r)] ibar = self.moints[ijkl2intindex(i, b, a, r)] term += iabr * (2 * iabr - ibar) / ( E + self.e0[r] - self.e0[a] - self.e0[b]) return term
def eval0(self,i,E): # just do the simple approximation, S/A eqs 7.44-7.46 term = 0. occs = range(self.nocc) virts = range(self.nocc,self.norb) for a in occs: for r in virts: for s in virts: iras = self.moints[ijkl2intindex(i,r,a,s)] isar = self.moints[ijkl2intindex(i,s,a,r)] term += iras*(2*iras-isar)/( E+self.e0[a]-self.e0[r]-self.e0[s]) for a in occs: for b in occs: for r in virts: iabr = self.moints[ijkl2intindex(i,a,b,r)] ibar = self.moints[ijkl2intindex(i,b,a,r)] term += iabr*(2*iabr-ibar)/( E+self.e0[r]-self.e0[a]-self.e0[b]) return term
def der2JmK(D,d2Ints_dXa,d2Ints_dYa,d2Ints_dZa): #modified from Ints.py -> get2Jmk "Form the 2J-K integrals corresponding to a density matrix D" nbf = D.shape[0] D1d = reshape(D,(nbf*nbf,)) #1D version of Dens Gx = zeros((nbf,nbf),'d') Gy = zeros((nbf,nbf),'d') Gz = zeros((nbf,nbf),'d') for i in xrange(nbf): for j in xrange(i+1): xtemp = zeros(nbf*nbf,'d') ytemp = zeros(nbf*nbf,'d') ztemp = zeros(nbf*nbf,'d') kl = 0 for k in xrange(nbf): for l in xrange(nbf): index_j = ijkl2intindex(i,j,k,l) index_k1 = ijkl2intindex(i,k,j,l) index_k2 = ijkl2intindex(i,l,k,j) xtemp[kl] = 2.*d2Ints_dXa[index_j]-0.5*d2Ints_dXa[index_k1]\ -0.5*d2Ints_dXa[index_k2] ytemp[kl] = 2.*d2Ints_dYa[index_j]-0.5*d2Ints_dYa[index_k1]\ -0.5*d2Ints_dYa[index_k2] ztemp[kl] = 2.*d2Ints_dZa[index_j]-0.5*d2Ints_dZa[index_k1]\ -0.5*d2Ints_dZa[index_k2] kl += 1 Gx[i,j] = dot(xtemp,D1d) Gx[j,i] = Gx[i,j] Gy[i,j] = dot(ytemp,D1d) Gy[j,i] = Gy[i,j] Gz[i,j] = dot(ztemp,D1d) Gz[j,i] = Gz[i,j] return Gx,Gy,Gz
def fulleval(self,E): # This routine doesn't work very well. g = zeros((self.norb,self.norb),'d') orbs = range(self.norb) occs = range(self.nocc) virts = range(self.nocc,self.norb) term = 0. for i in orbs: for j in orbs: for a in occs: for r in virts: for s in virts: iras = self.moints[ijkl2intindex(i,r,a,s)] jras = self.moints[ijkl2intindex(j,r,a,s)] jsar = self.moints[ijkl2intindex(j,s,a,r)] term += iras*(2*jras-jsar)/( E+self.e0[a]-self.e0[r]-self.e0[s]) for a in occs: for b in occs: for r in virts: iabr = self.moints[ijkl2intindex(i,a,b,r)] jabr = self.moints[ijkl2intindex(j,a,b,r)] jbar = self.moints[ijkl2intindex(j,b,a,r)] term += iabr*(2*jabr-jbar)/( E+self.e0[r]-self.e0[a]-self.e0[b]) g[i,j] = -term for i in orbs: g[i,i] += E - self.e0[i] return det(g)
def fulleval(self, E): # This routine doesn't work very well. g = zeros((self.norb, self.norb), 'd') orbs = range(self.norb) occs = range(self.nocc) virts = range(self.nocc, self.norb) term = 0. for i in orbs: for j in orbs: for a in occs: for r in virts: for s in virts: iras = self.moints[ijkl2intindex(i, r, a, s)] jras = self.moints[ijkl2intindex(j, r, a, s)] jsar = self.moints[ijkl2intindex(j, s, a, r)] term += iras * (2 * jras - jsar) / ( E + self.e0[a] - self.e0[r] - self.e0[s]) for a in occs: for b in occs: for r in virts: iabr = self.moints[ijkl2intindex(i, a, b, r)] jabr = self.moints[ijkl2intindex(j, a, b, r)] jbar = self.moints[ijkl2intindex(j, b, a, r)] term += iabr * (2 * jabr - jbar) / ( E + self.e0[r] - self.e0[a] - self.e0[b]) g[i, j] = -term for i in orbs: g[i, i] += E - self.e0[i] return det(g)
def der2JmK(D, d2Ints_dXa, d2Ints_dYa, d2Ints_dZa): #modified from Ints.py -> get2Jmk "Form the 2J-K integrals corresponding to a density matrix D" nbf = D.shape[0] D1d = reshape(D, (nbf * nbf, )) #1D version of Dens Gx = zeros((nbf, nbf), 'd') Gy = zeros((nbf, nbf), 'd') Gz = zeros((nbf, nbf), 'd') for i in xrange(nbf): for j in xrange(i + 1): xtemp = zeros(nbf * nbf, 'd') ytemp = zeros(nbf * nbf, 'd') ztemp = zeros(nbf * nbf, 'd') kl = 0 for k in xrange(nbf): for l in xrange(nbf): index_j = ijkl2intindex(i, j, k, l) index_k1 = ijkl2intindex(i, k, j, l) index_k2 = ijkl2intindex(i, l, k, j) xtemp[kl] = 2.*d2Ints_dXa[index_j]-0.5*d2Ints_dXa[index_k1]\ -0.5*d2Ints_dXa[index_k2] ytemp[kl] = 2.*d2Ints_dYa[index_j]-0.5*d2Ints_dYa[index_k1]\ -0.5*d2Ints_dYa[index_k2] ztemp[kl] = 2.*d2Ints_dZa[index_j]-0.5*d2Ints_dZa[index_k1]\ -0.5*d2Ints_dZa[index_k2] kl += 1 Gx[i, j] = dot(xtemp, D1d) Gx[j, i] = Gx[i, j] Gy[i, j] = dot(ytemp, D1d) Gy[j, i] = Gy[i, j] Gz[i, j] = dot(ztemp, D1d) Gz[j, i] = Gz[i, j] return Gx, Gy, Gz
def CISDMatrix(Ints,orbs,Ehf,orbe,occs): nocc, nvirt = get_occ_unocc(occs) singles = SingleExcitations(range(nocc),range(nocc,nocc+nvirt)) #doubles = DoubleExcitations(range(nocc),range(nocc,nocc+nvirt)) doubles = [] nsin = len(singles) ndoub = len(doubles) nex = nsin+ndoub MOInts = TransformInts(Ints,orbs) # see Szabo/Ostlund Table 4.1 CIMatrix = zeros((nex,nex),'d') for ar in xrange(nsin): a,r = singles[ar] for bs in xrange(nsin): b,s = singles[bs] rabs = ijkl2intindex(r,a,b,s) rsba = ijkl2intindex(r,s,b,a) CIMatrix[ar,bs] = 2*MOInts[rabs] - MOInts[rsba] if r==s and a==b: CIMatrix[ar,bs] += Ehf+orbe[r]-orbe[a] CIMatrix[bs,ar] = CIMatrix[ar,bs] return CIMatrix
def CISDMatrix(Ints, orbs, Ehf, orbe, occs): nocc, nvirt = get_occ_unocc(occs) singles = SingleExcitations(range(nocc), range(nocc, nocc + nvirt)) #doubles = DoubleExcitations(range(nocc),range(nocc,nocc+nvirt)) doubles = [] nsin = len(singles) ndoub = len(doubles) nex = nsin + ndoub MOInts = TransformInts(Ints, orbs) # see Szabo/Ostlund Table 4.1 CIMatrix = zeros((nex, nex), 'd') for ar in xrange(nsin): a, r = singles[ar] for bs in xrange(nsin): b, s = singles[bs] rabs = ijkl2intindex(r, a, b, s) rsba = ijkl2intindex(r, s, b, a) CIMatrix[ar, bs] = 2 * MOInts[rabs] - MOInts[rsba] if r == s and a == b: CIMatrix[ar, bs] += Ehf + orbe[r] - orbe[a] CIMatrix[bs, ar] = CIMatrix[ar, bs] return CIMatrix
def CISMatrix(Ints, orbs, Ehf, orbe, nocc, nvirt): "Naive implementation: Int xfrm + slow formation" # The best reference for this stuff is Chap 4 of Szabo/Ostlund # Generate the list, and the number of excitations: singles = SingleExcitations(range(nocc), range(nocc, nocc + nvirt)) nex = len(singles) # Do the four-index transformation of the 2e ints. This is expensive! MOInts = TransformInts(Ints, orbs) # Build the CI matrix using the Slater Condon rules # see Szabo/Ostlund Table 4.1 CIMatrix = zeros((nex, nex), 'd') for ar in xrange(nex): a, r = singles[ar] for bs in xrange(nex): b, s = singles[bs] rabs = ijkl2intindex(r, a, b, s) rsba = ijkl2intindex(r, s, b, a) CIMatrix[ar, bs] = 2 * MOInts[rabs] - MOInts[rsba] if r == s and a == b: CIMatrix[ar, bs] += Ehf + orbe[r] - orbe[a] CIMatrix[bs, ar] = CIMatrix[ar, bs] return CIMatrix
def CISMatrix(Ints,orbs,Ehf,orbe,nocc,nvirt): "Naive implementation: Int xfrm + slow formation" # The best reference for this stuff is Chap 4 of Szabo/Ostlund # Generate the list, and the number of excitations: singles = SingleExcitations(range(nocc),range(nocc,nocc+nvirt)) nex = len(singles) # Do the four-index transformation of the 2e ints. This is expensive! MOInts = TransformInts(Ints,orbs) # Build the CI matrix using the Slater Condon rules # see Szabo/Ostlund Table 4.1 CIMatrix = zeros((nex,nex),'d') for ar in xrange(nex): a,r = singles[ar] for bs in xrange(nex): b,s = singles[bs] rabs = ijkl2intindex(r,a,b,s) rsba = ijkl2intindex(r,s,b,a) CIMatrix[ar,bs] = 2*MOInts[rabs] - MOInts[rsba] if r==s and a==b: CIMatrix[ar,bs] += Ehf+orbe[r]-orbe[a] CIMatrix[bs,ar] = CIMatrix[ar,bs] return CIMatrix
def get_k_mat(self): """ build k_pq from (11.8.8) """ try: self.h_mat except: self.h_mat = transform_one_ints(self.h,self.orbs) try: self.MOInts except: self.MOInts = TransformInts(self.ERI,self.orbs) # except: self.MOInts = TransformInts_test(self.ERI,self.orbs) self.k_mat = np.zeros((self.n_orbs,self.n_orbs)) for p,q in self.singles: for r in xrange(self.n_orbs): self.k_mat[p,q] -= 0.5*self.MOInts[ijkl2intindex(p,r,r,q)] # self.k_mat[p,q] -= 0.5*self.MOInts[p,r,r,q] self.k_mat[p,q] += self.h_mat[p,q] print "build of k_mat successful"
def get2ints(bfs,coul_func): """Store integrals in a long array in the form (ij|kl) (chemists notation. We only need i>=j, k>=l, and ij <= kl""" from array import array nbf = len(bfs) totlen = nbf*(nbf+1)*(nbf*nbf+nbf+2)/8 Ints = array('d',[0]*totlen) for i in range(nbf): for j in range(i+1): ij = i*(i+1)/2+j for k in range(nbf): for l in range(k+1): kl = k*(k+1)/2+l if ij >= kl: ijkl = ijkl2intindex(i,j,k,l) Ints[ijkl] = coulomb(bfs[i],bfs[j],bfs[k],bfs[l], coul_func) return Ints
def get2ints(bfs, coul_func): """Store integrals in a long array in the form (ij|kl) (chemists notation. We only need i>=j, k>=l, and ij <= kl""" from array import array nbf = len(bfs) totlen = nbf * (nbf + 1) * (nbf * nbf + nbf + 2) / 8 Ints = array('d', [0] * totlen) for i in range(nbf): for j in range(i + 1): ij = i * (i + 1) / 2 + j for k in range(nbf): for l in range(k + 1): kl = k * (k + 1) / 2 + l if ij >= kl: ijkl = ijkl2intindex(i, j, k, l) Ints[ijkl] = coulomb(bfs[i], bfs[j], bfs[k], bfs[l], coul_func) return Ints
def get_G_beta_ib_jb_pq(self, p, q): """ (11.8.42) """ row_index = [] column_index = [] data = [] for ib_string in self.BetaStrings.occupations: """ """ for jb_string in self.BetaStrings.occupations: row = self.BetaStrings.address(ib_string) column = self.BetaStrings.address(jb_string) elem = 0 for r, s in self.singles: """ loop over excitations """ # apply excitation operator on string: phase, e_rs_jb = e_pq_on_string(r, s, jb_string) if e_rs_jb == 0: """ tried to annihilate vaccum or to create doubly """ continue if row != self.BetaStrings.address(e_rs_jb): """ strings differed by more than the pair p q """ continue else: elem += phase * self.MOInts[ijkl2intindex(p, q, r, s)] # elem += phase*self.MOInts[p,q,r,s] if abs(elem) > 1e-14: row_index.append(row) column_index.append(column) data.append(elem) return spspa.csr_matrix( (np.array(data), (np.array(row_index), np.array(column_index))), shape=(len(self.BetaStrings.occupations), len(self.BetaStrings.occupations)))
def der2Ints(a,bset): #modified from Ints.py -> get2ints """Store integrals in a long array in the form (ij|kl) (chemists notation. We only need i>=j, k>=l, and ij <= kl""" from array import array nbf = len(bset) totlen = nbf*(nbf+1)*(nbf*nbf+nbf+2)/8 d2Ints_dXa = array('d',[0]*totlen) d2Ints_dYa = array('d',[0]*totlen) d2Ints_dZa = array('d',[0]*totlen) for i in xrange(nbf): for j in xrange(i+1): ij = i*(i+1)/2+j for k in xrange(nbf): for l in xrange(k+1): kl = k*(k+1)/2+l if ij >= kl: ijkl = ijkl2intindex(i,j,k,l) d2Ints_dXa[ijkl],d2Ints_dYa[ijkl],d2Ints_dZa[ijkl] =\ der_Jints(a,bset[i],bset[j],bset[k],bset[l]) return d2Ints_dXa,d2Ints_dYa,d2Ints_dZa
def der2Ints(a, bset): #modified from Ints.py -> get2ints """Store integrals in a long array in the form (ij|kl) (chemists notation. We only need i>=j, k>=l, and ij <= kl""" from array import array nbf = len(bset) totlen = nbf * (nbf + 1) * (nbf * nbf + nbf + 2) / 8 d2Ints_dXa = array('d', [0] * totlen) d2Ints_dYa = array('d', [0] * totlen) d2Ints_dZa = array('d', [0] * totlen) for i in xrange(nbf): for j in xrange(i + 1): ij = i * (i + 1) / 2 + j for k in xrange(nbf): for l in xrange(k + 1): kl = k * (k + 1) / 2 + l if ij >= kl: ijkl = ijkl2intindex(i, j, k, l) d2Ints_dXa[ijkl],d2Ints_dYa[ijkl],d2Ints_dZa[ijkl] =\ der_Jints(a,bset[i],bset[j],bset[k],bset[l]) return d2Ints_dXa, d2Ints_dYa, d2Ints_dZa
def get_G_beta_ib_jb_pq(self,p,q): """ (11.8.42) """ row_index=[] column_index=[] data=[] for ib_string in self.BetaStrings.occupations: """ """ for jb_string in self.BetaStrings.occupations: row = self.BetaStrings.address(ib_string) column = self.BetaStrings.address(jb_string) elem = 0 for r,s in self.singles: """ loop over excitations """ # apply excitation operator on string: phase, e_rs_jb = e_pq_on_string(r,s,jb_string) if e_rs_jb == 0: """ tried to annihilate vaccum or to create doubly """ continue if row != self.BetaStrings.address(e_rs_jb): """ strings differed by more than the pair p q """ continue else: elem += phase*self.MOInts[ijkl2intindex(p,q,r,s)] # elem += phase*self.MOInts[p,q,r,s] if abs(elem) > 1e-14: row_index.append(row) column_index.append(column) data.append(elem) return spspa.csr_matrix( (np.array(data),(np.array(row_index),np.array(column_index))), shape=(len(self.BetaStrings.occupations),len(self.BetaStrings.occupations)) )
def get_G_gamma(self, alpha_beta): """ get G_sigma matrices (11.8.33/34) gamma is alpha or beta. It is sparse! Hence is it constructed solely from the non-zero elements. """ try: self.MOInts except: self.MOInts = TransformInts(self.ERI,self.orbs) # except: self.MOInts = TransformInts_test(self.ERI,self.orbs) if alpha_beta == "alpha": Strings = self.AlphaStrings elif alpha_beta == "beta": Strings = self.BetaStrings else: raise ValueError, 'argument alpha_beta must be alpha or beta' row_index = [] column_index = [] data = [] for i_string in Strings.occupations: for j_string in Strings.occupations: row = Strings.address(i_string) column = Strings.address(j_string) elem = 0 for p,q,r,s in self.doubles: """ loop over excitations """ # apply excitation E_rs operator on string: phase_rs, e_rs_j = e_pq_on_string(r,s,j_string) if e_rs_j == 0: """ tried to annihilate vaccum or to create doubly """ continue # apply excitation E_pq operator on string: phase_pq, e_pqrs_j = e_pq_on_string(p,q,e_rs_j) if e_pqrs_j == 0: """ tried to annihilate vaccum or to create doubly """ continue if row != Strings.address(e_pqrs_j): """ strings differed by more than two pairs p q r s """ continue else: elem += 0.5 *phase_pq *phase_rs *self.MOInts[ijkl2intindex(p,q,r,s)] # elem += 0.5 *phase_pq *phase_rs *self.MOInts[p,q,r,s] ### Need to think when can exit the loop. For sure if p!=q!=r!=s # if p!=q and q!=r and r!=s: # """ there will not be another pqrs that # satisfies, exit pqrs loop """ # row_index.append(row) # column_index.append(column) # data.append(elem) # break if abs(elem) > 1e-14: row_index.append(row) column_index.append(column) data.append(elem) return spspa.csr_matrix( (np.array(data),(np.array(row_index),np.array(column_index))), shape=(len(Strings.occupations),len(Strings.occupations)) )
def EN2(molecule,**opts):# "General wrapper for the simple CI method" nalpha,nbeta = molecule.get_alphabeta() bfs = getbasis(molecule) S,h,Ints = getints(bfs,molecule) energy,(orbea,orbeb),(orbsa,orbsb) = uhf(molecule,integrals=(S,h,Ints), bfs=bfs,**opts) EHF = energy print "The Hatree-Fock energy is ",EHF #compute the transformed molecular orbital integrals aamoints, nbf = TransformInts(Ints,orbsa,orbsa, nalpha) bbmoints, nbf = TransformInts(Ints,orbsb,orbsb, nbeta) abmoints, nbf = TransformInts(Ints,orbsa,orbsb, nalpha) #Initialize the fractional occupations: Yalpha = zeros((nbf),'d') Ybeta = zeros((nbf),'d') #set up the occupied and virtual orbitals aoccs = range(nalpha) boccs = range(nbeta) avirt = range(nalpha,nbf) #numbers of alpha virtual orbitals bvirt = range(nbeta,nbf) #numbers of beta virtual orbitals ######## Computation of the primary energy correction ######### #Set initial correction terms to zero Ec1 = 0. sum = 0. z = 1. #compute correction term for two alpha electrons for a in aoccs: for b in xrange(a): for r in avirt: for s in xrange(nalpha,r): arbs = aamoints[ijkl2intindex(a,r,b,s)] asbr = aamoints[ijkl2intindex(a,s,b,r)] rraa = aamoints[ijkl2intindex(r,r,a,a)] - \ aamoints[ijkl2intindex(r,a,a,r)] rrbb = aamoints[ijkl2intindex(r,r,b,b)] - \ aamoints[ijkl2intindex(r,b,b,r)] ssaa = aamoints[ijkl2intindex(s,s,a,a)] - \ aamoints[ijkl2intindex(s,a,a,s)] ssbb = aamoints[ijkl2intindex(s,s,b,b)] - \ aamoints[ijkl2intindex(s,b,b,s)] rrss = aamoints[ijkl2intindex(r,r,s,s)] - \ aamoints[ijkl2intindex(r,s,s,r)] aabb = aamoints[ijkl2intindex(a,a,b,b)] - \ aamoints[ijkl2intindex(a,b,b,a)] eigendif = (orbea[r] + orbea[s] - orbea[a] - orbea[b]) delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) delta = eigendif + delcorr*z Eio = (arbs - asbr) x = -Eio/delta if abs(x) > 1: print "Warning a large x value has been ",\ "discovered with x = ",x x = choose(x < 1, (1,x)) x = choose(x > -1, (-1,x)) sum += x*x Yalpha[a] -= x*x Yalpha[b] -= x*x Yalpha[r] += x*x Yalpha[s] += x*x Ec1 += x*Eio #compute correction term for two beta electrons for a in boccs: for b in xrange(a): for r in bvirt: for s in xrange(nbeta,r): arbs = bbmoints[ijkl2intindex(a,r,b,s)] asbr = bbmoints[ijkl2intindex(a,s,b,r)] rraa = bbmoints[ijkl2intindex(r,r,a,a)] - \ bbmoints[ijkl2intindex(r,a,a,r)] rrbb = bbmoints[ijkl2intindex(r,r,b,b)] - \ bbmoints[ijkl2intindex(r,b,b,r)] ssaa = bbmoints[ijkl2intindex(s,s,a,a)] - \ bbmoints[ijkl2intindex(s,a,a,s)] ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \ bbmoints[ijkl2intindex(s,b,b,s)] rrss = bbmoints[ijkl2intindex(r,r,s,s)] - \ bbmoints[ijkl2intindex(r,s,s,r)] aabb = bbmoints[ijkl2intindex(a,a,b,b)] - \ bbmoints[ijkl2intindex(a,b,b,a)] eigendif = (orbeb[r] + orbeb[s] - orbeb[a] - orbeb[b]) delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) delta = eigendif + delcorr*z Eio = (arbs - asbr) x = -Eio/delta if abs(x) > 1: print "Warning a large x value has ",\ "been discovered with x = ",x x = choose(x < 1, (1,x)) x = choose(x > -1, (-1,x)) sum += x*x Ybeta[a] -= x*x Ybeta[b] -= x*x Ybeta[r] += x*x Ybeta[s] += x*x Ec1 += x*Eio #compute correction term for one alpha and one beta electron for a in aoccs: for b in boccs: for r in avirt: for s in bvirt: arbs = abmoints[ijkl2intindex(a,r,b,s)] rraa = aamoints[ijkl2intindex(r,r,a,a)] - \ aamoints[ijkl2intindex(r,a,a,r)] rrbb = abmoints[ijkl2intindex(r,r,b,b)] aass = abmoints[ijkl2intindex(a,a,s,s)] ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \ bbmoints[ijkl2intindex(s,b,b,s)] rrss = abmoints[ijkl2intindex(r,r,s,s)] aabb = abmoints[ijkl2intindex(a,a,b,b)] eigendif = (orbea[r] + orbeb[s] - orbea[a] - orbeb[b]) delcorr = (-rraa - rrbb - aass - ssbb + rrss + aabb) delta = eigendif + delcorr*z Eio = arbs x = -Eio/delta if abs(x) > 1: print "Warning a large x value has ",\ "been discovered with x = ",x x = choose(x < 1, (1,x)) x = choose(x > -1, (-1,x)) sum += x*x Yalpha[a] -= x*x Ybeta[b] -= x*x Yalpha[r] += x*x Ybeta[s] += x*x Ec1 += x*Eio #compute the fractional occupations of the occupied orbitals for a in aoccs: Yalpha[a] = 1 + Yalpha[a] for b in boccs: Ybeta[b] = 1 + Ybeta[b] #for a in xrange(nbf): #print "For alpha = ",a,"the fractional occupation is ",Yalpha[a] #print "For beta = ",a,"the fractional occupation is ",Ybeta[a] #print the energy and its corrections E = energy + Ec1 print "The total sum of excitations is ",sum print "The primary correlation correction is ",Ec1 print "The total energy is ", E return E
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)
def EN2(molecule, **kwargs): # "General wrapper for the simple CI method" nalpha, nbeta = molecule.get_alphabeta() bfs = getbasis(molecule) S, h, Ints = getints(bfs, molecule) energy, (orbea, orbeb), (orbsa, orbsb) = uhf(molecule, integrals=(S, h, Ints), bfs=bfs, **kwargs) EHF = energy print "The Hatree-Fock energy is ", EHF #compute the transformed molecular orbital integrals aamoints, nbf = TransformInts(Ints, orbsa, orbsa, nalpha) bbmoints, nbf = TransformInts(Ints, orbsb, orbsb, nbeta) abmoints, nbf = TransformInts(Ints, orbsa, orbsb, nalpha) #Initialize the fractional occupations: Yalpha = zeros((nbf), 'd') Ybeta = zeros((nbf), 'd') #set up the occupied and virtual orbitals aoccs = range(nalpha) boccs = range(nbeta) avirt = range(nalpha, nbf) #numbers of alpha virtual orbitals bvirt = range(nbeta, nbf) #numbers of beta virtual orbitals ######## Computation of the primary energy correction ######### #Set initial correction terms to zero Ec1 = 0. sum = 0. z = 1. #compute correction term for two alpha electrons for a in aoccs: for b in xrange(a): for r in avirt: for s in xrange(nalpha, r): arbs = aamoints[ijkl2intindex(a, r, b, s)] asbr = aamoints[ijkl2intindex(a, s, b, r)] rraa = aamoints[ijkl2intindex(r,r,a,a)] - \ aamoints[ijkl2intindex(r,a,a,r)] rrbb = aamoints[ijkl2intindex(r,r,b,b)] - \ aamoints[ijkl2intindex(r,b,b,r)] ssaa = aamoints[ijkl2intindex(s,s,a,a)] - \ aamoints[ijkl2intindex(s,a,a,s)] ssbb = aamoints[ijkl2intindex(s,s,b,b)] - \ aamoints[ijkl2intindex(s,b,b,s)] rrss = aamoints[ijkl2intindex(r,r,s,s)] - \ aamoints[ijkl2intindex(r,s,s,r)] aabb = aamoints[ijkl2intindex(a,a,b,b)] - \ aamoints[ijkl2intindex(a,b,b,a)] eigendif = (orbea[r] + orbea[s] - orbea[a] - orbea[b]) delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) delta = eigendif + delcorr * z Eio = (arbs - asbr) x = -Eio / delta if abs(x) > 1: print "Warning a large x value has been ",\ "discovered with x = ",x x = choose(x < 1, (1, x)) x = choose(x > -1, (-1, x)) sum += x * x Yalpha[a] -= x * x Yalpha[b] -= x * x Yalpha[r] += x * x Yalpha[s] += x * x Ec1 += x * Eio #compute correction term for two beta electrons for a in boccs: for b in xrange(a): for r in bvirt: for s in xrange(nbeta, r): arbs = bbmoints[ijkl2intindex(a, r, b, s)] asbr = bbmoints[ijkl2intindex(a, s, b, r)] rraa = bbmoints[ijkl2intindex(r,r,a,a)] - \ bbmoints[ijkl2intindex(r,a,a,r)] rrbb = bbmoints[ijkl2intindex(r,r,b,b)] - \ bbmoints[ijkl2intindex(r,b,b,r)] ssaa = bbmoints[ijkl2intindex(s,s,a,a)] - \ bbmoints[ijkl2intindex(s,a,a,s)] ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \ bbmoints[ijkl2intindex(s,b,b,s)] rrss = bbmoints[ijkl2intindex(r,r,s,s)] - \ bbmoints[ijkl2intindex(r,s,s,r)] aabb = bbmoints[ijkl2intindex(a,a,b,b)] - \ bbmoints[ijkl2intindex(a,b,b,a)] eigendif = (orbeb[r] + orbeb[s] - orbeb[a] - orbeb[b]) delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) delta = eigendif + delcorr * z Eio = (arbs - asbr) x = -Eio / delta if abs(x) > 1: print "Warning a large x value has ",\ "been discovered with x = ",x x = choose(x < 1, (1, x)) x = choose(x > -1, (-1, x)) sum += x * x Ybeta[a] -= x * x Ybeta[b] -= x * x Ybeta[r] += x * x Ybeta[s] += x * x Ec1 += x * Eio #compute correction term for one alpha and one beta electron for a in aoccs: for b in boccs: for r in avirt: for s in bvirt: arbs = abmoints[ijkl2intindex(a, r, b, s)] rraa = aamoints[ijkl2intindex(r,r,a,a)] - \ aamoints[ijkl2intindex(r,a,a,r)] rrbb = abmoints[ijkl2intindex(r, r, b, b)] aass = abmoints[ijkl2intindex(a, a, s, s)] ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \ bbmoints[ijkl2intindex(s,b,b,s)] rrss = abmoints[ijkl2intindex(r, r, s, s)] aabb = abmoints[ijkl2intindex(a, a, b, b)] eigendif = (orbea[r] + orbeb[s] - orbea[a] - orbeb[b]) delcorr = (-rraa - rrbb - aass - ssbb + rrss + aabb) delta = eigendif + delcorr * z Eio = arbs x = -Eio / delta if abs(x) > 1: print "Warning a large x value has ",\ "been discovered with x = ",x x = choose(x < 1, (1, x)) x = choose(x > -1, (-1, x)) sum += x * x Yalpha[a] -= x * x Ybeta[b] -= x * x Yalpha[r] += x * x Ybeta[s] += x * x Ec1 += x * Eio #compute the fractional occupations of the occupied orbitals for a in aoccs: Yalpha[a] = 1 + Yalpha[a] for b in boccs: Ybeta[b] = 1 + Ybeta[b] #for a in xrange(nbf): #print "For alpha = ",a,"the fractional occupation is ",Yalpha[a] #print "For beta = ",a,"the fractional occupation is ",Ybeta[a] #print the energy and its corrections E = energy + Ec1 print "The total sum of excitations is ", sum print "The primary correlation correction is ", Ec1 print "The total energy is ", E return E
def TransformInts_mpi(Ints, orbs, rank, comm, _debug_=True): """ O(N^5) 4-index transformation of the two-electron integrals. Not as efficient as it could be, since it inflates to the full rectangular matrices rather than keeping them compressed. But at least it gets the correct result. """ ''' THIS ROUTINE DOES NOT WORK THE PARALLELISATION IS HERE COMPLIATED AS THE THE FINAL RESULTS NEEDS ALL THE VALUES OF THE OUTER LOOP ALL THE time WE SHOULD FINE A WAY OF MAKING IT PARALLEL THOUGH ... PLUS THE MOINTS LOOP IS UNBALANCED WITH THE IF IJ<=kl IT NEEDS A SPECIAL TREATMENT TO DIVIDE THE LOAD ''' nbf_tot, nmo_tot = orbs.shape totlen = nmo_tot * (nmo_tot + 1) * (nmo_tot * nmo_tot + nmo_tot + 2) / 8 # number of terms per process nmo_pp = int(nmo_tot / comm.size) nbf_pp = int(nbf_tot / comm.size) # precompute the index each process takes care of mos_term = range(rank * nmo_pp, (rank + 1) * nmo_pp) bfs_term = range(rank * nbf_pp, (rank + 1) * nbf_pp) # for the inner loops we still have the full range mos = range(nmo_tot) bfs = range(nbf_tot) # special case for the last one if rank == comm.size - 1: mos_term = range(rank * nmo_pp, nmo_tot) bfs_term = range(rank * nbf_pp, nbf_tot) # actual number of terms calculated nbf = len(bfs_term) nmo = len(mos_term) # initialize the temp vectors temp = np.zeros((nbf_tot, nbf_tot, nbf_tot, nmo_tot), 'd') tempvec = np.zeros(nbf_tot, 'd') temp2 = np.zeros((nbf_tot, nbf_tot, nmo_tot, nmo_tot), 'd') if rank == 0: print '\n\t Rearrange the 2electron integrals on %d procs' % ( comm.size) print '\t There is %d BFS in the system' % (nbf_tot) print '\t', print '-' * 50 print '\t\t Proc [%03d] computes %d terms' % (rank, len(bfs_term)) t0 = time.time() ########################################## # Each proc compute a part of the temp # vector that will be assembled afterwards ########################################## # Start with (mu,nu|sigma,eta) # Unpack aoints and transform eta -> l print bfs_term for mu in bfs: for nu in bfs: for sigma in bfs: for l in mos: for eta in bfs: tempvec[eta] = Ints[ijkl2intindex(mu, nu, sigma, eta)] temp[mu, nu, sigma, l] = np.dot(orbs[:, l], tempvec) print temp # Transform sigma -> k for mu in bfs_term: for nu in bfs: for l in mos: for k in mos: temp2[mu, nu, k, l] = np.dot(orbs[:, k], temp[mu, nu, :, l]) # Transform nu -> j for mu in bfs_term: for k in mos: for l in mos: for j in mos: temp[mu, j, k, l] = np.dot(orbs[:, j], temp2[mu, :, k, l]) if _debug_: print '\t\t Calculation [%03d] of %d terms done in %f sec ' % ( rank, len(bfs_term), time.time() - t0) ########################################## # Start communication between nodes # to aggregate the values of the temp ########################################## comm.Barrier() # PROC 0 receive the data if rank == 0: if _debug_: print '\t\t Gather all the data on 0' rec_data = np.zeros((nbf_tot, nbf_tot, nbf_tot, nmo_tot), 'd') for iC in range(1, comm.size): # receive the data comm.Recv(rec_data, source=iC) rec_data[temp != 0] = 0 temp += rec_data if _debug_: print '\t\t\t Proc [%03d] : data received from [%03d]' % (0, iC) # PROC n send data else: comm.Send(temp, dest=0) # force garbage collection now if rank == 0: del rec_data ########################################## # Broadcast the values of temp to all # to finalize the transofrmation ########################################## if rank == 0 and _debug_: print '\n\t\t Broadcast the data from 0 to all procs' comm.Bcast(temp, root=0) ########################################## # Each procs process a part of MOInts # that are then aggregated ########################################## if rank == 0: print '\n\t Compute MO 2electron integrals on %d procs' % (comm.size) print '\t There is %d MO in the system' % (nmo_tot) print '\t', print '-' * 50 print '\t\t Proc [%03d] computes %d terms' % (rank, len(mos_term)) # Transform mu -> i and repack integrals: MOInts = np.zeros(totlen, 'd') 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) MOInts[ijkl] = np.dot(orbs[:, i], temp[:, j, k, l]) #force garbage collection now del temp, temp2, tempvec ########################################## # Start communication between nodes # to aggregate the values of the MOint ########################################## comm.Barrier() #print MOInts # PROC 0 receive the data if rank == 0: if _debug_: print '\t\t Gather all the data on 0' rec_data = np.zeros(totlen, 'd') for iC in range(1, comm.size): # receive the data comm.Recv(rec_data, source=iC) rec_data[MOInts != 0] = 0 MOInts += rec_data if _debug_: print '\t\t\t Proc [%03d] : data received from [%03d]' % (0, iC) # PROC n send data else: comm.Send(MOInts, dest=0) # remove the unwanted if rank == 0: del rec_data # done return MOInts
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)
def get_G_gamma(self, alpha_beta): """ get G_sigma matrices (11.8.33/34) gamma is alpha or beta. It is sparse! Hence is it constructed solely from the non-zero elements. """ try: self.MOInts except: self.MOInts = TransformInts(self.ERI, self.orbs) # except: self.MOInts = TransformInts_test(self.ERI,self.orbs) if alpha_beta == "alpha": Strings = self.AlphaStrings elif alpha_beta == "beta": Strings = self.BetaStrings else: raise ValueError, 'argument alpha_beta must be alpha or beta' row_index = [] column_index = [] data = [] for i_string in Strings.occupations: for j_string in Strings.occupations: row = Strings.address(i_string) column = Strings.address(j_string) elem = 0 for p, q, r, s in self.doubles: """ loop over excitations """ # apply excitation E_rs operator on string: phase_rs, e_rs_j = e_pq_on_string(r, s, j_string) if e_rs_j == 0: """ tried to annihilate vaccum or to create doubly """ continue # apply excitation E_pq operator on string: phase_pq, e_pqrs_j = e_pq_on_string(p, q, e_rs_j) if e_pqrs_j == 0: """ tried to annihilate vaccum or to create doubly """ continue if row != Strings.address(e_pqrs_j): """ strings differed by more than two pairs p q r s """ continue else: elem += 0.5 * phase_pq * phase_rs * self.MOInts[ ijkl2intindex(p, q, r, s)] # elem += 0.5 *phase_pq *phase_rs *self.MOInts[p,q,r,s] ### Need to think when can exit the loop. For sure if p!=q!=r!=s # if p!=q and q!=r and r!=s: # """ there will not be another pqrs that # satisfies, exit pqrs loop """ # row_index.append(row) # column_index.append(column) # data.append(elem) # break if abs(elem) > 1e-14: row_index.append(row) column_index.append(column) data.append(elem) return spspa.csr_matrix( (np.array(data), (np.array(row_index), np.array(column_index))), shape=(len(Strings.occupations), len(Strings.occupations)))