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 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 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 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 Main(ArgList): description = '''Plot band structure or DOS from data including kpoint-energy data, kpoint list, kpoint name list ( for band ) or energy-DOS data, PDOS name ( for DOS). Fermi energy can be used to adjust position in the process. %prog --fermi 0.5 ''' usage = "%prog " parser = OptionParser(formatter=EmptyFormatter(), usage=usage, description=description) parser.add_option( "--band", dest="BandFileName", help= "Specify the energy data filename; This file should be a space or tabular split text file with all states in one k-points in one row" ) parser.add_option( "--kpt", dest="KptFileName", help= "Specify the k-point list filename; This file should be a space or tabular split text file with x,y,z coordinate of k-vector in one line. The order must be the same as band file" ) parser.add_option("--fermi", dest="FermiFileName", help="Specify the fermi energy filename.") parser.add_option( "-g", dest="Align", action="store_true", default=False, help= "If set to true, data will be modified to make E_F=0, otherwise a fermi level will be pointed out at its actual position" ) parser.add_option( "--band2", dest="Band2FileName", default=None, help= "Specify the second energy data filename; the second energy data file will be plotted in dot mode" ) parser.add_option("--fermi2", dest="Fermi2FileName", help="Specify the second fermi energy filename.") parser.add_option("--ymax", dest="Ymax", default=None, help="Maximum of Y axis") parser.add_option("--ymin", dest="Ymin", default=None, help="Minimum of Y axis") (options, args) = parser.parse_args(ArgList) if (len(args) != 1): parser.error("incorrect number of arguments.") #aKPT,list_band = f_ReadBandFile(options.stBandFileName,options.stKptFileName) list_band = f_Band_ReadFromFile(options.BandFileName) aKPT = KPointsT(options.KptFileName) if (options.Band2FileName != None): list_band2 = f_Band_ReadFromFile(options.Band2FileName) else: list_band2 = None eig_fermi = 0.0 if (options.FermiFileName != None): eig_fermi = f_ReadFileFloatValue(options.FermiFileName) if (eig_fermi == None): print("Warning: fermi file not found, use 0.0 instead") eig_fermi = 0.0 eig_fermi2 = 0.0 if (options.Fermi2FileName != None): eig_fermi2 = f_ReadFileFloatValue(options.Fermi2FileName) if (eig_fermi == None): print("Warning: second fermi file not found, use 0.0 instead") eig_fermi2 = 0.0 eig_max = None if options.Ymax == None else float(options.Ymax) eig_min = None if options.Ymin == None else float(options.Ymin) f_PlotBand(aKPT, list_band, eig_fermi, bAlignData=options.Align, list_band2=list_band2, eig_fermi2=eig_fermi2, y_min=eig_min, y_max=eig_max)
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)