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 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