def yaeh_ReadBand(stFileName): ''' Read k-points and band from yaeh band result. Fermi energy is not calculated. @todo spin is always 1 ''' f = open(stFileName) ar_stLine = f.readlines() list_kp = [] list_band = [] nbnd = int(ar_stLine[4].split()[0]) #Number of bands in each kpt nStart = 0 #Start position of band data for i in range(0, len(ar_stLine)): if ("Begin band data" in ar_stLine[i]): nStart = i + 1 #line count that not band data break for i in range(0, (len(ar_stLine) - nStart) / (nbnd + 1)): i2 = (nbnd + 1) * i + nStart list_kp.append([float(x) for x in ar_stLine[i2][10:].split()]) list_band.append([float(x) for x in ar_stLine[i2 + 1:i2 + nbnd + 1]]) #write aKPT = KPointsT() aKPT.ReadFromList(list_kp) # return aKPT,list_band,0,0,0 band = BandsT(aKPT, list_band) band.num_spin = 1 return band
def bdf_read_band(filename): ''' Read a band structure from bdf output ''' f = open(filename) #Read reciporocal vectors lines = f.readlines() f.close() mK = [[float(y) for y in x.split()[1:4]] for x in lines[2:5]] eig_fermi = float(lines[6].split()[-1]) print(eig_fermi) list_kpt = [] list_eig = [] for line in lines[7:]: ar = line.split() #"A" is marked as non-special k-points if (ar[1] == "A"): ar[1] = "" list_kpt.append(ar[1:2] + [float(x) for x in ar[2:5]] + [1.0]) list_eig.append([float(x) for x in ar[5:]]) kpt = KPointsT() kpt.stMode = "crystal" kpt.ReadFromList(list_kpt) kpt.ConvertUnit("cart", mLatt=f_GetReciprocalLattice(mK)) band = BandsT(kpt, list_eig, eig_fermi, eig_fermi) band.b_metal = True #Just set to plot fermi return band
def read_eigs(filename): ''' Read eigenvalues only as a band structure ''' list_eig = f_Data_ReadMultiCol(filename, func=float) kpt = KPointsT() kpt.listKPt = [["", 0, 0, x, 0] for x in xrange(len(list_eig))] band = BandsT(kpt=kpt, list_eig=list_eig) return band
def abi_ReadBand_EIG(stFileName): ''' Read band structure from _EIG file ''' f = open(stFileName) stLine = f.readline() if ("hartree" in stLine): # "(hartree) =" energy_unit = Ha2eV else: energy_unit = 1.0 # energy unit; if it is hartree then convert to eV if ("Fermi" in stLine): # Find the first equal ixEqual = stLine.index("=") dFermi = float(stLine[ixEqual + 1:ixEqual + 10]) stLine = f.readline() else: dFermi = None nKPt = int(stLine[32:36]) listKPt = [] listBand = [] listB1 = [] # for i in xrange(0,nKPt): while True: stLine = f.readline() if not stLine: break stLine = stLine[:-1] #Remove \cr for splitting if ("kpt" in stLine): listKPt.append([ float(stLine[41:49]), float(stLine[49:57]), float(stLine[58:65]), float(stLine[26:35]) ]) if (len(listB1) > 0): listBand.append(listB1) listB1 = [] else: #To avoid two maximum length float recognized as one # listB1 += [float(x) if not "*" in x else 0.0 * energy_unit for x in stLine.split()] n = 10 listB1 += [ float(x) if not "*" in x else 0.0 for x in [stLine[i:i + n] for i in xrange(0, len(stLine), n)] ] #Find band listBand.append(listB1) aKPt = KPointsT() aKPt.ReadFromList(listKPt) # return aKPt, listBand, dFermi, None, 1 return BandsT(aKPt, listBand, dFermi, None, None, 1)
def load(self,st_program): ''' Load external content with given parameters Note : the program-related input object should be initilized manually ''' self.st_program = st_program #Customize if (st_program == "tbgwpw"): self.calcIn = TBGWInput(self.stInputFile) self.calcIn.b_warn_write = False elif (st_program == "yaeh" or st_program == "yaehg"): self.calcIn = yaeh_input(self.stInputFile) #End Customize self.bandRef = f_Band_ReadFromFile(self.stBandRefFile) self.listBandWeight = [0.001 for x in range(0,self.nBandStartIndex)] + [ 1.0 for x in range(self.nBandStartIndex,self.nBandStartIndex+self.nBandFitCount)] #Additional weight for VBM and CBM if range we considered include VBM and CBM if ( len(self.listBandWeight) >= self.nElectron /2 + 1): print("Unoccupied states included in calculation, use different weight for H**O and LUMO") if ( self.dBandHighWeight == None): self.dBandHighWeight = 10 for i in xrange(0,-self.nBandHighVB): self.listBandWeight[self.nElectron/2-1-i] = self.dBandHighWeight for i in xrange(0, self.nBandHighCB): self.listBandWeight[self.nElectron/2] = self.dBandHighWeight - self.dCBMLessWeight if ( self.nBandTotal == None): #Not specified #Additional very small weight to make result not fluctuate too much self.listBandWeight.append(0.001) else: #Add all additional band to make result stabilize self.listBandWeight = self.listBandWeight + [0.001 for x in range(0,self.nBandTotal-len(self.listBandWeight))] self.dVBMRef = f_Band_GetVBMFromElectron(self.bandRef,self.nElectron) self.dGapRef,dt,nt = f_Band_GetGap(self.bandRef,self.dVBMRef,False) #Use weights if (self.bUseKPtWeight): self.band = BandsT.load_xml(self.stDataRefFile) self.listKPtWeight = [kpt[4] for kpt in self.band.kpt.listKPt] #Normalize to each k, each band = 1 d_total = sum(self.listKPtWeight) n_len = len(self.listKPtWeight) self.listKPtWeight = [ x / d_total * n_len for x in self.listKPtWeight]
def abi_ReadBand_GW(stFileName): ''' Read band structure from _GW file ''' f = open(stFileName) nKPt, nSpin = [int(x) for x in f.readline().split()] listKPt = [] listBand = [] for i in xrange(0, nKPt): listKPt.append([float(x) for x in f.readline().split()]) n = int(f.readline()) listB = [] for j in xrange(0, n): listB.append(float(f.readline().split()[1])) listBand.append(listB) aKPt = KPointsT() aKPt.ReadFromList(listKPt) # return aKPt, listBand, None, None, nSpin return BandsT(aKPt, listBand, None, None, None, nSpin)
def uni_ReadBand(stProgram="auto", para=[]): ''' Read band structure from specific program result :param stProgram: program name, "auto" means automatically detected :param para: arguments for specific programs :return: BandsT object ''' # :param nElectron: electron number, default 0. If specified, then VBM will be calculated for plot # :param bPlot: Whether plot bandstructure # :param bAlign: Whether shift band energy to make VBM = 0 in plot # :return: k-points,eigenvalues,VBM,Electron count,Spin count # ''' stProgram = uni_Package_Detect(stProgram, para) dicFunc = {\ "auto":[(0,),None],\ "w2k":[(0,1,),w2k_ReadBand],\ "yaeh":[(1,),yaeh_ReadBand],\ "siesta":[(3,),siesta_read_band],\ "vasp":[(0,),vasp_ReadBand],\ "vasp_out":[(1,),vasp_ReadBand],\ "qe":[(1,), qesp_read_band],\ "abinit":[(2,),abi_ReadBand],\ "gap":[(1,),w2k_ReadBand],\ "w90":[(1,),wann_read_band],\ "bdf":[(1,),bdf_read_band],\ "yambo":[(1,2,),yambo_read_band],\ "raw":[(1,),lambda x:BandsT(dirname=x)],\ "band":[(1,),read_eigs]\ } if (not dicFunc.has_key(stProgram)): raise ValueError, "Package %s is not supported!" % stProgram if (not len(para) in dicFunc[stProgram][0]): raise ValueError, "incorrect number of arguments : %i" % len(para) #(aKPt,listBand,dVBM) = dicFunc[stProgram][1](*para) return dicFunc[stProgram][1](*para)
def siesta_read_band(stFDFFileName, stOutputfile, stBandFileName): ''' Read band structure of siesta Number of electrons is deduced from fermi energy, which may give wrong value when system is a metal @todo when spin=2 , two bands does not seperate ''' dicScale = {"pi/a": "piba", "ReciprocalLatticeVectors": "crystal"} aKPt = KPointsT() f = open(stFDFFileName) list_stLine = f.readlines() nInfoLine = 0 #The information line in .bands file is 3 if BandLines is used, 2 if BandPoints is used f.close() for i in range(0, len(list_stLine)): stLine = list_stLine[i].strip() if (len(stLine) == 0): #Skip empty line continue if (stLine[0] == '#'): #Skip comments continue if ("BandLinesScale " in stLine): aKPt.stMode = dicScale[stLine.split()[1]] if ("%block BandLines" in stLine): j = 1 listPt = [] listCount = [] arLine = list_stLine[i + j].split() while (not "%endblock" in arLine[0]): listPt.append(arLine[1:]) listCount.append(int(arLine[0])) j += 1 arLine = list_stLine[i + j].split() aKPt.CreateFromPointLine(listPt, listCount[1:]) nInfoLine = 3 break elif ("%block BandPoints" in stLine): j = 1 listPt = [] arLine = list_stLine[i + j].split() while (not "%endblock" in arLine[0]): listPt.append([float(x) for x in arLine[:3]]) j += 1 arLine = list_stLine[i + j].split() aKPt.ReadFromList(listPt) nInfoLine = 2 break #Convert aKPt to tpiba mode data if it is piba if (aKPt.stMode == "piba"): aKPt.stMode = "tpiba" for ar in aKPt.listKPt: ar[1:4] = [x * 0.5 for x in ar[1:4]] nElectron = siesta_read_electron(stOutputfile) #read band structure f = open(stBandFileName) list_stLine = f.readlines() f.close() fFermi = float(list_stLine[0]) (nBand, nSpin, nKPt) = [int(x) for x in list_stLine[nInfoLine].split()] if (nKPt != len(aKPt.listKPt)): raise ValueError, "k-points in %s and %s are not same!" % ( stFDFFileName, stBandFileName) listBand = [] (dVBM, fCBM) = [float(x) for x in list_stLine[nInfoLine - 1].split()] #read energy until the count of energy reaches nBand arLine = [] i = nInfoLine + 1 nSkip = 1 if nInfoLine == 3 else 3 # Skip first term( band line) if BandLines is used, Skip first three term (k-pt coord) if BandPoints is used delta = 0.0002 #nHOIndex = -1 while (len(listBand) < nKPt): arLineNow = [float(x) for x in list_stLine[i].split() ] #the first 10 is preserved for k-point coordinate if (len(arLine) != 0): #a start one k-point arLine += arLineNow else: arLine = arLineNow[nSkip:] #Cut if (len(arLine) == nBand * nSpin): #Read one k-point end listBand.append(arLine) dVBM = max([x for x in arLine if x < fFermi + delta] + [dVBM]) fCBM = min([x for x in arLine if x > fFermi - delta] + [fCBM]) arLine = [] #if ( dVBM in listBand[-1]): #nHOIndex = listBand[-1].index(dVBM) #print("VBM:%i %f" % ( nHOIndex,dVBM)) i += 1 #use VBM as zero point; if either VBM or CBM is very close to fFermi, then use fFermi if (abs(dVBM - fFermi) < delta / 2 or abs(fCBM - fFermi) < delta / 2): dVBM = fFermi print("Detect VBM from SIESTA Fermi: %f" % dVBM) # return aKPt,listBand,dVBM,nElectron,nSpin return BandsT(aKPt, listBand, dVBM, None, nElectron, nSpin)
def Main(ArgList): description = '''Plot band strcture of specific package in specific format, also create plain tabular seperated text of band structure data and k-points list. File required: SIESTA : .fdf , stdout, .bands VASP : none, require to run in the case folder WIEN2K : none , require to run in the case folder FHI-GAP : energy file name suffix (_gw-band or _gw0-band) , require to run in the WIEN2k case folder QE : data-file.xml in the save folder, or pw.x output ABINIT : _EIG output or _GW output Wannier90: _w90_band.dat file ( other files are necessary but will be selected according to this file name) Yambo : o-*.qp file RAW: folder name contains all files generated by %prog By default, output folder is current folder, so it is sugguested to run this in an empty folder to avoid overwritten as it will create plenty of files. Band characteres can also be plotted. To do this add "--plotinfo File". The input file contains extra format informations. ''' parser = ArgumentParser(description=description, formatter_class=RawDescriptionHelpFormatter) parser.add_argument("extra_args", type=str, nargs="*", help="Arguments passed to package-specific procedures") parser.add_argument("-i", dest="Program", default="auto", help="The package name") parser.add_argument("-g", dest="Align", default=False, action="store_true", help="Shift band position to make VBM = 0 in graph") parser.add_argument( "--electron", dest="Electron", default="0", help= "The number of electrons in the system of the band structure. This is used to determine VBM/Fermi energy. If not specified, this program will try to find from input files" ) parser.add_argument( "-s", dest="FormatOnly", default=False, action="store_true", help= "Do not plot band structure, just write band structure data and k-point list in space-seperated format" ) parser.add_argument("-d", dest="OutputDir", default="band", help="The name of folder used to store output files") parser.add_argument( "-k", dest="KPointsUnit", default="cart", help= "The unit of k-points in the output, also determine x-axis distance. Possible options include 'cart','crystal' and 'default', where default means use what the program read." ) parser.add_argument( "-f", dest="ForceOverwrite", default=False, action="store_true", help= "Control whether to overwrite if the output directory already exists, default is not " ) parser.add_argument( "--cross", dest="ResolveCorssing", default=False, action="store_true", help="Contrl whether to resolving band-crossing by derivatives") parser.add_argument( "--plotinfo", dest="FilePlotInfo", default=None, help= "The input file for plotting parameters, include band structure with band characters indicated" ) parser.add_argument( "--copyk", dest="CopyKPoints", default=None, help= "Copy k-points information from given band.xml, instead of use what is read. This to make two plots have the same x-coord" ) parser.add_argument( "--removek", dest="RemoveKPoints", type=int, default=0, help= "Remove the first N k-points in the bandstructure, especially useful when plotting HSE / metaGGA bands that must be calculated with full M-P k-points self-consistently" ) parser.add_argument( "--kname", dest="NameK", default=None, help= "Provide a list of names of k-points that will be plotted, in format \" 1 Gamma 30 X 50 L\", indicies start from 1, this works before --removek" ) parser.add_argument( "--alignenergy", dest="AlignEnergy", default=None, help= "Manually specify the energy to align instead of using VBM/Fermi energy automatically read. The unit must be the same as what the package outputs." ) options = parser.parse_args() stProgram = uni_Package_Detect(options.Program, options.extra_args) band = uni_ReadBand(stProgram, options.extra_args) #Read k-points if (options.CopyKPoints is not None): band_copyk = BandsT.load_xml(options.CopyKPoints) band.kpt = band_copyk.kpt if (options.NameK is not None): list_name = options.NameK.split() for i in xrange(len(list_name) / 2): ix1 = int(list_name[i * 2]) - 1 name1 = list_name[i * 2 + 1] band.kpt.listKPt[ix1][0] = name1 #Read character informations info_plot = None if (options.FilePlotInfo is not None): with open(options.FilePlotInfo) as f: info_plot = json.loads(f.read()) if (info_plot.has_key("orb_map")): list_orb, list_character = uni_read_band_character(stProgram) if (stProgram == "w2k"): #Wien2K qtl is not good for plotting list_character = w2k_rescale_character(band.list_orb, band.list_character) #Add to band object for prop, orb, character in zip(band.prop, list_orb, list_character): prop.orb = orb prop.character = character #Remove extra k-points if (options.RemoveKPoints > 0): band = f_band_remove_k(band, options.RemoveKPoints) #Resolving crossing if (options.ResolveCorssing): band.resolve_crossing() #Unit conversion unit_k = options.KPointsUnit.lower() if (unit_k != "default" and band.kpt.stMode != unit_k): print("Convert k-point unit from %s to %s" % (band.kpt.stMode, unit_k)) #band.kpt.ConvertUnit(unit_k,band.kpt.latt.PrimitiveCellVector) band.kpt.ConvertUnit(unit_k) nElectronInput = int(options.Electron) if (nElectronInput != 0): band.num_electron = nElectronInput #Align energy if (options.AlignEnergy is not None): e1 = float(options.AlignEnergy) band.fermi = e1 band.vbm = e1 # f_Band_Analyse(listBand) band.show_info(( band.fermi if band.b_metal else band.vbm) if options.Align else None) # f_Band_SaveData(aKPt,listBand,dVBM,options.OutputDir,nElectron,not options.FormatOnly,options.Align) if (os.path.exists(options.OutputDir) and not options.ForceOverwrite): print( "Warning:Directory %s already exists, band structure information will not be saved!" % options.OutputDir) return band.save(options.OutputDir, b_plot=not options.FormatOnly, align=BandsT.align_auto if options.Align else BandsT.align_none, plotinfo=info_plot)
def vasp_ReadBand(stFileName="EIGENVAL",filetype=None): ''' Read k-point and band from vasp EIGENVAL file or OUTCAR file WARNING: EIGENVAL does not handle non-integer electrons! Use OUTCAR or vasprun.xml if it is that case Note the structure is always read from vasprun.xml Another problem is the occuptation numbers are 1 in vasprun.xml and 2 in OUTCAR, if spin unpolarized :param stFileName: the file to read bandstructure :param filetype: the file type to read, can be OUTCAR or EIGENVAL. Automatically inferred from stFileName if set to None ''' if (filetype is None): if ("EIGENVAL" in stFileName): filetype = "EIGENVAL" elif ("vasprun.xml" in stFileName): filetype = "vasprun.xml" else: filetype = "OUTCAR" f = open(stFileName) ar_stLine = f.readlines() f.close() list_kp = [] list_band = [] list_band2 = [] list_occ = None bElectronFraction = False if (filetype == "EIGENVAL"): #Note we cannot determine LNONCOLLINEAR in EIGENVAL, assume false b_noncoll = False num_spin = int(ar_stLine[0].split()[3]) (nElectron,nKPt,nbnd) = [int(x) for x in ar_stLine[5].split()] for i in range(0,nKPt): i2 = i * (nbnd+2) + 7 list_kp.append([float(x) for x in ar_stLine[i2].split()]) ar2 =[x.split() for x in ar_stLine[i2+1:i2+nbnd+1]] list_band.append([float(x[1]) for x in ar2]) if (num_spin == 2): list_band2.append([float(x[2]) for x in ar2]) if (num_spin == 2): list_band = [list_band,list_band2] elif (filetype == "OUTCAR"): def read_tag(tag, i0): val = None for i in xrange(i0, len(ar_stLine)): line = ar_stLine[i] if (tag in line): val = line.split()[2] break if (val is None): raise ValueError("Cannot find tag %s" % tag) return val, i list_occ = [] list_occ2 = [] i = 0 num_spin, i = read_tag("ISPIN", i) num_spin = int(num_spin) b_noncoll, i = read_tag("LNONCOLLINEAR", i) b_noncoll = b_noncoll == "T" nElectron, i = read_tag("NELECT", i) dElectron = float(nElectron) nElectron = int(dElectron) bElectronFraction = abs(dElectron != nElectron) > 1e-7 # if (bElectronFraction): # print("The number of electrons is not an integer.") efermi, i = read_tag("E-fermi", i) efermi = float(efermi) i += 2 if (num_spin != 1): i += 2 list_band_now = list_band list_occ_now = list_occ while (len(ar_stLine[i+1])>4): i += 1 if (list_band_now == list_band): list_kp.append([float(x) for x in ar_stLine[i].split()[-3:]]) i += 2 ar2 = [] ar_occ = [] line = ar_stLine[i] while (len(line) > 4): ar_line = line.split() ar2.append(float(ar_line[1])) ar_occ.append(float(ar_line[2])) i += 1 line = ar_stLine[i] list_band_now.append(ar2) list_occ_now.append(ar_occ) if (num_spin != 1 and "spin" in ar_stLine[i+1]): list_band_now = list_band2 list_occ_now = list_occ2 i += 2 nKPt = len(list_band) nbnd = len(list_band[0]) # print(nElectron, nKPt, nbnd) if (num_spin == 2): list_band = [list_band, list_band2] list_occ = [list_occ, list_occ2] elif (filetype == "vasprun.xml"): #Read from vasprun.xml for event, elem in ET.iterparse(stFileName,events=('end',)): if (elem.tag == "parameters"): node_parameters = elem elif (elem.tag == "eigenvalues"): node_eigenvalues = elem elif (elem.tag == "kpoints"): node_kpoints = elem elif (elem.tag == "dos"): node_dos = elem break #Read LNONCOLLINEAR b_noncoll = node_parameters.find('./separator[@name="electronic"]/separator[@name="electronic spin"]/i[@name="LNONCOLLINEAR"]').text b_noncoll = b_noncoll.strip() == "T" #Read NELECT dElectron = float(node_parameters.find('./separator[@name="electronic"]/i[@name="NELECT"]').text) nElectron = int(dElectron) bElectronFraction = abs(dElectron != nElectron) > 1e-7 #Read band node_band = node_eigenvalues list_band = [] list_occ = [] list_occ2 = [] #3-level nested , hard to read so split them for node1 in node_band.findall("./array/set/set"): #Spin band_spin = [] occ_spin = [] for node2 in node1.findall("./set"): #Kpt data_kpt = [node3.text.split() for node3 in node2.findall("./r")] band_spin.append([float(x[0]) for x in data_kpt]) occ_spin.append([float(x[1]) for x in data_kpt]) list_band.append(band_spin) list_occ.append(occ_spin) # list_band = reduce(lambda x,y: x+y, list_band) # list_occ = reduce(lambda x,y: x+y, list_occ) #Read kpoints coordinates list_kp = [[float(x) for x in nodek.text.split()] for nodek in node_kpoints.findall('./varray[@name="kpointlist"]/v')] #Read other properties num_spin = int(node_parameters.find('./separator[@name="electronic"]/separator[@name="electronic spin"]/i[@name="ISPIN"]').text) efermi = float(node_dos.find('./i[@name="efermi"]').text) #Do not use array for each spin if only 1 spin if (num_spin == 1): list_band = list_band[0] list_occ = list_occ[0] aKPT = KPointsT() aKPT.ReadFromList(list_kp) aKPT.stMode = "crystal" #OUTCAR is not necasseary, it is used to convert k-point unit try: latt = vasp_read_latt("initialpos","vasprun.xml") except ET.ParseError: matR,matK = vasp_ReadLattVec("OUTCAR") latt = Lattice() latt.ReadFromRawCellVector(matR) aKPT.latt = latt # aKPT.ConvertUnit("cart",matR) aKPT.ConvertUnit("cart") #Each band is assumed to be double occupied in BandsT #So we use 2 times electron in NONCOLLINEAR where only single occupied if (b_noncoll): print("Noncollinear calculation, band.electron = 2*actual electrons") nElectron *= 2 band = BandsT(aKPT,list_band,None,None,nElectron,num_spin, list_occ=list_occ) #Calculate VBM #Only do if the number of electrons is an integer if (bElectronFraction): band.fermi = efermi else: if (not band.guess_vbm()): band.fermi = vasp_getout("efer") # return aKPT,list_band,dVBM,nElectron,1 return band
def yambo_read_band(filename, filename_pw_xml=None): ''' Read band structure from yambo o-*.qp file Additional data-file.xml can be used to indicate information Lattice is a fake and not used ''' with open(filename, 'r') as f: lines = f.readlines() ar = [[float(x) for x in line.split()] for line in lines if line[0] != "#"] for a1 in ar: a1[0] = int(a1[0]) a1[1] = int(a1[1]) ix_k = [x[0] for x in ar] ix_b = [x[1] for x in ar] ix_k_min = min(ix_k) ix_k_max = max(ix_k) ix_b_min = min(ix_b) ix_b_max = max(ix_b) #If spin=2, there is 6th column for spin #If not, only 5 columns if (len(ar[0]) == 5): num_spin = 1 elif (len(ar[0]) == 6): num_spin = 2 else: raise ValueError("Unknown number of columns %i" % len(ar[0])) if (filename_pw_xml is not None): band = qesp_read_band(filename_pw_xml) if (band.num_spin != num_spin): raise ValueError("Inconsistent spin for QE file and Yambo file") #Modify bands #Set spin if (num_spin == 1): for a1 in ar: a1.append(0) else: for a1 in ar: a1[-1] = int((1 - a1[-1]) / 2) #Set GW eigenvalues #Note yambo make a shift to input DFT bands to make KS VBM=0, #We shuold get it back #Method 1 : calc shift and apply it to Yambo data # a = ar[0] # shift = a[2] - band.prop[a[-1]].eig[a[0]-1][a[1]-1] # for a in ar: # band.prop[a[-1]].eig[a[0]-1][a[1]-1] = a[2] + a[3] - shift #Method 2 : add the correction to DFT instead of reading yambo DFT for a in ar: band.prop[a[-1]].eig[a[0] - 1][a[1] - 1] += a[3] #Calculate properties if (band.vbm is not None): #Clear and recalculate band.vbm = None band.guess_vbm() else: if (num_spin == 1): list_eig = [[None] * (ix_b_max - ix_b_min + 1) for x in range(ix_k_max - ix_k_min + 1)] for x in ar: #Eo + (E-Eo) list_eig[x[0] - ix_k_min][x[1] - ix_b_min] = x[2] + x[3] elif (num_spin == 2): num_spin = 2 list_eig = [[[None] * (ix_b_max - ix_b_min + 1) for x in range(ix_k_max - ix_k_min + 1)], [[None] * (ix_b_max - ix_b_min + 1) for x in range(ix_k_max - ix_k_min + 1)]] for x in ar: #Eo + (E-Eo) list_eig[int( (1 - x[5]) / 2)][x[0] - ix_k_min][x[1] - ix_b_min] = x[2] + x[3] #Dummy kpt latt = Lattice() latt.ReadFromRawCellVector([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) kpt = KPointsT() kpt.ReadFromList([[x, 0, 0] for x in range(len(list_eig))]) kpt.unit = "crystal" kpt.latt = latt band = BandsT(kpt, list_eig, num_spin=num_spin) return band
def wann_read_band(filename_band, filename_kpt=None, filename_gnu=None, filename_out=None): ''' Read band structure information from wannier90 output Indeed wannier90 output can be directly plotted but sometimes we need to combine two picture! :param filename_band: the name of eigenvalues ( normally seedname_band.dat ) :param filename_kpt: the name of eigenvalues ( normally seedname_band.kpt;if not provided treated same as filename_band ) :param filename_gnu: the name of gnuplot script ( if not provided treated same as band filename) :param filename_out: the name of stdout ( if not provided deduced from band filename) ''' seedname = filename_band[:-9] if (filename_kpt == None): filename_kpt = seedname + "_band.kpt" if (filename_gnu == None): filename_gnu = seedname + "_band.gnu" if (filename_out == None): filename_out = seedname + ".wout" unit = wann_read_length_unit(filename_out) #K-points kpt1 = KPointsT() f = open(filename_kpt) n = int(f.readline()) list_k = [] for i in xrange(n): #Weight is ignored list_k.append([float(x) for x in f.readline().split()][0:3]) f.close() kpt1.ReadFromList(list_k) #Bands list_band = f_Data_ReadTwoCol(filename_band) list_kcoord = [float(x[0]) for x in list_band] list_band = [[float(y) for y in x[1:]] for x in list_band] #Special k-points from gnuplot f = open(filename_gnu) for line in f: if ("xtics" in line): line2 = line[line.index("(") + 1:line.index(")")] ar = line2.split(",") for spec in ar: kcoord_last = 0.0 kcoord_now = 0.0 spec_name = spec[spec.index('"') + 1:spec.rindex('"')].strip() spec_value = float(spec[spec.rindex('"') + 1:]) # print(spec_name,spec_value) #Search nearest point for i, value in enumerate(list_kcoord): # print(value) if (spec_value <= value): # if (abs(spec_value - value) <= abs(kcoord_last - spec_value)): kpt1.listKPt[i][0] = spec_name else: kpt1.listKPt[i - 1][0] = spec_name break kcoord_last = value #Detect the last one if not used if (i == len(list_kcoord) - 1): kpt1.listKPt[-1][0] = spec_name # print("Set kpt%i to %s" % ( i,spec_name)) break #Convert unit to Bohr #However list_kcoord is not used later, maybe useful later if (unit == "Ang"): print("Convert unit from Angstrom to Bohr") list_kcoord = [x * Ang2Bohr for x in list_kcoord] return BandsT(kpt1, list_band, None, None, None, 1)