def simple_point_dens_mat(self): ntoi = self.names_to_ind[self.SO] bln = self.block_names[self.SO] MMat = [numpy.zeros( [self.n_orbitals[0][ntoi[bl]],self.n_orbitals[0][ntoi[bl]]], numpy.complex_) for bl in bln] dens_mat = [ {} for icrsh in xrange(self.n_corr_shells)] for icrsh in xrange(self.n_corr_shells): for bl in self.block_names[self.corr_shells[icrsh][4]]: dens_mat[icrsh][bl] = numpy.zeros([self.corr_shells[icrsh][3],self.corr_shells[icrsh][3]], numpy.complex_) ikarray=numpy.array(range(self.n_k)) for ik in mpi.slice_array(ikarray): unchangedsize = all( [ self.n_orbitals[ik][ntoi[bln[ib]]]==len(MMat[ib]) for ib in range(self.n_spin_blocks_gf[self.SO]) ] ) if (not unchangedsize): MMat = [numpy.zeros( [self.n_orbitals[ik][ntoi[bl]],self.n_orbitals[ik][ntoi[bl]]], numpy.complex_) for bl in bln] for ibl,bl in enumerate(bln): ind = ntoi[bl] for inu in range(self.n_orbitals[ik][ind]): if ( (self.hopping[ik][ind][inu,inu]-self.h_field*(1-2*ibl)) < 0.0): MMat[ibl][inu,inu] = 1.0 else: MMat[ibl][inu,inu] = 0.0 for icrsh in range(self.n_corr_shells): for ibn,bn in enumerate(self.block_names[self.corr_shells[icrsh][4]]): isp = self.names_to_ind[self.corr_shells[icrsh][4]][bn] #print ik, bn, isp dens_mat[icrsh][bn] += self.bz_weights[ik] * numpy.dot( numpy.dot(self.proj_mat[ik][isp][icrsh],MMat[ibn]) , self.proj_mat[ik][isp][icrsh].transpose().conjugate() ) # get data from nodes: for icrsh in range(self.n_corr_shells): for sig in dens_mat[icrsh]: dens_mat[icrsh][sig] = mpi.all_reduce(mpi.world,dens_mat[icrsh][sig],lambda x,y : x+y) mpi.barrier() if (self.symm_op!=0): dens_mat = self.Symm_corr.symmetrize(dens_mat) # Rotate to local coordinate system: if (self.use_rotations): for icrsh in xrange(self.n_corr_shells): for bn in dens_mat[icrsh]: if (self.rot_mat_time_inv[icrsh]==1): dens_mat[icrsh][bn] = dens_mat[icrsh][bn].conjugate() dens_mat[icrsh][bn] = numpy.dot( numpy.dot(self.rot_mat[icrsh].conjugate().transpose(),dens_mat[icrsh][bn]) , self.rot_mat[icrsh]) return dens_mat
def extract_G_loc(self, mu=None, with_Sigma = True): """ extracts the local downfolded Green function at the chemical potential of the class. At the end, the local G is rotated from the gloabl coordinate system to the local system. if with_Sigma = False: Sigma is not included => non-interacting local GF """ if (mu is None): mu = self.chemical_potential Gloc = [ self.Sigma_imp[icrsh].copy() for icrsh in xrange(self.n_corr_shells) ] # this list will be returned for icrsh in xrange(self.n_corr_shells): Gloc[icrsh].zero() # initialize to zero ikarray=numpy.array(range(self.n_k)) for ik in mpi.slice_array(ikarray): S = self.lattice_gf_matsubara(ik=ik,mu=mu,with_Sigma = with_Sigma) S *= self.bz_weights[ik] for icrsh in xrange(self.n_corr_shells): tmp = Gloc[icrsh].copy() # init temporary storage for sig,gf in tmp: tmp[sig] <<= self.downfold(ik,icrsh,sig,S[sig],gf) Gloc[icrsh] += tmp #collect data from mpi: for icrsh in xrange(self.n_corr_shells): Gloc[icrsh] <<= mpi.all_reduce(mpi.world,Gloc[icrsh],lambda x,y : x+y) mpi.barrier() # Gloc[:] is now the sum over k projected to the local orbitals. # here comes the symmetrisation, if needed: if (self.symm_op!=0): Gloc = self.Symm_corr.symmetrize(Gloc) # Gloc is rotated to the local coordinate system: if (self.use_rotations): for icrsh in xrange(self.n_corr_shells): for sig,gf in Gloc[icrsh]: Gloc[icrsh][sig] <<= self.rotloc(icrsh,gf,direction='toLocal') # transform to CTQMC blocks: Glocret = [ BlockGf( name_block_generator = [ (a,GfImFreq(indices = al, mesh = Gloc[0].mesh)) for a,al in self.gf_struct_solver[i] ], make_copies = False) for i in xrange(self.n_inequiv_corr_shells) ] for ish in xrange(self.n_inequiv_corr_shells): for ibl in range(len(self.gf_struct_solver[ish])): for i in range(len(self.gf_struct_solver[ish][ibl][1])): for j in range(len(self.gf_struct_solver[ish][ibl][1])): bl = self.gf_struct_solver[ish][ibl][0] ind1 = self.gf_struct_solver[ish][ibl][1][i] ind2 = self.gf_struct_solver[ish][ibl][1][j] Glocret[ish][bl][ind1,ind2] <<= Gloc[self.invshellmap[ish]][self.map_inv[ish][bl]][ind1,ind2] # return only the inequivalent shells: return Glocret
def density_gf(self,beta): """Calculates the density without setting up Gloc. It is useful for Hubbard I, and very fast.""" dens_mat = [ {} for icrsh in xrange(self.n_corr_shells)] for icrsh in xrange(self.n_corr_shells): for bl in self.block_names[self.corr_shells[icrsh][4]]: dens_mat[icrsh][bl] = numpy.zeros([self.corr_shells[icrsh][3],self.corr_shells[icrsh][3]], numpy.complex_) ikarray=numpy.array(range(self.n_k)) for ik in mpi.slice_array(ikarray): Gupf = self.lattice_gf_matsubara(ik=ik, beta=beta, mu=self.chemical_potential) Gupf *= self.bz_weights[ik] dm = Gupf.density() MMat = [dm[bl] for bl in self.block_names[self.SO]] for icrsh in range(self.n_corr_shells): for ibn,bn in enumerate(self.block_names[self.corr_shells[icrsh][4]]): isp = self.names_to_ind[self.corr_shells[icrsh][4]][bn] #print ik, bn, isp dens_mat[icrsh][bn] += numpy.dot( numpy.dot(self.proj_mat[ik][isp][icrsh],MMat[ibn]),self.proj_mat[ik][isp][icrsh].transpose().conjugate() ) # get data from nodes: for icrsh in range(self.n_corr_shells): for sig in dens_mat[icrsh]: dens_mat[icrsh][sig] = mpi.all_reduce(mpi.world,dens_mat[icrsh][sig],lambda x,y : x+y) mpi.barrier() if (self.symm_op!=0): dens_mat = self.Symm_corr.symmetrize(dens_mat) # Rotate to local coordinate system: if (self.use_rotations): for icrsh in xrange(self.n_corr_shells): for bn in dens_mat[icrsh]: if (self.rot_mat_time_inv[icrsh]==1): dens_mat[icrsh][bn] = dens_mat[icrsh][bn].conjugate() dens_mat[icrsh][bn] = numpy.dot( numpy.dot(self.rot_mat[icrsh].conjugate().transpose(),dens_mat[icrsh][bn]) , self.rot_mat[icrsh] ) return dens_mat
def total_density(self, mu): """ Calculates the total charge for the energy window for a given mu. Since in general n_orbitals depends on k, the calculation is done in the following order: G_aa'(k,iw) -> n(k) = Tr G_aa'(k,iw) -> sum_k n_k mu: chemical potential The calculation is done in the global coordinate system, if distinction is made between local/global! """ dens = 0.0 ikarray=numpy.array(range(self.n_k)) for ik in mpi.slice_array(ikarray): S = self.lattice_gf_matsubara(ik=ik,mu=mu) dens += self.bz_weights[ik] * S.total_density() # collect data from mpi: dens = mpi.all_reduce(mpi.world,dens,lambda x,y : x+y) mpi.barrier() return dens
def partial_charges(self): """Calculates the orbitally-resolved density matrix for all the orbitals considered in the input. The theta-projectors are used, hence case.parproj data is necessary""" #thingstoread = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all'] #retval = self.read_input_from_HDF(SubGrp=self.par_proj_data,thingstoread=thingstoread) retval = self.read_par_proj_input_from_hdf() if not retval: return retval if self.symm_op: self.Symm_par = Symmetry(self.hdf_file,subgroup=self.symm_par_data) # Density matrix in the window bln = self.blocnames[self.SO] ntoi = self.names_to_ind[self.SO] self.Dens_Mat_window = [ [numpy.zeros([self.shells[ish][3],self.shells[ish][3]],numpy.complex_) for ish in range(self.N_shells)] for isp in range(len(bln)) ] # init the density matrix mu = self.Chemical_Potential GFStruct_proj = [ [ (al, range(self.shells[i][3])) for al in bln ] for i in xrange(self.N_shells) ] if hasattr(self,"Sigma_imp"): Gproj = [BlockGf(name_block_generator = [ (a,GfImFreq(indices = al, mesh = self.Sigma_imp[0].mesh)) for a,al in GFStruct_proj[ish] ], make_copies = False) for ish in xrange(self.N_shells)] else: Gproj = [BlockGf(name_block_generator = [ (a,GfImFreq(indices = al, beta = 40)) for a,al in GFStruct_proj[ish] ], make_copies = False) for ish in xrange(self.N_shells)] for ish in xrange(self.N_shells): Gproj[ish].zero() ikarray=numpy.array(range(self.Nk)) #print mpi.rank, mpi.slice_array(ikarray) #print "K-Sum starts on node",mpi.rank," at ",datetime.now() for ik in mpi.slice_array(ikarray): #print mpi.rank, ik, datetime.now() S = self.latticeGF_Matsubara(ik=ik,mu=mu) S *= self.BZ_weights[ik] for ish in xrange(self.N_shells): tmp = Gproj[ish].copy() for ir in xrange(self.N_parproj[ish]): for sig,gf in tmp: tmp[sig] <<= self.downfold_pc(ik,ir,ish,sig,S[sig],gf) Gproj[ish] += tmp #print "K-Sum done on node",mpi.rank," at ",datetime.now() #collect data from mpi: for ish in xrange(self.N_shells): Gproj[ish] <<= mpi.all_reduce(mpi.world,Gproj[ish],lambda x,y : x+y) mpi.barrier() #print "Data collected on node",mpi.rank," at ",datetime.now() # Symmetrisation: if (self.symm_op!=0): Gproj = self.Symm_par.symmetrize(Gproj) #print "Symmetrisation done on node",mpi.rank," at ",datetime.now() for ish in xrange(self.N_shells): # Rotation to local: if (self.use_rotations): for sig,gf in Gproj[ish]: Gproj[ish][sig] <<= self.rotloc_all(ish,gf,direction='toLocal') isp = 0 for sig,gf in Gproj[ish]: #dmg.append(Gproj[ish].density()[sig]) self.Dens_Mat_window[isp][ish] = Gproj[ish].density()[sig] isp+=1 # add Density matrices to get the total: Dens_Mat = [ [ self.Dens_Mat_below[ntoi[bln[isp]]][ish]+self.Dens_Mat_window[isp][ish] for ish in range(self.N_shells)] for isp in range(len(bln)) ] return Dens_Mat
def dos_partial(self,broadening=0.01): """calculates the orbitally-resolved DOS""" assert hasattr(self,"Sigma_imp"), "Set Sigma First!!" #thingstoread = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all'] #retval = self.read_input_from_HDF(SubGrp=self.par_proj_data, thingstoread=thingstoread) retval = self.read_par_proj_input_from_hdf() if not retval: return retval if self.symm_op: self.Symm_par = Symmetry(self.hdf_file,subgroup=self.symm_par_data) mu = self.Chemical_Potential GFStruct_proj = [ [ (al, range(self.shells[i][3])) for al in self.blocnames[self.SO] ] for i in xrange(self.N_shells) ] Gproj = [BlockGf(name_block_generator = [ (a,GfReFreq(indices = al, mesh = self.Sigma_imp[0].mesh)) for a,al in GFStruct_proj[ish] ], make_copies = False ) for ish in xrange(self.N_shells)] for ish in range(self.N_shells): Gproj[ish].zero() Msh = [x for x in self.Sigma_imp[0].mesh] n_om = len(Msh) DOS = {} for bn in self.blocnames[self.SO]: DOS[bn] = numpy.zeros([n_om],numpy.float_) DOSproj = [ {} for ish in range(self.N_shells) ] DOSproj_orb = [ {} for ish in range(self.N_shells) ] for ish in range(self.N_shells): for bn in self.blocnames[self.SO]: dl = self.shells[ish][3] DOSproj[ish][bn] = numpy.zeros([n_om],numpy.float_) DOSproj_orb[ish][bn] = numpy.zeros([dl,dl,n_om],numpy.float_) ikarray=numpy.array(range(self.Nk)) for ik in mpi.slice_array(ikarray): S = self.lattice_gf_realfreq(ik=ik,mu=mu,broadening=broadening) S *= self.BZ_weights[ik] # non-projected DOS for iom in range(n_om): for sig,gf in S: DOS[sig][iom] += gf._data.array[:,:,iom].imag.trace()/(-3.1415926535) #projected DOS: for ish in xrange(self.N_shells): tmp = Gproj[ish].copy() for ir in xrange(self.N_parproj[ish]): for sig,gf in tmp: tmp[sig] <<= self.downfold_pc(ik,ir,ish,sig,S[sig],gf) Gproj[ish] += tmp # collect data from mpi: for sig in DOS: DOS[sig] = mpi.all_reduce(mpi.world,DOS[sig],lambda x,y : x+y) for ish in xrange(self.N_shells): Gproj[ish] <<= mpi.all_reduce(mpi.world,Gproj[ish],lambda x,y : x+y) mpi.barrier() if (self.symm_op!=0): Gproj = self.Symm_par.symmetrize(Gproj) # rotation to local coord. system: if (self.use_rotations): for ish in xrange(self.N_shells): for sig,gf in Gproj[ish]: Gproj[ish][sig] <<= self.rotloc_all(ish,gf,direction='toLocal') for ish in range(self.N_shells): for sig,gf in Gproj[ish]: for iom in range(n_om): DOSproj[ish][sig][iom] += gf._data.array[:,:,iom].imag.trace()/(-3.1415926535) DOSproj_orb[ish][sig][:,:,:] += gf._data.array[:,:,:].imag / (-3.1415926535) if (mpi.is_master_node()): # output to files for bn in self.blocnames[self.SO]: f=open('./DOScorr%s.dat'%bn, 'w') for i in range(n_om): f.write("%s %s\n"%(Msh[i],DOS[bn][i])) f.close() # partial for ish in range(self.N_shells): f=open('DOScorr%s_proj%s.dat'%(bn,ish),'w') for i in range(n_om): f.write("%s %s\n"%(Msh[i],DOSproj[ish][bn][i])) f.close() for i in range(self.shells[ish][3]): for j in range(i,self.shells[ish][3]): Fname = './DOScorr'+bn+'_proj'+str(ish)+'_'+str(i)+'_'+str(j)+'.dat' f=open(Fname,'w') for iom in range(n_om): f.write("%s %s\n"%(Msh[iom],DOSproj_orb[ish][bn][i,j,iom])) f.close()
def calc_density_correction(self,filename = 'dens_mat.dat'): """ Calculates the density correction in order to feed it back to the DFT calculations.""" assert (type(filename)==StringType), "filename has to be a string!" ntoi = self.names_to_ind[self.SO] bln = self.block_names[self.SO] # Set up deltaN: deltaN = {} for ib in bln: deltaN[ib] = [ numpy.zeros( [self.n_orbitals[ik][ntoi[ib]],self.n_orbitals[ik][ntoi[ib]]], numpy.complex_) for ik in range(self.n_k)] ikarray=numpy.array(range(self.n_k)) dens = {} for ib in bln: dens[ib] = 0.0 for ik in mpi.slice_array(ikarray): S = self.lattice_gf_matsubara(ik=ik,mu=self.chemical_potential) for sig,g in S: deltaN[sig][ik] = S[sig].density() dens[sig] += self.bz_weights[ik] * S[sig].total_density() #put mpi Barrier: for sig in deltaN: for ik in range(self.n_k): deltaN[sig][ik] = mpi.all_reduce(mpi.world,deltaN[sig][ik],lambda x,y : x+y) dens[sig] = mpi.all_reduce(mpi.world,dens[sig],lambda x,y : x+y) mpi.barrier() # now save to file: if (mpi.is_master_node()): if (self.SP==0): f=open(filename,'w') else: f=open(filename+'up','w') f1=open(filename+'dn','w') # write chemical potential (in Rydberg): f.write("%.14f\n"%(self.chemical_potential/self.energy_unit)) if (self.SP!=0): f1.write("%.14f\n"%(self.chemical_potential/self.energy_unit)) # write beta in ryderg-1 f.write("%.14f\n"%(S.beta*self.energy_unit)) if (self.SP!=0): f1.write("%.14f\n"%(S.beta*self.energy_unit)) if (self.SP==0): for ik in range(self.n_k): f.write("%s\n"%self.n_orbitals[ik][0]) for inu in range(self.n_orbitals[ik][0]): for imu in range(self.n_orbitals[ik][0]): valre = (deltaN['up'][ik][inu,imu].real + deltaN['down'][ik][inu,imu].real) / 2.0 valim = (deltaN['up'][ik][inu,imu].imag + deltaN['down'][ik][inu,imu].imag) / 2.0 f.write("%.14f %.14f "%(valre,valim)) f.write("\n") f.write("\n") f.close() elif ((self.SP==1)and(self.SO==0)): for ik in range(self.n_k): f.write("%s\n"%self.n_orbitals[ik][0]) for inu in range(self.n_orbitals[ik][0]): for imu in range(self.n_orbitals[ik][0]): f.write("%.14f %.14f "%(deltaN['up'][ik][inu,imu].real,deltaN['up'][ik][inu,imu].imag)) f.write("\n") f.write("\n") f.close() for ik in range(self.n_k): f1.write("%s\n"%self.n_orbitals[ik][1]) for inu in range(self.n_orbitals[ik][1]): for imu in range(self.n_orbitals[ik][1]): f1.write("%.14f %.14f "%(deltaN['down'][ik][inu,imu].real,deltaN['down'][ik][inu,imu].imag)) f1.write("\n") f1.write("\n") f1.close() else: for ik in range(self.n_k): f.write("%s\n"%self.n_orbitals[ik][0]) for inu in range(self.n_orbitals[ik][0]): for imu in range(self.n_orbitals[ik][0]): f.write("%.14f %.14f "%(deltaN['ud'][ik][inu,imu].real,deltaN['ud'][ik][inu,imu].imag)) f.write("\n") f.write("\n") f.close() for ik in range(self.n_k): f1.write("%s\n"%self.n_orbitals[ik][0]) for inu in range(self.n_orbitals[ik][0]): for imu in range(self.n_orbitals[ik][0]): f1.write("%.14f %.14f "%(deltaN['ud'][ik][inu,imu].real,deltaN['ud'][ik][inu,imu].imag)) f1.write("\n") f1.write("\n") f1.close() return deltaN, dens