def update_params(self, d): allparams = [ ('QMC_N_cycles_MAX', 'N_Cycles'), ('NCycles', 'N_Cycles'), ('Hloc', 'H_Local'), ('QuantumNumbers', 'Quantum_Numbers'), ('Length_One_QMC_Cycle', 'Length_Cycle'), ('Number_Warming_Iteration', 'N_Warmup_Cycles'), ('Number_Frequencies_Accumulated', 'N_Frequencies_Accumulated'), ('Global_Move', 'Global_Moves'), ('UseSegmentPicture', 'Use_Segment_Picture'), ('Proba_Move_Insert_Remove_Kink', 'Proba_Insert_Remove'), ('Proba_Move_Move_Kink', 'Proba_Move'), ('OperatorsToAverage', 'Measured_Operators'), ('OpCorrToAverage', 'Measured_Time_Correlators'), ('KeepGF_MC_series', 'Keep_Full_MC_Series'), ('DecorrelationAnalysisG_NFreq', 'Decorrelation_Analysis_G_NFreq'), ('RecordStatisticConfigurations', 'Record_Statistics_Configurations') ] issue_warning = False for (old, new) in allparams: if old in d: val = d.pop(old) d.update({new:val}) issue_warning = True msg = """ ********************************************************************************** Warning: some parameters you used have a different name now and will be deprecated in future versions. Please check the documentation. ********************************************************************************** """ if issue_warning: MPI.report(msg)
def fitTails(self): """Fits the tails using the constant value for the Re Sigma calculated from F=Sigma*G. Works only for blocks of size one.""" #if (len(self.GFStruct)==2*self.Norb): if (self.blocssizeone): spinblocs = [v for v in self.map] MPI.report("Fitting tails manually") known_coeff = numpy.zeros([1, 1, 2], numpy.float_) msh = [x.imag for x in self.G[self.map[spinblocs[0]][0]].mesh] fit_start = msh[self.Fitting_Frequency_Start] fit_stop = msh[self.N_Frequencies_Accumulated] # Fit the tail of G just to get the density for n, g in self.G: g.fitTail([[[0, 0, 1]]], 7, fit_start, 2 * fit_stop) densmat = self.G.density() for sig1 in spinblocs: for i in range(self.Norb): coeff = 0.0 for sig2 in spinblocs: for j in range(self.Norb): if (sig1 == sig2): coeff += self.U[self.offset + i, self.offset + j] * densmat[self.map[sig1] [j]][0, 0].real else: coeff += self.Up[self.offset + i, self.offset + j] * densmat[self.map[sig2] [j]][0, 0].real known_coeff[0, 0, 1] = coeff self.Sigma[self.map[sig1][i]].fitTail( fixed_coef=known_coeff, order_max=3, fit_start=fit_start, fit_stop=fit_stop) else: for n, sig in self.Sigma: known_coeff = numpy.zeros([sig.N1, sig.N2, 1], numpy.float_) msh = [x.imag for x in sig.mesh] fit_start = msh[self.Fitting_Frequency_Start] fit_stop = msh[self.N_Frequencies_Accumulated] sig.fitTail(fixed_coef=known_coeff, order_max=3, fit_start=fit_start, fit_stop=fit_stop)
def __repack(self): """Calls the h5repack routine, in order to reduce the file size of the hdf5 archive. Should only be used BEFORE the first invokation of HDF_Archive in the program, otherwise the hdf5 linking is broken!!!""" import subprocess if not (MPI.IS_MASTER_NODE()): return MPI.report("Repacking the file %s"%self.HDFfile) retcode = subprocess.call(["h5repack","-i%s"%self.HDFfile, "-otemphgfrt.h5"]) if (retcode!=0): MPI.report("h5repack failed!") else: subprocess.call(["mv","-f","temphgfrt.h5","%s"%self.HDFfile])
def read_input_from_HDF(self, SubGrp, thingstoread, optionalthings=[]): """ Reads data from the HDF file """ retval = True # init variables on all nodes: for it in thingstoread: exec "self.%s = 0" % it for it in optionalthings: exec "self.%s = 0" % it if MPI.IS_MASTER_NODE(): ar = HDF_Archive(self.HDFfile, "a") if SubGrp in ar: # first read the necessary things: for it in thingstoread: if it in ar[SubGrp]: exec "self.%s = ar['%s']['%s']" % (it, SubGrp, it) else: MPI.report("Loading %s failed!" % it) retval = False if (retval) and (len(optionalthings) > 0): # if necessary things worked, now read optional things: retval = {} for it in optionalthings: if it in ar[SubGrp]: exec "self.%s = ar['%s']['%s']" % (it, SubGrp, it) retval["%s" % it] = True else: retval["%s" % it] = False else: MPI.report("Loading failed: No %s subgroup in HDF5!" % SubGrp) retval = False del ar # now do the broadcasting: for it in thingstoread: exec "self.%s = MPI.bcast(self.%s)" % (it, it) for it in optionalthings: exec "self.%s = MPI.bcast(self.%s)" % (it, it) retval = MPI.bcast(retval) return retval
def __repack(self): """Calls the h5repack routine, in order to reduce the file size of the hdf5 archive. Should only be used BEFORE the first invokation of HDF_Archive in the program, otherwise the hdf5 linking is broken!!!""" import subprocess if not (MPI.IS_MASTER_NODE()): return MPI.report("Repacking the file %s" % self.HDFfile) retcode = subprocess.call( ["h5repack", "-i%s" % self.HDFfile, "-otemphgfrt.h5"]) if (retcode != 0): MPI.report("h5repack failed!") else: subprocess.call(["mv", "-f", "temphgfrt.h5", "%s" % self.HDFfile])
def Self_Consistency(self) : S.Transform_SymmetryBasis_toRealSpace (IN= S.Sigma, OUT = Sigma) # Embedding # Computes sum over BZ and returns density F = lambda mu : SK(mu = mu,Sigma = Sigma, Field = None ,Res = G).total_density()/4 if Density_Required : self.Chemical_potential = Dichotomy.Dichotomy(Function = F, xinit = self.Chemical_potential, yvalue =Density_Required, Precision_on_y = 0.01, Delta_x=0.5, MaxNbreLoop = 100, xname="Chemical_Potential", yname= "Total Density", verbosity = 3)[0] else: MPI.report("Total density = %.3f"%F(self.Chemical_potential)) S.Transform_RealSpace_to_SymmetryBasis (IN = G, OUT = S.G) # Extraction S.G0 = inverse(S.Sigma + inverse(S.G)) # Finally get S.G0
def run(self,N_Loops, Mixing_Coefficient = 0.5, MaxTime = 0 ): r""" Run the DMFT Loop with the following algorithm :: while STOP_CONDITION : self.Self_Consistency() for solver in Solver_List : S.solve() self.PostSolver() # 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_Coefficient: :param MaxTime: 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(MaxTime) 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_Coefficient + sol.Sigma_Old * (1-Mixing_Coefficient) # post-solver processing self.PostSolver() 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 fitTails(self): """Fits the tails using the constant value for the Re Sigma calculated from F=Sigma*G. Works only for blocks of size one.""" #if (len(self.GFStruct)==2*self.Norb): if (self.blocssizeone): spinblocs = [v for v in self.map] MPI.report("Fitting tails manually") known_coeff = numpy.zeros([1,1,2],numpy.float_) msh = [x.imag for x in self.G[self.map[spinblocs[0]][0]].mesh ] fit_start = msh[self.Fitting_Frequency_Start] fit_stop = msh[self.N_Frequencies_Accumulated] # Fit the tail of G just to get the density for n,g in self.G: g.fitTail([[[0,0,1]]],7,fit_start,2*fit_stop) densmat = self.G.density() for sig1 in spinblocs: for i in range(self.Norb): coeff = 0.0 for sig2 in spinblocs: for j in range(self.Norb): if (sig1==sig2): coeff += self.U[self.offset+i,self.offset+j] * densmat[self.map[sig1][j]][0,0].real else: coeff += self.Up[self.offset+i,self.offset+j] * densmat[self.map[sig2][j]][0,0].real known_coeff[0,0,1] = coeff self.Sigma[self.map[sig1][i]].fitTail(fixed_coef = known_coeff, order_max = 3, fit_start = fit_start, fit_stop = fit_stop) else: for n,sig in self.Sigma: known_coeff = numpy.zeros([sig.N1,sig.N2,1],numpy.float_) msh = [x.imag for x in sig.mesh] fit_start = msh[self.Fitting_Frequency_Start] fit_stop = msh[self.N_Frequencies_Accumulated] sig.fitTail(fixed_coef = known_coeff, order_max = 3, fit_start = fit_start, fit_stop = fit_stop)
def Self_Consistency(self): S.Transform_SymmetryBasis_toRealSpace(IN=S.Sigma, OUT=Sigma) # Embedding # Computes sum over BZ and returns density F = lambda mu: SK(mu=mu, Sigma=Sigma, Field=None, Res=G).total_density( ) / 4 if Density_Required: self.Chemical_potential = Dichotomy.Dichotomy( Function=F, xinit=self.Chemical_potential, yvalue=Density_Required, Precision_on_y=0.01, Delta_x=0.5, MaxNbreLoop=100, xname="Chemical_Potential", yname="Total Density", verbosity=3)[0] else: MPI.report("Total density = %.3f" % F(self.Chemical_potential)) S.Transform_RealSpace_to_SymmetryBasis(IN=G, OUT=S.G) # Extraction S.G0 = inverse(S.Sigma + inverse(S.G)) # Finally get S.G0
def __init__(self, HDFfile, mu = 0.0, hfield = 0.0, UseLDABlocs = False, LDAdata = 'SumK_LDA', Symmcorrdata = 'SymmCorr', ParProjdata = 'SumK_LDA_ParProj', Symmpardata = 'SymmPar', Bandsdata = 'SumK_LDA_Bands'): """ Initialises the class from data previously stored into an HDF5 """ if not (type(HDFfile)==StringType): MPI.report("Give a string for the HDF5 filename to read the input!") else: self.HDFfile = HDFfile self.LDAdata = LDAdata self.ParProjdata = ParProjdata self.Bandsdata = Bandsdata self.Symmpardata = Symmpardata self.Symmcorrdata = Symmcorrdata self.blocnames= [ ['up','down'], ['ud'] ] self.NspinblocsGF = [2,1] self.Gupf = None self.hfield = hfield # read input from HDF: thingstoread = ['EnergyUnit','Nk','k_dep_projection','SP','SO','charge_below','Density_Required', 'symm_op','N_shells','shells','N_corr_shells','corr_shells','use_rotations','rotmat','rotmat_timeinv','Nreps', 'dim_reps','T','N_Orbitals','Proj_Mat','BZ_weights','Hopping'] optionalthings = ['GFStruct_Solver','mapinv','map','Chemical_Potential','dc_imp','DCenerg','deg_shells'] #ar=HDF_Archive(self.HDFfile,'a') #del ar self.retval = self.read_input_from_HDF(SubGrp=self.LDAdata,thingstoread=thingstoread,optionalthings=optionalthings) #ar=HDF_Archive(self.HDFfile,'a') #del ar if (self.SO) and (abs(self.hfield)>0.000001): self.hfield=0.0 MPI.report("For SO, the external magnetic field is not implemented, setting it to 0!!") self.inequiv_shells(self.corr_shells) # determine the number of inequivalent correlated shells # field to convert blocnames to indices self.names_to_ind = [{}, {}] for ibl in range(2): for inm in range(self.NspinblocsGF[ibl]): self.names_to_ind[ibl][self.blocnames[ibl][inm]] = inm * self.SP #(self.Nspinblocs-1) # GF structure used for the local things in the k sums self.GFStruct_corr = [ [ (al, range( self.corr_shells[i][3])) for al in self.blocnames[self.corr_shells[i][4]] ] for i in xrange(self.N_corr_shells) ] if not (self.retval['GFStruct_Solver']): # No GFStruct was stored in HDF, so first set a standard one: self.GFStruct_Solver = [ [ (al, range( self.corr_shells[self.invshellmap[i]][3]) ) for al in self.blocnames[self.corr_shells[self.invshellmap[i]][4]] ] for i in xrange(self.N_inequiv_corr_shells) ] self.map = [ {} for i in xrange(self.N_inequiv_corr_shells) ] self.mapinv = [ {} for i in xrange(self.N_inequiv_corr_shells) ] for i in xrange(self.N_inequiv_corr_shells): for al in self.blocnames[self.corr_shells[self.invshellmap[i]][4]]: self.map[i][al] = [al for j in range( self.corr_shells[self.invshellmap[i]][3] ) ] self.mapinv[i][al] = al if not (self.retval['dc_imp']): # init the double counting: self.__initDC() if not (self.retval['Chemical_Potential']): self.Chemical_Potential = mu if not (self.retval['deg_shells']): self.deg_shells = [ [] for i in range(self.N_inequiv_corr_shells)] if self.symm_op: #MPI.report("Do the init for symm:") self.Symm_corr = Symmetry(HDFfile,subgroup=self.Symmcorrdata) # determine the smallest blocs, if wanted: if (UseLDABlocs): dm=self.analyse_BS() # now save things again to HDF5: if (MPI.IS_MASTER_NODE()): ar=HDF_Archive(self.HDFfile,'a') ar[self.LDAdata]['hfield'] = self.hfield del ar self.save()
def Solve(self): """ Solve the impurity problem """ # Find if an operator is in oplist def mysearch(op): l = [ k for (k,v) in OPdict.items() if (v-op).is_zero()] assert len(l) <=1 return l[0] if l else None # Same but raises an error if pb def myfind(op): r = mysearch(op) if r==None : raise "Operator %s can not be found by myfind !"%r return r # For backward compatibility self.update_params(self.__dict__) # Test all a parameters before solutions MPI.report(Parameters.check(self.__dict__,self.Required,self.Optional)) # We have to add the Hamiltonian the epsilon part of G0 if type(self.H_Local) != type(Operator()) : raise "H_Local is not an operator" H = self.H_Local for a,alpha_list in self.GFStruct : for mu in alpha_list : for nu in alpha_list : H += real(self.G0[a]._tail[2][mu,nu]) * Cdag(a,mu)*C(a,nu) OPdict = {"Hamiltonian": H} MPI.report("Hamiltonian with Eps0 term : ",H) # First separate the quantum Numbers that are operators and those which are symmetries. QuantumNumberOperators = dict( (n,op) for (n,op) in self.Quantum_Numbers.items() if type(op) == type(Operator())) QuantumNumberSymmetries = dict( (n,op) for (n,op) in self.Quantum_Numbers.items() if type(op) != type(Operator())) # Check that the quantum numbers commutes with the Hamiltonian for name,op in QuantumNumberOperators.items(): assert Commutator(self.H_Local ,op).is_zero(), "One quantum number is not commuting with Hamiltonian" OPdict[name]=op # Complete the OPdict with the fundamental operators OPdict, nf, nb, SymChar, NameOpFundamentalList = Operators.Complete_OperatorsList_with_Fundamentals(OPdict) # Add the operators to be averaged in OPdict and prepare the list for the C-code self.Measured_Operators_Results = {} self.twice_defined_Ops = {} self.Operators_To_Average_List = [] for name, op in self.Measured_Operators.items(): opn = mysearch(op) if opn == None : OPdict[name] = op self.Measured_Operators_Results[name] = 0.0 self.Operators_To_Average_List.append(name) else: MPI.report("Operator %s already defined as %s, using this instead for measuring"%(name,opn)) self.twice_defined_Ops[name] = opn self.Measured_Operators_Results[opn] = 0.0 if opn not in self.Operators_To_Average_List: self.Operators_To_Average_List.append(opn) # Time correlation functions are added self.OpCorr_To_Average_List = [] for name, op in self.Measured_Time_Correlators.items(): opn = mysearch(op[0]) if opn == None : OPdict[name] = op[0] self.OpCorr_To_Average_List.append(name) else: MPI.report("Operator %s already defined as %s, using this instead for measuring"%(name,opn)) if opn not in self.OpCorr_To_Average_List: self.OpCorr_To_Average_List.append(opn) # Create storage for data: Nops = len(self.OpCorr_To_Average_List) f = lambda L : GFBloc_ImTime(Indices= [0], Beta = self.Beta, NTimeSlices=L ) if (Nops>0): self.Measured_Time_Correlators_Results = GF(Name_Block_Generator = [ ( n,f(self.Measured_Time_Correlators[n][1]) ) for n in self.Measured_Time_Correlators], Copy=False) else: self.Measured_Time_Correlators_Results = GF(Name_Block_Generator = [ ( 'OpCorr',f(2) ) ], Copy=False) # Take care of the global moves # First, given a function (a,alpha,dagger) -> (a', alpha', dagger') # I construct a function on fundamental operators def Map_GM_to_Fund_Ops( GM ) : def f(fop) : a,alpha, dagger = fop.name + (fop.dag,) ap,alphap,daggerp = GM((a,alpha,dagger)) return Cdag(ap,alphap) if daggerp else C(ap,alphap) return f # Complete the OpList so that it is closed under the global moves while 1: added_something = False for n,(proba,GM) in enumerate(self.Global_Moves): # F is a function that map all operators according to the global move F = Extend_Function_on_Fundamentals(Map_GM_to_Fund_Ops(GM)) # Make sure that OPdict is complete, i.e. all images of OPdict operators are in OPdict for name,op in OPdict.items() : op_im = F(op) if mysearch(op_im)==None : # find the key and put in in the dictionnary i=0 while 1: new_name = name + 'GM' + i*'_' + "%s"%n if new_name not in OPdict : break added_something = True OPdict[new_name] = op_im # break the while loop if not added_something: break # Now I have all operators, I make the transcription of the global moves self.Global_Moves_Mapping_List = [] for n,(proba,GM) in enumerate(self.Global_Moves): F = Extend_Function_on_Fundamentals(Map_GM_to_Fund_Ops(GM)) m = {} for name,op in OPdict.items() : op_im = F(op) n1,n2 = myfind(op),myfind(op_im) m[n1] = n2 name = "%s"%n self.Global_Moves_Mapping_List.append((proba,m,name)) #MPI.report ("Global_Moves_Mapping_List", self.Global_Moves_Mapping_List) # Now add the operator for F calculation if needed if self.Use_F : Hloc_WithoutQuadratic = self.H_Local.RemoveQuadraticTerms() for n,op in OPdict.items() : if op.is_Fundamental(): op2 = Commutator(Hloc_WithoutQuadratic,op) if not mysearch(op2) : OPdict["%s_Comm_Hloc"%n] = op2 # All operators have real coefficients. Check this and remove the 0j term # since the C++ expects operators with real numbers for n,op in OPdict.items(): op.make_coef_real_and_check() # Transcription of operators for C++ Oplist2 = Operators.Transcribe_OpList_for_C(OPdict) SymList = [sym for (n,sym) in SymChar.items() if n in QuantumNumberSymmetries] self.H_diag = C_Module.Hloc(nf,nb,Oplist2,QuantumNumberOperators,SymList,self.Quantum_Numbers_Selection,0) # Create the C_Cag_Ops array which describes the grouping of (C,Cdagger) operator # for the MonteCarlo moves : (a, alpha) block structure [ [ (C_name, Cdag_name)]] self.C_Cdag_Ops = [ [ (myfind(C(a,alpha)), myfind(Cdag(a,alpha))) for alpha in al ] for a,al in self.GFStruct] # Define G0_inv and correct it to have G0 to have perfect 1/omega behavior self.G0_inv = inverse(self.G0) Delta = self.G0_inv.Delta() for n,g in self.G0_inv: assert(g.N1==g.N2) identity=numpy.identity(g.N1) self.G0[n] <<= GF_Initializers.A_Omega_Plus_B(identity, g._tail[0]) self.G0[n] -= Delta[n] #self.G0[n] <<= iOmega_n + g._tail[0] - Delta[n] self.G0_inv <<= self.G0 self.G0.invert() # Construct the function in tau f = lambda g,L : GFBloc_ImTime(Indices= g.Indices, Beta = g.Beta, NTimeSlices=L ) self.Delta_tau = GF(Name_Block_Generator = [ (n,f(g,self.N_Time_Slices_Delta) ) for n,g in self.G], Copy=False, Name='D') self.G_tau = GF(Name_Block_Generator = [ (n,f(g,self.N_Time_Slices_Gtau) ) for n,g in self.G], Copy=False, Name='G') self.F_tau = GF(Name_Block_Generator = self.G_tau, Copy=True, Name='F') for (i,gt) in self.Delta_tau : gt.setFromInverseFourierOf(Delta[i]) MPI.report("Inv Fourier done") if (self.Legendre_Accumulation): self.G_Legendre = GF(Name_Block_Generator = [ (n,GFBloc_ImLegendre(Indices=g.Indices, Beta=g.Beta, NLegendreCoeffs=self.N_Legendre_Coeffs) ) for n,g in self.G], Copy=False, Name='Gl') else: self.G_Legendre = GF(Name_Block_Generator = [ (n,GFBloc_ImLegendre(Indices=[1], Beta=g.Beta, NLegendreCoeffs=1) ) for n,g in self.G], Copy=False, Name='Gl') # G_Legendre must not be empty but is not needed in this case. So I make it as small as possible. # Starting the C++ code self.Sigma_Old <<= self.Sigma C_Module.MC_solve(self.__dict__ ) # C++ solver # Compute G on Matsubara axis possibly fitting the tail if self.Legendre_Accumulation: for s,g in self.G: identity=numpy.zeros([g.N1,g.N2],numpy.float) for i,m in enumerate (g._IndicesL): for j,n in enumerate (g._IndicesR): if m==n: identity[i,j]=1 self.G_Legendre[s].enforce_discontinuity(identity) # set the known tail g <<= LegendreToMatsubara(self.G_Legendre[s]) else: if (self.Time_Accumulation): for name, g in self.G_tau: identity=numpy.zeros([g.N1,g.N2],numpy.float) for i,m in enumerate (g._IndicesL): for j,n in enumerate (g._IndicesR): if m==n: identity[i,j]=1 g._tail.zero() g._tail[1] = identity self.G[name].setFromFourierOf(g) # This is very sick... but what can we do??? self.Sigma <<= self.G0_inv - inverse(self.G) self.fitTails() self.G <<= inverse(self.G0_inv - self.Sigma) # Now find the self-energy self.Sigma <<= self.G0_inv - inverse(self.G) MPI.report("Solver %(Name)s has ended."%self.__dict__) # for operator averages: if twice defined operator, rename output: for op1,op2 in self.twice_defined_Ops.items(): self.Measured_Operators_Results[op1] = self.Measured_Operators_Results[op2] for op1,op2 in self.twice_defined_Ops.items(): if op2 in self.Measured_Operators_Results.keys(): del self.Measured_Operators_Results[op2] if self.Use_F : for (n,f) in self.F: f.setFromFourierOf(self.F_tau[n]) self.G2 = self.G0 + self.G0 * self.F self.Sigma2 = self.F * inverse(self.G2)
def convert_DMFT_input(self): """ Reads the input files, and stores the data in the HDFfile """ if not (MPI.IS_MASTER_NODE()): return # do it only on master: MPI.report("Reading input from %s..."%self.LDA_file) # Read and write only on Master!!! # R is a generator : each R.Next() will return the next number in the file R = Read_Fortran_File(self.LDA_file) try: EnergyUnit = R.next() # read the energy convertion factor Nk = int(R.next()) # read the number of k points k_dep_projection = 1 SP = int(R.next()) # flag for spin-polarised calculation SO = int(R.next()) # flag for spin-orbit calculation charge_below = R.next() # total charge below energy window Density_Required = R.next() # total density required, for setting the chemical potential symm_op = 1 # Use symmetry groups for the k-sum # the information on the non-correlated shells is not important here, maybe skip: N_shells = int(R.next()) # number of shells (e.g. Fe d, As p, O p) in the unit cell, # corresponds to index R in formulas # now read the information about the shells: shells = [ [ int(R.next()) for i in range(4) ] for icrsh in range(N_shells) ] # reads iatom, sort, l, dim N_corr_shells = int(R.next()) # number of corr. shells (e.g. Fe d, Ce f) in the unit cell, # corresponds to index R in formulas # now read the information about the shells: corr_shells = [ [ int(R.next()) for i in range(6) ] for icrsh in range(N_corr_shells) ] # reads iatom, sort, l, dim, SO flag, irep self.inequiv_shells(corr_shells) # determine the number of inequivalent correlated shells, has to be known for further reading... use_rotations = 1 rotmat = [numpy.identity(corr_shells[icrsh][3],numpy.complex_) for icrsh in xrange(N_corr_shells)] # read the matrices rotmat_timeinv = [0 for i in range(N_corr_shells)] for icrsh in xrange(N_corr_shells): for i in xrange(corr_shells[icrsh][3]): # read real part: for j in xrange(corr_shells[icrsh][3]): rotmat[icrsh][i,j] = R.next() for i in xrange(corr_shells[icrsh][3]): # read imaginary part: for j in xrange(corr_shells[icrsh][3]): rotmat[icrsh][i,j] += 1j * R.next() if (SP==1): # read time inversion flag: rotmat_timeinv[icrsh] = int(R.next()) # Read here the infos for the transformation of the basis: Nreps = [1 for i in range(self.N_inequiv_corr_shells)] dim_reps = [0 for i in range(self.N_inequiv_corr_shells)] T = [] for icrsh in range(self.N_inequiv_corr_shells): Nreps[icrsh] = int(R.next()) # number of representatives ("subsets"), e.g. t2g and eg dim_reps[icrsh] = [int(R.next()) for i in range(Nreps[icrsh])] # dimensions of the subsets # The transformation matrix: # it is of dimension 2l+1, if no SO, and 2*(2l+1) with SO!! #T = [] #for ish in xrange(self.N_inequiv_corr_shells): ll = 2*corr_shells[self.invshellmap[icrsh]][2]+1 lmax = ll * (corr_shells[self.invshellmap[icrsh]][4] + 1) T.append(numpy.zeros([lmax,lmax],numpy.complex_)) # now read it from file: for i in xrange(lmax): for j in xrange(lmax): T[icrsh][i,j] = R.next() for i in xrange(lmax): for j in xrange(lmax): T[icrsh][i,j] += 1j * R.next() # Spin blocks to be read: Nspinblocs = SP + 1 - SO # number of spins to read for Norbs and Ham, NOT Projectors # read the list of N_Orbitals for all k points N_Orbitals = [ [0 for isp in range(Nspinblocs)] for ik in xrange(Nk)] for isp in range(Nspinblocs): for ik in xrange(Nk): N_Orbitals[ik][isp] = int(R.next()) #print N_Orbitals # Initialise the projectors: Proj_Mat = [ [ [numpy.zeros([corr_shells[icrsh][3], N_Orbitals[ik][isp]], numpy.complex_) for icrsh in range (N_corr_shells)] for isp in range(Nspinblocs)] for ik in range(Nk) ] # Read the projectors from the file: for ik in xrange(Nk): for icrsh in range(N_corr_shells): no = corr_shells[icrsh][3] # first Real part for BOTH spins, due to conventions in dmftproj: for isp in range(Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i,j] = R.next() # now Imag part: for isp in range(Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i,j] += 1j * R.next() # now define the arrays for weights and hopping ... BZ_weights = numpy.ones([Nk],numpy.float_)/ float(Nk) # w(k_index), default normalisation Hopping = [ [numpy.zeros([N_Orbitals[ik][isp],N_Orbitals[ik][isp]],numpy.complex_) for isp in range(Nspinblocs)] for ik in xrange(Nk) ] # weights in the file for ik in xrange(Nk) : BZ_weights[ik] = R.next() # if the sum over spins is in the weights, take it out again!! sm = sum(BZ_weights) BZ_weights[:] /= sm # Grab the H # we use now the convention of a DIAGONAL Hamiltonian!!!! for isp in range(Nspinblocs): for ik in xrange(Nk) : no = N_Orbitals[ik][isp] for i in xrange(no): Hopping[ik][isp][i,i] = R.next() * EnergyUnit #keep some things that we need for reading parproj: self.N_shells = N_shells self.shells = shells self.N_corr_shells = N_corr_shells self.corr_shells = corr_shells self.Nspinblocs = Nspinblocs self.N_Orbitals = N_Orbitals self.Nk = Nk self.SO = SO self.SP = SP self.EnergyUnit = EnergyUnit except StopIteration : # a more explicit error if the file is corrupted. raise "SumK_LDA : reading file HMLT_file failed!" R.close() #print Proj_Mat[0] #----------------------------------------- # Store the input into HDF5: ar = HDF_Archive(self.HDFfile,'a') if not (self.LDASubGrp in ar): ar.create_group(self.LDASubGrp) # The subgroup containing the data. If it does not exist, it is created. # If it exists, the data is overwritten!!! ar[self.LDASubGrp]['EnergyUnit'] = EnergyUnit ar[self.LDASubGrp]['Nk'] = Nk ar[self.LDASubGrp]['k_dep_projection'] = k_dep_projection ar[self.LDASubGrp]['SP'] = SP ar[self.LDASubGrp]['SO'] = SO ar[self.LDASubGrp]['charge_below'] = charge_below ar[self.LDASubGrp]['Density_Required'] = Density_Required ar[self.LDASubGrp]['symm_op'] = symm_op ar[self.LDASubGrp]['N_shells'] = N_shells ar[self.LDASubGrp]['shells'] = shells ar[self.LDASubGrp]['N_corr_shells'] = N_corr_shells ar[self.LDASubGrp]['corr_shells'] = corr_shells ar[self.LDASubGrp]['use_rotations'] = use_rotations ar[self.LDASubGrp]['rotmat'] = rotmat ar[self.LDASubGrp]['rotmat_timeinv'] = rotmat_timeinv ar[self.LDASubGrp]['Nreps'] = Nreps ar[self.LDASubGrp]['dim_reps'] = dim_reps ar[self.LDASubGrp]['T'] = T ar[self.LDASubGrp]['N_Orbitals'] = N_Orbitals ar[self.LDASubGrp]['Proj_Mat'] = Proj_Mat ar[self.LDASubGrp]['BZ_weights'] = BZ_weights ar[self.LDASubGrp]['Hopping'] = Hopping del ar # Symmetries are used, # Now do the symmetries for correlated orbitals: self.read_Symmetry_input(orbits=corr_shells,symmfile=self.Symm_file,SymmSubGrp=self.SymmSubGrp,SO=SO,SP=SP)
def Solve(self,Iteration_Number=1,Test_Convergence=0.0001): """Calculation of the impurity Greens function using Hubbard-I""" # Test all a parameters before solutions print Parameters.check(self.__dict__,self.Required,self.Optional) #Solver_Base.Solve(self,is_last_iteration,Iteration_Number,Test_Convergence) if self.Converged : MPI.report("Solver %(Name)s has already converted: SKIPPING"%self.__dict__) return self.__save_eal('eal.dat',Iteration_Number) MPI.report( "Starting Fortran solver %(Name)s"%self.__dict__) self.Sigma_Old <<= self.Sigma self.G_Old <<= self.G # call the fortran solver: temp = 1.0/self.Beta gf,tail,self.atocc,self.atmag = gf_hi_fullu(e0f=self.ealmat, ur=self.ur, umn=self.umn, ujmn=self.ujmn, zmsb=self.zmsb, nmom=self.Nmoments, ns=self.Nspin, temp=temp, verbosity = self.Verbosity) #self.sig = sigma_atomic_fullu(gf=self.gf,e0f=self.eal,zmsb=self.zmsb,ns=self.Nspin,nlm=self.Nlm) if (self.Verbosity==0): # No fortran output, so give basic results here MPI.report("Atomic occupancy in Hubbard I Solver : %s"%self.atocc) MPI.report("Atomic magn. mom. in Hubbard I Solver : %s"%self.atmag) # transfer the data to the GF class: if (self.UseSpinOrbit): nlmtot = self.Nlm*2 # only one block in this case! else: nlmtot = self.Nlm M={} isp=-1 for a,al in self.GFStruct: isp+=1 #M[a] = gf[isp*self.Nlm:(isp+1)*self.Nlm,isp*self.Nlm:(isp+1)*self.Nlm,:] M[a] = gf[isp*nlmtot:(isp+1)*nlmtot,isp*nlmtot:(isp+1)*nlmtot,:] for i in range(min(self.Nmoments,10)): self.tailtempl[a][i+1].array[:] = tail[i][isp*nlmtot:(isp+1)*nlmtot,isp*nlmtot:(isp+1)*nlmtot] glist = lambda : [ GFBloc_ImFreq(Indices = al, Beta = self.Beta, NFreqMatsubara = self.Nmsb, Data=M[a], Tail=self.tailtempl[a]) for a,al in self.GFStruct] self.G = GF(NameList = self.a_list, BlockList = glist(),Copy=False) # Self energy: self.G0 <<= GF_Initializers.A_Omega_Plus_B(A=1,B=0.0) M = [ self.ealmat[isp*nlmtot:(isp+1)*nlmtot,isp*nlmtot:(isp+1)*nlmtot] for isp in range((2*self.Nlm)/nlmtot) ] self.G0 -= M self.Sigma <<= self.G0 - inverse(self.G) # invert G0 self.G0.invert() def test_distance(G1,G2, dist) : def f(G1,G2) : print abs(G1._data.array - G2._data.array) dS = max(abs(G1._data.array - G2._data.array).flatten()) aS = max(abs(G1._data.array).flatten()) return dS <= aS*dist return reduce(lambda x,y : x and y, [f(g1,g2) for (i1,g1),(i2,g2) in izip(G1,G2)]) MPI.report("\nChecking Sigma for convergence...\nUsing tolerance %s"%Test_Convergence) self.Converged = test_distance(self.Sigma,self.Sigma_Old,Test_Convergence) if self.Converged : MPI.report("Solver HAS CONVERGED") else : MPI.report("Solver has not yet converged")
def read_Symmetry_input(self,orbits,symmfile,SymmSubGrp,SO,SP): """ Reads input for the symmetrisations from symmfile, which is case.sympar or case.symqmc. """ if not (MPI.IS_MASTER_NODE()): return MPI.report("Reading symmetry input from %s..."%symmfile) N_orbits = len(orbits) R=Read_Fortran_File(symmfile) try: Ns = int(R.next()) # Number of symmetry operations Natoms = int(R.next()) # number of atoms involved perm = [ [int(R.next()) for i in xrange(Natoms)] for j in xrange(Ns) ] # list of permutations of the atoms if SP: timeinv = [ int(R.next()) for j in xrange(Ns) ] # timeinversion for SO xoupling else: timeinv = [ 0 for j in xrange(Ns) ] # Now read matrices: mat = [] for iNs in xrange(Ns): mat.append( [ numpy.zeros([orbits[orb][3], orbits[orb][3]],numpy.complex_) for orb in xrange(N_orbits) ] ) for orb in range(N_orbits): for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat[iNs][orb][i,j] = R.next() # real part for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat[iNs][orb][i,j] += 1j * R.next() # imaginary part # determine the inequivalent shells: #SHOULD BE FINALLY REMOVED, PUT IT FOR ALL ORBITALS!!!!! #self.inequiv_shells(orbits) mat_tinv = [numpy.identity(orbits[orb][3],numpy.complex_) for orb in range(N_orbits)] if ((SO==0) and (SP==0)): # here we need an additional time inversion operation, so read it: for orb in range(N_orbits): for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat_tinv[orb][i,j] = R.next() # real part for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat_tinv[orb][i,j] += 1j * R.next() # imaginary part except StopIteration : # a more explicit error if the file is corrupted. raise "Symmetry : reading file failed!" R.close() # Save it to the HDF: ar=HDF_Archive(self.HDFfile,'a') if not (SymmSubGrp in ar): ar.create_group(SymmSubGrp) thingstowrite = ['Ns','Natoms','perm','orbits','SO','SP','timeinv','mat','mat_tinv'] for it in thingstowrite: exec "ar['%s']['%s'] = %s"%(SymmSubGrp,it,it) del ar
def convert_Parproj_input(self, ParProjSubGrp='SumK_LDA_ParProj', SymmParSubGrp='SymmPar'): """ Reads the input for the partial charges projectors from case.parproj, and stores it in the SymmParSubGrp group in the HDF5. """ if not (MPI.IS_MASTER_NODE()): return self.ParProjSubGrp = ParProjSubGrp self.SymmParSubGrp = SymmParSubGrp MPI.report("Reading parproj input from %s..." % self.Parproj_file) Dens_Mat_below = [[ numpy.zeros([self.shells[ish][3], self.shells[ish][3]], numpy.complex_) for ish in range(self.N_shells) ] for isp in range(self.Nspinblocs)] R = Read_Fortran_File(self.Parproj_file) #try: N_parproj = [int(R.next()) for i in range(self.N_shells)] # Initialise P, here a double list of matrices: Proj_Mat_pc = [[[[ numpy.zeros([self.shells[ish][3], self.N_Orbitals[ik][isp]], numpy.complex_) for ir in range(N_parproj[ish]) ] for ish in range(self.N_shells)] for isp in range(self.Nspinblocs)] for ik in range(self.Nk)] rotmat_all = [ numpy.identity(self.shells[ish][3], numpy.complex_) for ish in xrange(self.N_shells) ] rotmat_all_timeinv = [0 for i in range(self.N_shells)] for ish in range(self.N_shells): #print ish # read first the projectors for this orbital: for ik in xrange(self.Nk): for ir in range(N_parproj[ish]): for isp in range(self.Nspinblocs): for i in xrange( self.shells[ish][3]): # read real part: for j in xrange(self.N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][i, j] = R.next() for isp in range(self.Nspinblocs): for i in xrange( self.shells[ish][3]): # read imaginary part: for j in xrange(self.N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][ i, j] += 1j * R.next() # now read the Density Matrix for this orbital below the energy window: for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read real part: for j in xrange(self.shells[ish][3]): Dens_Mat_below[isp][ish][i, j] = R.next() for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read imaginary part: for j in xrange(self.shells[ish][3]): Dens_Mat_below[isp][ish][i, j] += 1j * R.next() if (self.SP == 0): Dens_Mat_below[isp][ish] /= 2.0 # Global -> local rotation matrix for this shell: for i in xrange(self.shells[ish][3]): # read real part: for j in xrange(self.shells[ish][3]): rotmat_all[ish][i, j] = R.next() for i in xrange(self.shells[ish][3]): # read imaginary part: for j in xrange(self.shells[ish][3]): rotmat_all[ish][i, j] += 1j * R.next() #print Dens_Mat_below[0][ish],Dens_Mat_below[1][ish] if (self.SP): rotmat_all_timeinv[ish] = int(R.next()) #except StopIteration : # a more explicit error if the file is corrupted. # raise "SumK_LDA_Wien2k_input: reading file for Projectors failed!" R.close() #----------------------------------------- # Store the input into HDF5: ar = HDF_Archive(self.HDFfile, 'a') if not (self.ParProjSubGrp in ar): ar.create_group(self.ParProjSubGrp) # The subgroup containing the data. If it does not exist, it is created. # If it exists, the data is overwritten!!! thingstowrite = [ 'Dens_Mat_below', 'N_parproj', 'Proj_Mat_pc', 'rotmat_all', 'rotmat_all_timeinv' ] for it in thingstowrite: exec "ar['%s']['%s'] = %s" % (self.ParProjSubGrp, it, it) del ar # Symmetries are used, # Now do the symmetries for all orbitals: self.read_Symmetry_input(orbits=self.shells, symmfile=self.Symmpar_file, SymmSubGrp=self.SymmParSubGrp, SO=self.SO, SP=self.SP)
def __init__(self, Beta, Norb, U_interact=None, J_Hund=None, GFStruct=False, map=False, use_spinflip=False, useMatrix=True, l=2, T=None, dimreps=None, irep=None, deg_orbs=[], Sl_Int=None): self.offset = 0 self.use_spinflip = use_spinflip self.Norb = Norb if (useMatrix): if not (Sl_Int is None): Umat = Umatrix(l=l) assert len(Sl_Int) == (l + 1), "Sl_Int has the wrong length" if (type(Sl_Int) == ListType): Rcl = numpy.array(Sl_Int) else: Rcl = Sl_Int Umat(T=T, Rcl=Rcl) else: if ((U_interact == None) and (J_Hund == None)): MPI.report("Give U,J or Slater integrals!!!") assert 0 Umat = Umatrix(U_interact=U_interact, J_Hund=J_Hund, l=l) Umat(T=T) Umat.ReduceMatrix() if (Umat.N == Umat.Nmat): # Transformation T is of size 2l+1 self.U = Umat.U self.Up = Umat.Up else: # Transformation is of size 2(2l+1) self.U = Umat.U # now we have the reduced matrices U and Up, we need it for tail fitting anyways if (use_spinflip): #Take the 4index Umatrix # check for imaginary matrix elements: if (abs(Umat.Ufull.imag) > 0.0001).any(): MPI.report( "WARNING: complex interaction matrix!! Ignoring imaginary part for the moment!" ) MPI.report( "If you want to change this, look into Wien2k/Solver_MultiBand.py" ) self.U4ind = Umat.Ufull.real # this will be changed for arbitrary irep: # use only one subgroup of orbitals? if not (irep is None): #print irep, dimreps assert not (dimreps is None ), "Dimensions of the representatives are missing!" assert Norb == dimreps[ irep - 1], "Dimensions of dimrep and Norb do not fit!" for ii in range(irep - 1): self.offset += dimreps[ii] else: if ((U_interact == None) and (J_Hund == None)): MPI.report("For Kanamori representation, give U and J!!") assert 0 self.U = numpy.zeros([Norb, Norb], numpy.float_) self.Up = numpy.zeros([Norb, Norb], numpy.float_) for i in range(Norb): for j in range(Norb): if (i == j): self.Up[i, i] = U_interact + 2.0 * J_Hund else: self.Up[i, j] = U_interact self.U[i, j] = U_interact - J_Hund if (GFStruct): assert map, "give also the mapping!" self.map = map else: # standard GFStruct and map GFStruct = [('%s' % (ud), [n for n in range(Norb)]) for ud in ['up', 'down']] self.map = { 'up': ['up' for v in range(self.Norb)], 'down': ['down' for v in range(self.Norb)] } #print GFStruct,self.map if (use_spinflip == False): Hamiltonian = self.__setHamiltonian_density() else: if (useMatrix): Hamiltonian = self.__setfullHamiltonian_Slater() else: Hamiltonian = self.__setfullHamiltonian_Kanamori(J_Hund=J_Hund) Quantum_Numbers = self.__setQuantumNumbers(GFStruct) # Determine if there are only blocs of size 1: self.blocssizeone = True for ib in GFStruct: if (len(ib[1]) > 1): self.blocssizeone = False # now initialize the solver with the stuff given above: Solver.__init__(self, Beta=Beta, GFstruct=GFStruct, H_Local=Hamiltonian, Quantum_Numbers=Quantum_Numbers) #self.SetGlobalMoves(deg_orbs) self.N_Cycles = 10000 self.Nmax_Matrix = 100 self.N_Time_Slices_Delta = 10000 #if ((len(GFStruct)==2*Norb) and (use_spinflip==False)): if ((self.blocssizeone) and (use_spinflip == False)): self.Use_Segment_Picture = True else: self.Use_Segment_Picture = False
def __init__( self, HDFfile, mu=0.0, hfield=0.0, UseLDABlocs=False, LDAdata="SumK_LDA", Symmcorrdata="SymmCorr", ParProjdata="SumK_LDA_ParProj", Symmpardata="SymmPar", Bandsdata="SumK_LDA_Bands", ): """ Initialises the class from data previously stored into an HDF5 """ if not (type(HDFfile) == StringType): MPI.report("Give a string for the HDF5 filename to read the input!") else: self.HDFfile = HDFfile self.LDAdata = LDAdata self.ParProjdata = ParProjdata self.Bandsdata = Bandsdata self.Symmpardata = Symmpardata self.Symmcorrdata = Symmcorrdata self.blocnames = [["up", "down"], ["ud"]] self.NspinblocsGF = [2, 1] self.Gupf = None self.hfield = hfield # read input from HDF: thingstoread = [ "EnergyUnit", "Nk", "k_dep_projection", "SP", "SO", "charge_below", "Density_Required", "symm_op", "N_shells", "shells", "N_corr_shells", "corr_shells", "use_rotations", "rotmat", "rotmat_timeinv", "Nreps", "dim_reps", "T", "N_Orbitals", "Proj_Mat", "BZ_weights", "Hopping", ] optionalthings = [ "GFStruct_Solver", "mapinv", "map", "Chemical_Potential", "dc_imp", "DCenerg", "deg_shells", ] # ar=HDF_Archive(self.HDFfile,'a') # del ar self.retval = self.read_input_from_HDF( SubGrp=self.LDAdata, thingstoread=thingstoread, optionalthings=optionalthings ) # ar=HDF_Archive(self.HDFfile,'a') # del ar if (self.SO) and (abs(self.hfield) > 0.000001): self.hfield = 0.0 MPI.report("For SO, the external magnetic field is not implemented, setting it to 0!!") self.inequiv_shells(self.corr_shells) # determine the number of inequivalent correlated shells # field to convert blocnames to indices self.names_to_ind = [{}, {}] for ibl in range(2): for inm in range(self.NspinblocsGF[ibl]): self.names_to_ind[ibl][self.blocnames[ibl][inm]] = inm * self.SP # (self.Nspinblocs-1) # GF structure used for the local things in the k sums self.GFStruct_corr = [ [(al, range(self.corr_shells[i][3])) for al in self.blocnames[self.corr_shells[i][4]]] for i in xrange(self.N_corr_shells) ] if not (self.retval["GFStruct_Solver"]): # No GFStruct was stored in HDF, so first set a standard one: self.GFStruct_Solver = [ [ (al, range(self.corr_shells[self.invshellmap[i]][3])) for al in self.blocnames[self.corr_shells[self.invshellmap[i]][4]] ] for i in xrange(self.N_inequiv_corr_shells) ] self.map = [{} for i in xrange(self.N_inequiv_corr_shells)] self.mapinv = [{} for i in xrange(self.N_inequiv_corr_shells)] for i in xrange(self.N_inequiv_corr_shells): for al in self.blocnames[self.corr_shells[self.invshellmap[i]][4]]: self.map[i][al] = [al for j in range(self.corr_shells[self.invshellmap[i]][3])] self.mapinv[i][al] = al if not (self.retval["dc_imp"]): # init the double counting: self.__initDC() if not (self.retval["Chemical_Potential"]): self.Chemical_Potential = mu if not (self.retval["deg_shells"]): self.deg_shells = [[] for i in range(self.N_inequiv_corr_shells)] if self.symm_op: # MPI.report("Do the init for symm:") self.Symm_corr = Symmetry(HDFfile, subgroup=self.Symmcorrdata) # determine the smallest blocs, if wanted: if UseLDABlocs: dm = self.analyse_BS() # now save things again to HDF5: if MPI.IS_MASTER_NODE(): ar = HDF_Archive(self.HDFfile, "a") ar[self.LDAdata]["hfield"] = self.hfield del ar self.save()
def convert_DMFT_input(self): """ Reads the input files, and stores the data in the HDFfile """ if not (MPI.IS_MASTER_NODE()): return # do it only on master: MPI.report("Reading input from %s..." % self.LDA_file) # Read and write only on Master!!! # R is a generator : each R.Next() will return the next number in the file R = Read_Fortran_File(self.LDA_file) try: EnergyUnit = R.next() # read the energy convertion factor Nk = int(R.next()) # read the number of k points k_dep_projection = 1 SP = int(R.next()) # flag for spin-polarised calculation SO = int(R.next()) # flag for spin-orbit calculation charge_below = R.next() # total charge below energy window Density_Required = R.next( ) # total density required, for setting the chemical potential symm_op = 1 # Use symmetry groups for the k-sum # the information on the non-correlated shells is not important here, maybe skip: N_shells = int(R.next( )) # number of shells (e.g. Fe d, As p, O p) in the unit cell, # corresponds to index R in formulas # now read the information about the shells: shells = [[int(R.next()) for i in range(4)] for icrsh in range(N_shells) ] # reads iatom, sort, l, dim N_corr_shells = int(R.next( )) # number of corr. shells (e.g. Fe d, Ce f) in the unit cell, # corresponds to index R in formulas # now read the information about the shells: corr_shells = [[int(R.next()) for i in range(6)] for icrsh in range(N_corr_shells) ] # reads iatom, sort, l, dim, SO flag, irep self.inequiv_shells( corr_shells ) # determine the number of inequivalent correlated shells, has to be known for further reading... use_rotations = 1 rotmat = [ numpy.identity(corr_shells[icrsh][3], numpy.complex_) for icrsh in xrange(N_corr_shells) ] # read the matrices rotmat_timeinv = [0 for i in range(N_corr_shells)] for icrsh in xrange(N_corr_shells): for i in xrange(corr_shells[icrsh][3]): # read real part: for j in xrange(corr_shells[icrsh][3]): rotmat[icrsh][i, j] = R.next() for i in xrange(corr_shells[icrsh][3]): # read imaginary part: for j in xrange(corr_shells[icrsh][3]): rotmat[icrsh][i, j] += 1j * R.next() if (SP == 1): # read time inversion flag: rotmat_timeinv[icrsh] = int(R.next()) # Read here the infos for the transformation of the basis: Nreps = [1 for i in range(self.N_inequiv_corr_shells)] dim_reps = [0 for i in range(self.N_inequiv_corr_shells)] T = [] for icrsh in range(self.N_inequiv_corr_shells): Nreps[icrsh] = int(R.next( )) # number of representatives ("subsets"), e.g. t2g and eg dim_reps[icrsh] = [int(R.next()) for i in range(Nreps[icrsh]) ] # dimensions of the subsets # The transformation matrix: # it is of dimension 2l+1, if no SO, and 2*(2l+1) with SO!! #T = [] #for ish in xrange(self.N_inequiv_corr_shells): ll = 2 * corr_shells[self.invshellmap[icrsh]][2] + 1 lmax = ll * (corr_shells[self.invshellmap[icrsh]][4] + 1) T.append(numpy.zeros([lmax, lmax], numpy.complex_)) # now read it from file: for i in xrange(lmax): for j in xrange(lmax): T[icrsh][i, j] = R.next() for i in xrange(lmax): for j in xrange(lmax): T[icrsh][i, j] += 1j * R.next() # Spin blocks to be read: Nspinblocs = SP + 1 - SO # number of spins to read for Norbs and Ham, NOT Projectors # read the list of N_Orbitals for all k points N_Orbitals = [[0 for isp in range(Nspinblocs)] for ik in xrange(Nk)] for isp in range(Nspinblocs): for ik in xrange(Nk): N_Orbitals[ik][isp] = int(R.next()) #print N_Orbitals # Initialise the projectors: Proj_Mat = [[[ numpy.zeros([corr_shells[icrsh][3], N_Orbitals[ik][isp]], numpy.complex_) for icrsh in range(N_corr_shells) ] for isp in range(Nspinblocs)] for ik in range(Nk)] # Read the projectors from the file: for ik in xrange(Nk): for icrsh in range(N_corr_shells): no = corr_shells[icrsh][3] # first Real part for BOTH spins, due to conventions in dmftproj: for isp in range(Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i, j] = R.next() # now Imag part: for isp in range(Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i, j] += 1j * R.next() # now define the arrays for weights and hopping ... BZ_weights = numpy.ones([Nk], numpy.float_) / float( Nk) # w(k_index), default normalisation Hopping = [[ numpy.zeros([N_Orbitals[ik][isp], N_Orbitals[ik][isp]], numpy.complex_) for isp in range(Nspinblocs) ] for ik in xrange(Nk)] # weights in the file for ik in xrange(Nk): BZ_weights[ik] = R.next() # if the sum over spins is in the weights, take it out again!! sm = sum(BZ_weights) BZ_weights[:] /= sm # Grab the H # we use now the convention of a DIAGONAL Hamiltonian!!!! for isp in range(Nspinblocs): for ik in xrange(Nk): no = N_Orbitals[ik][isp] for i in xrange(no): Hopping[ik][isp][i, i] = R.next() * EnergyUnit #keep some things that we need for reading parproj: self.N_shells = N_shells self.shells = shells self.N_corr_shells = N_corr_shells self.corr_shells = corr_shells self.Nspinblocs = Nspinblocs self.N_Orbitals = N_Orbitals self.Nk = Nk self.SO = SO self.SP = SP self.EnergyUnit = EnergyUnit except StopIteration: # a more explicit error if the file is corrupted. raise "SumK_LDA : reading file HMLT_file failed!" R.close() #print Proj_Mat[0] #----------------------------------------- # Store the input into HDF5: ar = HDF_Archive(self.HDFfile, 'a') if not (self.LDASubGrp in ar): ar.create_group(self.LDASubGrp) # The subgroup containing the data. If it does not exist, it is created. # If it exists, the data is overwritten!!! ar[self.LDASubGrp]['EnergyUnit'] = EnergyUnit ar[self.LDASubGrp]['Nk'] = Nk ar[self.LDASubGrp]['k_dep_projection'] = k_dep_projection ar[self.LDASubGrp]['SP'] = SP ar[self.LDASubGrp]['SO'] = SO ar[self.LDASubGrp]['charge_below'] = charge_below ar[self.LDASubGrp]['Density_Required'] = Density_Required ar[self.LDASubGrp]['symm_op'] = symm_op ar[self.LDASubGrp]['N_shells'] = N_shells ar[self.LDASubGrp]['shells'] = shells ar[self.LDASubGrp]['N_corr_shells'] = N_corr_shells ar[self.LDASubGrp]['corr_shells'] = corr_shells ar[self.LDASubGrp]['use_rotations'] = use_rotations ar[self.LDASubGrp]['rotmat'] = rotmat ar[self.LDASubGrp]['rotmat_timeinv'] = rotmat_timeinv ar[self.LDASubGrp]['Nreps'] = Nreps ar[self.LDASubGrp]['dim_reps'] = dim_reps ar[self.LDASubGrp]['T'] = T ar[self.LDASubGrp]['N_Orbitals'] = N_Orbitals ar[self.LDASubGrp]['Proj_Mat'] = Proj_Mat ar[self.LDASubGrp]['BZ_weights'] = BZ_weights ar[self.LDASubGrp]['Hopping'] = Hopping del ar # Symmetries are used, # Now do the symmetries for correlated orbitals: self.read_Symmetry_input(orbits=corr_shells, symmfile=self.Symm_file, SymmSubGrp=self.SymmSubGrp, SO=SO, SP=SP)
def analyse_BS(self, threshold=0.00001, includeshells=None): """ Determines the Greens function block structure from the simple point integration""" dm = self.simplepointdensmat() densmat = [dm[self.invshellmap[ish]] for ish in xrange(self.N_inequiv_corr_shells)] if includeshells is None: includeshells = range(self.N_inequiv_corr_shells) for ish in includeshells: # self.GFStruct_Solver.append([]) self.GFStruct_Solver[ish] = [] a_list = [a for a, al in self.GFStruct_corr[self.invshellmap[ish]]] for a in a_list: dm = densmat[ish][a] dmbool = abs(dm) > threshold # gives an index list of entries larger that threshold offdiag = [] for i in xrange(len(dmbool)): for j in xrange(i, len(dmbool)): if (dmbool[i, j]) & (i != j): offdiag.append([i, j]) NBlocs = len(dmbool) blocs = [[i] for i in range(NBlocs)] for i in range(len(offdiag)): if offdiag[i][0] != offdiag[i][1]: for j in range(len(blocs[offdiag[i][1]])): blocs[offdiag[i][0]].append(blocs[offdiag[i][1]][j]) del blocs[offdiag[i][1]] for j in range(i + 1, len(offdiag)): if offdiag[j][0] == offdiag[i][1]: offdiag[j][0] = offdiag[i][0] if offdiag[j][1] == offdiag[i][1]: offdiag[j][1] = offdiag[i][0] if offdiag[j][0] > offdiag[i][1]: offdiag[j][0] -= 1 if offdiag[j][1] > offdiag[i][1]: offdiag[j][1] -= 1 offdiag[j].sort() NBlocs -= 1 for i in range(NBlocs): blocs[i].sort() self.GFStruct_Solver[ish].append(("%s%s" % (a, i), blocs[i])) # map is the mapping of the blocs from the SK blocs to the CTQMC blocs: self.map[ish][a] = range(len(dmbool)) for ibl in range(NBlocs): for j in range(len(blocs[ibl])): self.map[ish][a][blocs[ibl][j]] = "%s%s" % (a, ibl) self.mapinv[ish]["%s%s" % (a, ibl)] = a # now calculate degeneracies of orbitals: dm = {} for bl in self.GFStruct_Solver[ish]: bln = bl[0] ind = bl[1] # get dm for the blocks: dm[bln] = numpy.zeros([len(ind), len(ind)], numpy.complex_) for i in range(len(ind)): for j in range(len(ind)): dm[bln][i, j] = densmat[ish][self.mapinv[ish][bln]][ind[i], ind[j]] for bl in self.GFStruct_Solver[ish]: for bl2 in self.GFStruct_Solver[ish]: if dm[bl[0]].shape == dm[bl2[0]].shape: if ((abs(dm[bl[0]] - dm[bl2[0]]) < threshold).all()) and (bl[0] != bl2[0]): # check if it was already there: ind1 = -1 ind2 = -2 for n, ind in enumerate(self.deg_shells[ish]): if bl[0] in ind: ind1 = n if bl2[0] in ind: ind2 = n if (ind1 < 0) and (ind2 >= 0): self.deg_shells[ish][ind2].append(bl[0]) elif (ind1 >= 0) and (ind2 < 0): self.deg_shells[ish][ind1].append(bl2[0]) elif (ind1 < 0) and (ind2 < 0): self.deg_shells[ish].append([bl[0], bl2[0]]) if MPI.IS_MASTER_NODE(): ar = HDF_Archive(self.HDFfile, "a") ar[self.LDAdata]["GFStruct_Solver"] = self.GFStruct_Solver ar[self.LDAdata]["map"] = self.map ar[self.LDAdata]["mapinv"] = self.mapinv try: ar[self.LDAdata]["deg_shells"] = self.deg_shells except: MPI.report("deg_shells not stored, degeneracies not found") del ar return densmat
def read_Symmetry_input(self, orbits, symmfile, SymmSubGrp, SO, SP): """ Reads input for the symmetrisations from symmfile, which is case.sympar or case.symqmc. """ if not (MPI.IS_MASTER_NODE()): return MPI.report("Reading symmetry input from %s..." % symmfile) N_orbits = len(orbits) R = Read_Fortran_File(symmfile) try: Ns = int(R.next()) # Number of symmetry operations Natoms = int(R.next()) # number of atoms involved perm = [[int(R.next()) for i in xrange(Natoms)] for j in xrange(Ns)] # list of permutations of the atoms if SP: timeinv = [int(R.next()) for j in xrange(Ns) ] # timeinversion for SO xoupling else: timeinv = [0 for j in xrange(Ns)] # Now read matrices: mat = [] for iNs in xrange(Ns): mat.append([ numpy.zeros([orbits[orb][3], orbits[orb][3]], numpy.complex_) for orb in xrange(N_orbits) ]) for orb in range(N_orbits): for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat[iNs][orb][i, j] = R.next() # real part for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat[iNs][orb][i, j] += 1j * R.next() # imaginary part # determine the inequivalent shells: #SHOULD BE FINALLY REMOVED, PUT IT FOR ALL ORBITALS!!!!! #self.inequiv_shells(orbits) mat_tinv = [ numpy.identity(orbits[orb][3], numpy.complex_) for orb in range(N_orbits) ] if ((SO == 0) and (SP == 0)): # here we need an additional time inversion operation, so read it: for orb in range(N_orbits): for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat_tinv[orb][i, j] = R.next() # real part for i in xrange(orbits[orb][3]): for j in xrange(orbits[orb][3]): mat_tinv[orb][i, j] += 1j * R.next() # imaginary part except StopIteration: # a more explicit error if the file is corrupted. raise "Symmetry : reading file failed!" R.close() # Save it to the HDF: ar = HDF_Archive(self.HDFfile, 'a') if not (SymmSubGrp in ar): ar.create_group(SymmSubGrp) thingstowrite = [ 'Ns', 'Natoms', 'perm', 'orbits', 'SO', 'SP', 'timeinv', 'mat', 'mat_tinv' ] for it in thingstowrite: exec "ar['%s']['%s'] = %s" % (SymmSubGrp, it, it) del ar
def convert_bands_input(self, BandsSubGrp='SumK_LDA_Bands'): """ Converts the input for momentum resolved spectral functions, and stores it in BandsSubGrp in the HDF5. """ if not (MPI.IS_MASTER_NODE()): return self.BandsSubGrp = BandsSubGrp MPI.report("Reading bands input from %s..." % self.Band_file) R = Read_Fortran_File(self.Band_file) try: Nk = int(R.next()) # read the list of N_Orbitals for all k points N_Orbitals = [[0 for isp in range(self.Nspinblocs)] for ik in xrange(Nk)] for isp in range(self.Nspinblocs): for ik in xrange(Nk): N_Orbitals[ik][isp] = int(R.next()) # Initialise the projectors: Proj_Mat = [[[ numpy.zeros([self.corr_shells[icrsh][3], N_Orbitals[ik][isp]], numpy.complex_) for icrsh in range(self.N_corr_shells) ] for isp in range(self.Nspinblocs)] for ik in range(Nk)] # Read the projectors from the file: for ik in xrange(Nk): for icrsh in range(self.N_corr_shells): no = self.corr_shells[icrsh][3] # first Real part for BOTH spins, due to conventions in dmftproj: for isp in range(self.Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i, j] = R.next() # now Imag part: for isp in range(self.Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i, j] += 1j * R.next() Hopping = [[ numpy.zeros([N_Orbitals[ik][isp], N_Orbitals[ik][isp]], numpy.complex_) for isp in range(self.Nspinblocs) ] for ik in xrange(Nk)] # Grab the H # we use now the convention of a DIAGONAL Hamiltonian!!!! for isp in range(self.Nspinblocs): for ik in xrange(Nk): no = N_Orbitals[ik][isp] for i in xrange(no): Hopping[ik][isp][i, i] = R.next() * self.EnergyUnit # now read the partial projectors: N_parproj = [int(R.next()) for i in range(self.N_shells)] # Initialise P, here a double list of matrices: Proj_Mat_pc = [[[[ numpy.zeros([self.shells[ish][3], N_Orbitals[ik][isp]], numpy.complex_) for ir in range(N_parproj[ish]) ] for ish in range(self.N_shells)] for isp in range(self.Nspinblocs)] for ik in range(Nk)] for ish in range(self.N_shells): for ik in xrange(Nk): for ir in range(N_parproj[ish]): for isp in range(self.Nspinblocs): for i in xrange( self.shells[ish][3]): # read real part: for j in xrange(N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][ i, j] = R.next() for i in xrange(self.shells[ish] [3]): # read imaginary part: for j in xrange(N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][ i, j] += 1j * R.next() except StopIteration: # a more explicit error if the file is corrupted. raise "SumK_LDA : reading file HMLT_file failed!" R.close() # reading done! #----------------------------------------- # Store the input into HDF5: ar = HDF_Archive(self.HDFfile, 'a') if not (self.BandsSubGrp in ar): ar.create_group(self.BandsSubGrp) # The subgroup containing the data. If it does not exist, it is created. # If it exists, the data is overwritten!!! thingstowrite = [ 'Nk', 'N_Orbitals', 'Proj_Mat', 'Hopping', 'N_parproj', 'Proj_Mat_pc' ] for it in thingstowrite: exec "ar['%s']['%s'] = %s" % (self.BandsSubGrp, it, it) #ar[self.BandsSubGrp]['Nk'] = Nk #ar[self.BandsSubGrp]['N_Orbitals'] = N_Orbitals #ar[self.BandsSubGrp]['Proj_Mat'] = Proj_Mat #self.Proj_Mat = Proj_Mat #self.N_Orbitals = N_Orbitals #self.Nk = Nk #self.Hopping = Hopping del ar
def convert_Parproj_input(self,ParProjSubGrp='SumK_LDA_ParProj',SymmParSubGrp='SymmPar'): """ Reads the input for the partial charges projectors from case.parproj, and stores it in the SymmParSubGrp group in the HDF5. """ if not (MPI.IS_MASTER_NODE()): return self.ParProjSubGrp = ParProjSubGrp self.SymmParSubGrp = SymmParSubGrp MPI.report("Reading parproj input from %s..."%self.Parproj_file) Dens_Mat_below = [ [numpy.zeros([self.shells[ish][3],self.shells[ish][3]],numpy.complex_) for ish in range(self.N_shells)] for isp in range(self.Nspinblocs) ] R = Read_Fortran_File(self.Parproj_file) #try: N_parproj = [int(R.next()) for i in range(self.N_shells)] # Initialise P, here a double list of matrices: Proj_Mat_pc = [ [ [ [numpy.zeros([self.shells[ish][3], self.N_Orbitals[ik][isp]], numpy.complex_) for ir in range(N_parproj[ish])] for ish in range (self.N_shells) ] for isp in range(self.Nspinblocs) ] for ik in range(self.Nk) ] rotmat_all = [numpy.identity(self.shells[ish][3],numpy.complex_) for ish in xrange(self.N_shells)] rotmat_all_timeinv = [0 for i in range(self.N_shells)] for ish in range(self.N_shells): #print ish # read first the projectors for this orbital: for ik in xrange(self.Nk): for ir in range(N_parproj[ish]): for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read real part: for j in xrange(self.N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][i,j] = R.next() for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read imaginary part: for j in xrange(self.N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][i,j] += 1j * R.next() # now read the Density Matrix for this orbital below the energy window: for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read real part: for j in xrange(self.shells[ish][3]): Dens_Mat_below[isp][ish][i,j] = R.next() for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read imaginary part: for j in xrange(self.shells[ish][3]): Dens_Mat_below[isp][ish][i,j] += 1j * R.next() if (self.SP==0): Dens_Mat_below[isp][ish] /= 2.0 # Global -> local rotation matrix for this shell: for i in xrange(self.shells[ish][3]): # read real part: for j in xrange(self.shells[ish][3]): rotmat_all[ish][i,j] = R.next() for i in xrange(self.shells[ish][3]): # read imaginary part: for j in xrange(self.shells[ish][3]): rotmat_all[ish][i,j] += 1j * R.next() #print Dens_Mat_below[0][ish],Dens_Mat_below[1][ish] if (self.SP): rotmat_all_timeinv[ish] = int(R.next()) #except StopIteration : # a more explicit error if the file is corrupted. # raise "SumK_LDA_Wien2k_input: reading file for Projectors failed!" R.close() #----------------------------------------- # Store the input into HDF5: ar = HDF_Archive(self.HDFfile,'a') if not (self.ParProjSubGrp in ar): ar.create_group(self.ParProjSubGrp) # The subgroup containing the data. If it does not exist, it is created. # If it exists, the data is overwritten!!! thingstowrite = ['Dens_Mat_below','N_parproj','Proj_Mat_pc','rotmat_all','rotmat_all_timeinv'] for it in thingstowrite: exec "ar['%s']['%s'] = %s"%(self.ParProjSubGrp,it,it) del ar # Symmetries are used, # Now do the symmetries for all orbitals: self.read_Symmetry_input(orbits=self.shells,symmfile=self.Symmpar_file,SymmSubGrp=self.SymmParSubGrp,SO=self.SO,SP=self.SP)
def __init__(self, Beta, Norb, U_interact=None, J_Hund=None, GFStruct=False, map=False, use_spinflip=False, useMatrix = True, l=2, T=None, dimreps=None, irep=None, deg_orbs = [], Sl_Int = None): self.offset = 0 self.use_spinflip = use_spinflip self.Norb = Norb if (useMatrix): if not (Sl_Int is None): Umat = Umatrix(l=l) assert len(Sl_Int)==(l+1),"Sl_Int has the wrong length" if (type(Sl_Int)==ListType): Rcl = numpy.array(Sl_Int) else: Rcl = Sl_Int Umat(T=T,Rcl=Rcl) else: if ((U_interact==None)and(J_Hund==None)): MPI.report("Give U,J or Slater integrals!!!") assert 0 Umat = Umatrix(U_interact=U_interact, J_Hund=J_Hund, l=l) Umat(T=T) Umat.ReduceMatrix() if (Umat.N==Umat.Nmat): # Transformation T is of size 2l+1 self.U = Umat.U self.Up = Umat.Up else: # Transformation is of size 2(2l+1) self.U = Umat.U # now we have the reduced matrices U and Up, we need it for tail fitting anyways if (use_spinflip): #Take the 4index Umatrix # check for imaginary matrix elements: if (abs(Umat.Ufull.imag)>0.0001).any(): MPI.report("WARNING: complex interaction matrix!! Ignoring imaginary part for the moment!") MPI.report("If you want to change this, look into Wien2k/Solver_MultiBand.py") self.U4ind = Umat.Ufull.real # this will be changed for arbitrary irep: # use only one subgroup of orbitals? if not (irep is None): #print irep, dimreps assert not (dimreps is None), "Dimensions of the representatives are missing!" assert Norb==dimreps[irep-1],"Dimensions of dimrep and Norb do not fit!" for ii in range(irep-1): self.offset += dimreps[ii] else: if ((U_interact==None)and(J_Hund==None)): MPI.report("For Kanamori representation, give U and J!!") assert 0 self.U = numpy.zeros([Norb,Norb],numpy.float_) self.Up = numpy.zeros([Norb,Norb],numpy.float_) for i in range(Norb): for j in range(Norb): if (i==j): self.Up[i,i] = U_interact + 2.0*J_Hund else: self.Up[i,j] = U_interact self.U[i,j] = U_interact - J_Hund if (GFStruct): assert map, "give also the mapping!" self.map = map else: # standard GFStruct and map GFStruct = [ ('%s'%(ud),[n for n in range(Norb)]) for ud in ['up','down'] ] self.map = {'up' : ['up' for v in range(self.Norb)], 'down' : ['down' for v in range(self.Norb)]} #print GFStruct,self.map if (use_spinflip==False): Hamiltonian = self.__setHamiltonian_density() else: if (useMatrix): Hamiltonian = self.__setfullHamiltonian_Slater() else: Hamiltonian = self.__setfullHamiltonian_Kanamori(J_Hund = J_Hund) Quantum_Numbers = self.__setQuantumNumbers(GFStruct) # Determine if there are only blocs of size 1: self.blocssizeone = True for ib in GFStruct: if (len(ib[1])>1): self.blocssizeone = False # now initialize the solver with the stuff given above: Solver.__init__(self, Beta = Beta, GFstruct = GFStruct, H_Local = Hamiltonian, Quantum_Numbers = Quantum_Numbers ) #self.SetGlobalMoves(deg_orbs) self.N_Cycles = 10000 self.Nmax_Matrix = 100 self.N_Time_Slices_Delta= 10000 #if ((len(GFStruct)==2*Norb) and (use_spinflip==False)): if ((self.blocssizeone) and (use_spinflip==False)): self.Use_Segment_Picture = True else: self.Use_Segment_Picture = False
def convert_bands_input(self,BandsSubGrp = 'SumK_LDA_Bands'): """ Converts the input for momentum resolved spectral functions, and stores it in BandsSubGrp in the HDF5. """ if not (MPI.IS_MASTER_NODE()): return self.BandsSubGrp = BandsSubGrp MPI.report("Reading bands input from %s..."%self.Band_file) R = Read_Fortran_File(self.Band_file) try: Nk = int(R.next()) # read the list of N_Orbitals for all k points N_Orbitals = [ [0 for isp in range(self.Nspinblocs)] for ik in xrange(Nk)] for isp in range(self.Nspinblocs): for ik in xrange(Nk): N_Orbitals[ik][isp] = int(R.next()) # Initialise the projectors: Proj_Mat = [ [ [numpy.zeros([self.corr_shells[icrsh][3], N_Orbitals[ik][isp]], numpy.complex_) for icrsh in range (self.N_corr_shells)] for isp in range(self.Nspinblocs)] for ik in range(Nk) ] # Read the projectors from the file: for ik in xrange(Nk): for icrsh in range(self.N_corr_shells): no = self.corr_shells[icrsh][3] # first Real part for BOTH spins, due to conventions in dmftproj: for isp in range(self.Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i,j] = R.next() # now Imag part: for isp in range(self.Nspinblocs): for i in xrange(no): for j in xrange(N_Orbitals[ik][isp]): Proj_Mat[ik][isp][icrsh][i,j] += 1j * R.next() Hopping = [ [numpy.zeros([N_Orbitals[ik][isp],N_Orbitals[ik][isp]],numpy.complex_) for isp in range(self.Nspinblocs)] for ik in xrange(Nk) ] # Grab the H # we use now the convention of a DIAGONAL Hamiltonian!!!! for isp in range(self.Nspinblocs): for ik in xrange(Nk) : no = N_Orbitals[ik][isp] for i in xrange(no): Hopping[ik][isp][i,i] = R.next() * self.EnergyUnit # now read the partial projectors: N_parproj = [int(R.next()) for i in range(self.N_shells)] # Initialise P, here a double list of matrices: Proj_Mat_pc = [ [ [ [numpy.zeros([self.shells[ish][3], N_Orbitals[ik][isp]], numpy.complex_) for ir in range(N_parproj[ish])] for ish in range (self.N_shells) ] for isp in range(self.Nspinblocs) ] for ik in range(Nk) ] for ish in range(self.N_shells): for ik in xrange(Nk): for ir in range(N_parproj[ish]): for isp in range(self.Nspinblocs): for i in xrange(self.shells[ish][3]): # read real part: for j in xrange(N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][i,j] = R.next() for i in xrange(self.shells[ish][3]): # read imaginary part: for j in xrange(N_Orbitals[ik][isp]): Proj_Mat_pc[ik][isp][ish][ir][i,j] += 1j * R.next() except StopIteration : # a more explicit error if the file is corrupted. raise "SumK_LDA : reading file HMLT_file failed!" R.close() # reading done! #----------------------------------------- # Store the input into HDF5: ar = HDF_Archive(self.HDFfile,'a') if not (self.BandsSubGrp in ar): ar.create_group(self.BandsSubGrp) # The subgroup containing the data. If it does not exist, it is created. # If it exists, the data is overwritten!!! thingstowrite = ['Nk','N_Orbitals','Proj_Mat','Hopping','N_parproj','Proj_Mat_pc'] for it in thingstowrite: exec "ar['%s']['%s'] = %s"%(self.BandsSubGrp,it,it) #ar[self.BandsSubGrp]['Nk'] = Nk #ar[self.BandsSubGrp]['N_Orbitals'] = N_Orbitals #ar[self.BandsSubGrp]['Proj_Mat'] = Proj_Mat #self.Proj_Mat = Proj_Mat #self.N_Orbitals = N_Orbitals #self.Nk = Nk #self.Hopping = Hopping del ar
def Dichotomy(Function, xinit,yvalue,Precision_on_y,Delta_x, MaxNbreLoop=1000, xname="", yname="",verbosity=1): """ Solver Function(x) = yvalue. Arguments : - Function : function (real valued) to be solved by dichotomy - xinit : Init value for x. On success, returns the new value of x - yvalue : - precision : calculation stops for abs(f(x) - yvalue)<precision - MaxNbreLoop : maximum number of loops before failure. Default is 1000 - xname, yname : name of the variable x, y for the report - verbosity : verbosity level. Returns : - A tuple (x,y). x is the value found, y is f(x). - (None,None) if the calculation failed. """ def sign(x): if x>0.0 : return 1 if x<0.0 : return -1 return 0 MPI.report("Dichotomy adjustment of %(xname)s to obtain %(yname)s = %(yvalue)f +/- %(Precision_on_y)f"%locals() ) PR = " " if xname=="" or yname=="" : verbosity = max(verbosity,1) x=xinit;Delta_x= abs(Delta_x) # First find the bounds y1 = Function(x) eps = sign(y1-yvalue) x1=x;y2=y1;x2=x1 nbre_loop=0 while (nbre_loop<= MaxNbreLoop) and (y2-yvalue)*eps>0 and abs(y2-yvalue)>Precision_on_y : nbre_loop +=1 x2 -= eps*Delta_x y2 = Function(x2) if xname!="" and verbosity>2: MPI.report("%(PR)s%(xname)s = %(x2)f \n%(PR)s%(yname)s = %(y2)f"%locals()) MPI.report("%(PR)s%(x1)f < %(xname)s < %(x2)f"%locals()) MPI.report("%(PR)s%(y1)f < %(yname)s < %(y2)f"%locals()) # Now mu is between mu1 and mu2 yfound = y2 # We found bounds. What if the next loop is never run ? # i.e. x1 or x2 are close to the solution # we have to know which one is the best .... if abs(y1-yvalue)< abs(y2-yvalue) : x=x1 else: x=x2 #Now let's refine our mu.... while (nbre_loop<= MaxNbreLoop) and (abs(yfound-yvalue)>Precision_on_y) : nbre_loop +=1 x = x1 + (x2 - x1) * (yvalue - y1)/(y2-y1) yfound = Function(x) if (y1-yvalue)*(yfound - yvalue)>0 : x1 = x; y1=yfound else : x2= x;y2=yfound; if verbosity>2 : MPI.report("%(PR)s%(x1)f < %(xname)s < %(x2)f"%locals()) MPI.report("%(PR)s%(y1)f < %(yname)s < %(y2)f"%locals()) if abs(yfound - yvalue) < Precision_on_y : if verbosity>0: MPI.report("%(PR)s%(xname)s found in %(nbre_loop)d iterations : "%locals()) MPI.report("%(PR)s%(yname)s = %(yfound)f;%(xname)s = %(x)f"%locals()) return (x,yfound) else : if verbosity>0: MPI.report("%(PR)sFAILURE to adjust %(xname)s to the value %(yvalue)f after %(nbre_loop)d iterations."%locals()) return (None,None)
def SetDoubleCounting(self, densmat, U_interact, J_Hund, orb=0, useDCformula=0, useval=None): """Sets the double counting term for inequiv orbital orb useDCformula=0: LDA+U FLL double counting, useDCformula=1: Held's formula. useDCformula=2: AMF Be sure that you use the correct interaction Hamiltonian!""" # if (not hasattr(self,"dc_imp")): self.__initDC() dm = [{} for i in xrange(self.N_corr_shells)] for i in xrange(self.N_corr_shells): l = self.corr_shells[i][3] # *(1+self.corr_shells[i][4]) for j in xrange(len(self.GFStruct_corr[i])): dm[i]["%s" % self.GFStruct_corr[i][j][0]] = numpy.zeros([l, l], numpy.float_) for icrsh in xrange(self.N_corr_shells): iorb = self.shellmap[icrsh] # iorb is the index of the inequivalent shell corresponding to icrsh if iorb == orb: # do this orbital l = self.corr_shells[icrsh][3] # *(1+self.corr_shells[icrsh][4]) for j in xrange(len(self.GFStruct_corr[icrsh])): self.dc_imp[icrsh]["%s" % self.GFStruct_corr[icrsh][j][0]] = numpy.identity(l, numpy.float_) # transform the CTQMC blocks to the full matrix: for ibl in range(len(self.GFStruct_Solver[iorb])): for i in range(len(self.GFStruct_Solver[iorb][ibl][1])): for j in range(len(self.GFStruct_Solver[iorb][ibl][1])): bl = self.GFStruct_Solver[iorb][ibl][0] ind1 = self.GFStruct_Solver[iorb][ibl][1][i] ind2 = self.GFStruct_Solver[iorb][ibl][1][j] dm[icrsh][self.mapinv[iorb][bl]][ind1, ind2] = densmat[bl][ i, j ].real # only real part relevant for trace M = self.corr_shells[icrsh][3] Ncr = {} Ncrtot = 0.0 a_list = [a for a, al in self.GFStruct_corr[icrsh]] for bl in a_list: Ncr[bl] = dm[icrsh][bl].trace() Ncrtot += Ncr[bl] # average the densities if there is no SP: if self.SP == 0: for bl in a_list: Ncr[bl] = Ncrtot / len(a_list) # correction for SO: we have only one block in this case, but in DC we need N/2 elif self.SP == 1 and self.SO == 1: for bl in a_list: Ncr[bl] = Ncrtot / 2.0 if useval is None: if useDCformula == 0: self.DCenerg[icrsh] = U_interact / 2.0 * Ncrtot * (Ncrtot - 1.0) for bl in a_list: Uav = U_interact * (Ncrtot - 0.5) - J_Hund * (Ncr[bl] - 0.5) self.dc_imp[icrsh][bl] *= Uav self.DCenerg[icrsh] -= J_Hund / 2.0 * (Ncr[bl]) * (Ncr[bl] - 1.0) MPI.report("DC for shell %(icrsh)i and block %(bl)s = %(Uav)f" % locals()) elif useDCformula == 1: self.DCenerg[icrsh] = ( (U_interact + J_Hund * (2.0 - (M - 1)) / (2 * M - 1)) / 2.0 * Ncrtot * (Ncrtot - 1.0) ) for bl in a_list: # Held's formula, with U_interact the interorbital onsite interaction Uav = (U_interact + J_Hund * (2.0 - (M - 1)) / (2 * M - 1)) * (Ncrtot - 0.5) self.dc_imp[icrsh][bl] *= Uav MPI.report("DC for shell %(icrsh)i and block %(bl)s = %(Uav)f" % locals()) elif useDCformula == 2: self.DCenerg[icrsh] = 0.5 * U_interact * Ncrtot * Ncrtot for bl in a_list: # AMF Uav = U_interact * (Ncrtot - Ncr[bl] / M) - J_Hund * (Ncr[bl] - Ncr[bl] / M) self.dc_imp[icrsh][bl] *= Uav self.DCenerg[icrsh] -= (U_interact + (M - 1) * J_Hund) / M * 0.5 * Ncr[bl] * Ncr[bl] MPI.report("DC for shell %(icrsh)i and block %(bl)s = %(Uav)f" % locals()) # output: MPI.report("DC energy for shell %s = %s" % (icrsh, self.DCenerg[icrsh])) else: a_list = [a for a, al in self.GFStruct_corr[icrsh]] for bl in a_list: self.dc_imp[icrsh][bl] *= useval self.DCenerg[icrsh] = useval * Ncrtot # output: MPI.report("DC for shell %(icrsh)i = %(useval)f" % locals()) MPI.report("DC energy = %s" % self.DCenerg[icrsh])