Esempio n. 1
0
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
Esempio n. 2
0
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