def mkQmatrix(self): #computes Q matrix which is basically density matrix weighted by the orbital eigenvalues if self.restricted: occ_orbe = self.orbe[0:self.nclosed] occ_orbs = self.orbs[:, 0:self.nclosed] Qmat = matrixmultiply( occ_orbs, matrixmultiply(diagonal_mat(occ_orbe), transpose(occ_orbs))) return Qmat if self.unrestricted: occ_orbs_A = self.orbs_a[:, 0:self.nalpha] occ_orbs_B = self.orbs_b[:, 0:self.nbeta] occ_orbe_A = self.orbe_a[0:self.nalpha] occ_orbe_B = self.orbe_b[0:self.nbeta] Qa = matrixmultiply( occ_orbs_A, matrixmultiply(diagonal_mat(occ_orbe_A), transpose(occ_orbs_A))) Qb = matrixmultiply( occ_orbs_B, matrixmultiply(diagonal_mat(occ_orbe_B), transpose(occ_orbs_B))) return Qa, Qb
def mk_auger_dens(c, occ): "Forms a density matrix from a coef matrix c and occupations in occ" #count how many states we were given nstates = occ.shape[0] D = 0.0 for i in xrange(nstates): D += occ[i]*dot( c[:,i:i+1], transpose(c[:,i:i+1])) #pad_out(D) return D
def mk_auger_dens(c, occ): "Forms a density matrix from a coef matrix c and occupations in occ" #count how many states we were given nstates = occ.shape[0] D = 0.0 for i in xrange(nstates): D += occ[i] * dot(c[:, i:i + 1], transpose(c[:, i:i + 1])) #pad_out(D) return D
def mk_auger_dens(self): "Forms a density matrix from a coef matrix c and occupations in occ" if self.restricted: nstates = self.occs.shape[0] D = 0.0 for i in range(nstates): D += self.occs[i]*dot( self.orbs[:,i:i+1], transpose(self.orbs[:,i:i+1])) #pad_out(D) return D if self.fixedocc: nastates = self.occs_a.shape[0] nbstates = self.occs_b.shape[0] Da,Db = 0.0,0.0 for i in range(nastates): Da += self.occs_a[i]*dot( self.orbs_a[:,i:i+1], transpose(self.orbs_a[:,i:i+1])) for i in range(nbstates): Db += self.occs_b[i]*dot( self.orbs_b[:,i:i+1], transpose(self.orbs_b[:,i:i+1])) return Da,Db
def mk_auger_Qmatrix(self): #computes Q matrix using occ arrays, which is basically density matrix weighted by the orbital eigenvalues if self.restricted: nstates = self.occs.shape[0] Qmat = 0.0 for i in range(nstates): Qmat += self.orbe[i]*self.occs[i]*dot( self.orbs[:,i:i+1], transpose(self.orbs[:,i:i+1])) return Qmat if self.fixedocc: nastates = self.occs_a.shape[0] nbstates = self.occs_b.shape[0] Qa,Qb = 0.0,0.0 for i in range(nastates): Qa += self.orbe_a[i]*self.occs_a[i]*dot( self.orbs_a[:,i:i+1], transpose(self.orbs_a[:,i:i+1])) for i in range(nbstates): Qb += self.orbe_a[i]*self.occs_b[i]*dot( self.orbs_b[:,i:i+1], transpose(self.orbs_b[:,i:i+1])) return Qa,Qb
def mk_auger_Qmatrix(self): #computes Q matrix using occ arrays, which is basically density matrix weighted by the orbital eigenvalues if self.restricted: nstates = self.occs.shape[0] Qmat = 0.0 for i in xrange(nstates): Qmat += self.orbe[i]*self.occs[i]*dot( self.orbs[:,i:i+1], transpose(self.orbs[:,i:i+1])) return Qmat if self.fixedocc: nastates = self.occs_a.shape[0] nbstates = self.occs_b.shape[0] Qa,Qb = 0.0,0.0 for i in xrange(nastates): Qa += self.orbe_a[i]*self.occs_a[i]*dot( self.orbs_a[:,i:i+1], transpose(self.orbs_a[:,i:i+1])) for i in xrange(nbstates): Qb += self.orbe_a[i]*self.occs_b[i]*dot( self.orbs_b[:,i:i+1], transpose(self.orbs_b[:,i:i+1])) return Qa,Qb
def mk_auger_dens(self): "Forms a density matrix from a coef matrix c and occupations in occ" if self.restricted: nstates = self.occs.shape[0] D = 0.0 for i in xrange(nstates): D += self.occs[i]*dot( self.orbs[:,i:i+1], transpose(self.orbs[:,i:i+1])) #pad_out(D) return D if self.fixedocc: nastates = self.occs_a.shape[0] nbstates = self.occs_b.shape[0] Da,Db = 0.0,0.0 for i in xrange(nastates): Da += self.occs_a[i]*dot( self.orbs_a[:,i:i+1], transpose(self.orbs_a[:,i:i+1])) for i in xrange(nbstates): Db += self.occs_b[i]*dot( self.orbs_b[:,i:i+1], transpose(self.orbs_b[:,i:i+1])) return Da,Db
def mkQmatrix(self): #computes Q matrix which is basically density matrix weighted by the orbital eigenvalues if self.restricted: occ_orbe = self.orbe[0:self.nclosed] occ_orbs = self.orbs[:,0:self.nclosed] Qmat = matrixmultiply( occ_orbs, matrixmultiply( diagonal_mat(occ_orbe), transpose(occ_orbs) ) ) return Qmat if self.unrestricted: occ_orbs_A = self.orbs_a[:,0:self.nalpha] occ_orbs_B = self.orbs_b[:,0:self.nbeta] occ_orbe_A = self.orbe_a[0:self.nalpha] occ_orbe_B = self.orbe_b[0:self.nbeta] Qa = matrixmultiply( occ_orbs_A, matrixmultiply( diagonal_mat(occ_orbe_A), transpose(occ_orbs_A) ) ) Qb = matrixmultiply( occ_orbs_B, matrixmultiply( diagonal_mat(occ_orbe_B), transpose(occ_orbs_B) ) ) return Qa,Qb
def mkdens_occs(c,occs,**kwargs): "Density matrix from a set of occupations (e.g. from FD expression)." tol = kwargs.get('tol',settings.FDOccTolerance) verbose = kwargs.get('verbose') # Determine how many orbs have occupations greater than 0 norb = 0 for fi in occs: if fi < tol: break norb += 1 if verbose: print "mkdens_occs: %d occupied orbitals found" % norb # Determine how many doubly occupied orbitals we have nclosed = 0 for i in xrange(norb): if abs(1.-occs[i]) > tol: break nclosed += 1 if verbose: print "mkdens_occs: %d closed-shell orbitals found" % nclosed D = mkdens(c,0,nclosed) for i in xrange(nclosed,norb): D = D + occs[i]*matrixmultiply(c[:,i:i+1],transpose(c[:,i:i+1])) return D
def getXC(gr,nel,**kwargs): "Form the exchange-correlation matrix" functional = kwargs.get('functional','SVWN') do_grad_dens = need_gradients[functional] do_spin_polarized = kwargs.get('do_spin_polarized') gr.floor_density() # Insure that the values of the density don't underflow gr.renormalize(nel) # Renormalize to the proper # electrons 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) 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]) # Now do the gamma-dependent part. # Fxc_a += dot(2 dfxcdgaa*graddensa + dfxcdgab*graddensb,grad(chia*chib)) # We can do the dot product as # sum_grid sum_xyz A[grid,xyz]*B[grid,xyz] # or a 2d trace product # Here A contains the dfxcdgaa stuff # B contains the grad(chia*chib) # Possible errors: gr.grad() here should be the grad of the b part? if do_grad_dens: # A,B are dimensioned (npts,3) A = transpose(0.5*transpose(gr.grad())*(weight*(2*dfxcdgaa+dfxcdgab))) for a in xrange(nbf): for b in xrange(a+1): B = gr.grad_bf_prod(a,b) Fxca[a,b] += sum(ravel(A*B)) Fxca[b,a] = Fxca[a,b] if not do_spin_polarized: return Exc,Fxca wvb = weight*dfxcdnb # Combine w*v in a vector for multiplication by bfs # First do the part that doesn't depend upon gamma Fxcb = zeros((nbf,nbf),'d') for i in xrange(nbf): wvb_i = wvb*gr.bfgrid[:,i] for j in xrange(nbf): Fxcb[i,j] = dot(wvb_i,gr.bfgrid[:,j]) # Now do the gamma-dependent part. # Fxc_b += dot(2 dfxcdgbb*graddensb + dfxcdgab*graddensa,grad(chia*chib)) # We can do the dot product as # sum_grid sum_xyz A[grid,xyz]*B[grid,xyz] # or a 2d trace product # Here A contains the dfxcdgaa stuff # B contains the grad(chia*chib) # Possible errors: gr.grad() here should be the grad of the b part? if do_grad_dens: # A,B are dimensioned (npts,3) A = transpose(0.5*transpose(gr.grad())*(weight*(2*dfxcdgbb+dfxcdgab))) for a in xrange(nbf): for b in xrange(a+1): B = gr.grad_bf_prod(a,b) Fxcb[a,b] += sum(ravel(A*B)) Fxcb[b,a] = Fxcb[a,b] return Exc,Fxca,Fxcb
def mk_B_Dmat(self, nstart, nstop): "Form a density matrix C*Ct given eigenvectors C[nstart:nstop,:]" d = self.orbs_b[:, nstart:nstop] Dmat = matrixmultiply(d, transpose(d)) return Dmat
def mk_B_Dmat(self,nstart,nstop): "Form a density matrix C*Ct given eigenvectors C[nstart:nstop,:]" d = self.orbs_b[:,nstart:nstop] Dmat = matrixmultiply(d,transpose(d)) return Dmat
def getXC(gr, nel, **kwargs): "Form the exchange-correlation matrix" functional = kwargs.get('functional', 'SVWN') do_grad_dens = need_gradients[functional] do_spin_polarized = kwargs.get('do_spin_polarized') gr.floor_density() # Insure that the values of the density don't underflow gr.renormalize(nel) # Renormalize to the proper # electrons 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) 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]) # Now do the gamma-dependent part. # Fxc_a += dot(2 dfxcdgaa*graddensa + dfxcdgab*graddensb,grad(chia*chib)) # We can do the dot product as # sum_grid sum_xyz A[grid,xyz]*B[grid,xyz] # or a 2d trace product # Here A contains the dfxcdgaa stuff # B contains the grad(chia*chib) # Possible errors: gr.grad() here should be the grad of the b part? if do_grad_dens: # A,B are dimensioned (npts,3) A = transpose(0.5 * transpose(gr.grad()) * (weight * (2 * dfxcdgaa + dfxcdgab))) for a in xrange(nbf): for b in xrange(a + 1): B = gr.grad_bf_prod(a, b) Fxca[a, b] += sum(ravel(A * B)) Fxca[b, a] = Fxca[a, b] if not do_spin_polarized: return Exc, Fxca wvb = weight * dfxcdnb # Combine w*v in a vector for multiplication by bfs # First do the part that doesn't depend upon gamma Fxcb = zeros((nbf, nbf), 'd') for i in xrange(nbf): wvb_i = wvb * gr.bfgrid[:, i] for j in xrange(nbf): Fxcb[i, j] = dot(wvb_i, gr.bfgrid[:, j]) # Now do the gamma-dependent part. # Fxc_b += dot(2 dfxcdgbb*graddensb + dfxcdgab*graddensa,grad(chia*chib)) # We can do the dot product as # sum_grid sum_xyz A[grid,xyz]*B[grid,xyz] # or a 2d trace product # Here A contains the dfxcdgaa stuff # B contains the grad(chia*chib) # Possible errors: gr.grad() here should be the grad of the b part? if do_grad_dens: # A,B are dimensioned (npts,3) A = transpose(0.5 * transpose(gr.grad()) * (weight * (2 * dfxcdgbb + dfxcdgab))) for a in xrange(nbf): for b in xrange(a + 1): B = gr.grad_bf_prod(a, b) Fxcb[a, b] += sum(ravel(A * B)) Fxcb[b, a] = Fxcb[a, b] return Exc, Fxca, Fxcb