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 run(self, n_loops, mixing_coeff = 0.5, max_time = 0 ): r""" Run the DMFT Loop with the following algorithm :: while STOP_CONDITION : self.Self_Consistency() for solver in solver_list : S.solve() self.post_solver() # defaults : does nothing where STOP_CONDITION is determined by the number of iterations. :param n_loops: Maximum number of iteration of the loop :param mixing_coeff: :param max_time: Maximum time of the loop. """ # Set up the signal # mpi.report("DMFTlab Job PID = %s"%os.getpid()) # Set the signal handler and a 5-second alarm signal.signal(signal.SIGALRM, self.handler) signal.alarm(max_time) should_continue = True while (should_continue): mpi.report("------ Node : %d -------- Iteration Number = %d"%(mpi.rank,self.Iteration_Number)) self.Self_Consistency() # call all solvers for n,sol in enumerate(self.SolverList) : if hasattr(self,"Chemical_potential") : sol.Chemical_potential=self.Chemical_potential sol.Iteration_Number=self.Iteration_Number sol.Solve() sol.Sigma = sol.Sigma * mixing_coeff + sol.Sigma_Old * (1-mixing_coeff) # post-solver processing self.post_solver() self.Iteration_Number +=1 should_continue = self.__should_continue(n_loops) # end of the while loop mpi.report("----------- END of DMFT_Loop ----------------") mpi.barrier()
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 run(self): """ """ mpi.barrier() if mpi.size==1 : # single machine. Avoid the fork while not(self.finished()): n = self.next() if n!=None : self.treate(self.the_function(n),0) return # Code for multiprocessor machines RequestList,pid = [],0 # the pid of the child on the master node_running,node_stopped= mpi.size*[False],mpi.size*[False] if mpi.rank==0 : while not(self.finished()) or pid or [n for n in node_running if n] != [] : # Treat the request which have self.finished def keep_request(r) : #if not(mpi.test(r)) : return True #if r.message !=None : self.treate(*r.message) #node_running[r.status.source] = False T = r.test() if T is None : return True value = T[0] if value !=None : self.treate(*value) node_running[T[1].source] = False return False RequestList = filter(keep_request,RequestList) # send new calculation to the nodes or "stop" them for node in [ n for n in range(1,mpi.size) if not(node_running[n] or node_stopped[n]) ] : #open('tmp','a').write("master : comm to node %d %s\n"%(node,self.finished())) mpi.send(self.finished(),node) if not(self.finished()) : mpi.send(self.next(),node) # send the data for the computation node_running[node] = True RequestList.append(mpi.irecv(node)) #Post the receive else : node_stopped[node] = True # Look if the child process on the master has self.finished. if not(pid) or os.waitpid(pid,os.WNOHANG) : if pid : RR = cPickle.load(open("res_master",'r')) if RR != None : self.treate(*RR) if not(self.finished()) : pid=os.fork(); currently_calculated_by_master = self.next() if pid==0 : # we are on the child if currently_calculated_by_master : res = self.the_function(currently_calculated_by_master) else: res = None cPickle.dump((res,mpi.rank),open('res_master','w')) os._exit(0) # Cf python doc. Used for child only. else : pid=0 if (pid): time.sleep(self.SleepTime) # so that most of the time is for the actual calculation on the master else : # not master while not(mpi.recv(0)) : # master will first send a finished flag omega = mpi.recv(0) if omega ==None : res = None else : res = self.the_function(omega) mpi.send((res,mpi.rank),0) mpi.barrier()
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