def __init__(self, bandpath="./", dospath=None): """ Init method. Read vasprun.xml for the band structure calculation and the DOS calculation if a path is provided. The band structure is extracted using the fermi level of the dos calculation if available. Args: bandpath (str): path to vasprun.xml file of the band structure dospath (str): path to vasprun.xml file of the dos """ self.xmlbands = os.path.join(bandpath, "vasprun.xml") if os.path.exists(self.xmlbands): run = BSVasprun(self.xmlbands, parse_projected_eigen=True) else: raise FileNotFoundError("File {0} not found".format(self.xmlbands)) kpoints_file = os.path.join(bandpath, "KPOINTS") if dospath: self.xmldos = os.path.join(dospath, "vasprun.xml") if os.path.exists(self.xmldos): self.dosrun = Vasprun(self.xmldos) else: raise FileNotFoundError("File {0} not found".format(self.xmldos)) self.bands = run.get_band_structure(kpoints_file, line_mode=True, efermi=self.dosrun.efermi) else: self.xmldos = None self.dosrun = None self.bands = run.get_band_structure(kpoints_file, line_mode=True)
def readgap(vasprun, kpoints): run = BSVasprun(vasprun) bs = run.get_band_structure(kpoints) if (bs.is_metal()==False): return bs.get_cbm()['energy']-bs.get_vbm()['energy'] else: return 0
def band_gap(args): v = BSVasprun(args.vasprun) try: band_gap_value, vbm_info, cbm_info = band_gap_properties(v) print(f"CBM info {cbm_info}") print(f"VBM info {vbm_info}") print(f"band gap info {band_gap_value}") except TypeError: print("Metallic system")
def brillplot(filenames=None, prefix=None, directory=None, width=6, height=6, fonts=None, image_format="pdf", dpi=400): """Generate plot of first brillouin zone from a band-structure calculation. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to input files. Vasp: Use vasprun.xml or vasprun.xml.gz file. image_format (:obj:`str`, optional): The image file format. Can be any format supported by matplotlib, including: png, jpg, pdf, and svg. Defaults to pdf. dpi (:obj:`int`, optional): The dots-per-inch (pixel density) for the image. """ if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) labels = {} for k in bs.kpoints: if k.label: labels[k.label] = k.frac_coords lines = [] for b in bs.branches: lines.append([ bs.kpoints[b['start_index']].frac_coords, bs.kpoints[b['end_index']].frac_coords ]) plt = pretty_plot_3d(width, height, dpi=dpi, fonts=fonts) fig = plot_brillouin_zone(bs.lattice_rec, lines=lines, labels=labels, ax=plt.gca()) basename = "brillouin.{}".format(image_format) filename = "{}_{}".format(prefix, basename) if prefix else basename if directory: filename = os.path.join(directory, filename) fig.savefig(filename, format=image_format, dpi=dpi, bbox_inches="tight") return plt
def __init__(self, folder, projected=False, hse=False, spin='up', kpath=None, n=None): """ Initialize parameters upon the generation of this class Inputs: ---------- folder: (str) This is the folder that contains the VASP files projected: (bool) Determined wheter of not to parte the projected eigenvalues from the vasprun.xml file. Making this true increases the computational time, so only use if a projected band structure is required. hse: (bool) Determines if the KPOINTS file is in the form of HSE or not. Only make true if the band structure was calculated using a hybrid functional. spin: (str) Choose which spin direction to parse. ('up' or 'down') """ self.vasprun = BSVasprun(f'{folder}/vasprun.xml', parse_projected_eigen=projected) self.poscar = Poscar.from_file(f'{folder}/POSCAR', check_for_POTCAR=False, read_velocities=False) self.projected = projected self.hse = hse self.kpath = kpath self.n = n self.folder = folder self.spin = 'up' self.spin_dict = {'up': Spin.up, 'dowm': Spin.down} self.bands_dict = self.load_bands() self.color_dict = { 0: '#FF0000', 1: '#0000FF', 2: '#008000', 3: '#800080', 4: '#E09200', 5: '#FF5C77', 6: '#778392', 7: '#07C589', 8: '#40BAF2', } if projected: self.projected_dict = self.load_projected_bands() if not hse: self.kpoints = Kpoints.from_file(f'{folder}/KPOINTS')
def plot_orbital_projected_band_structure(filename='vasprun.xml', ylim=[-5, 5], orbitals=None, color_codes=None, spin=Spin.up, save_filename=None): if orbitals is None: plot_simple_smoothed_band_structure(filename=filename, ylim=ylim) else: v = BSVasprun(filename, parse_projected_eigen=True) print('read in vasprun xml file') bs = v.get_band_structure(line_mode=True) get_projected_plot_dots_local(bs, orbitals, color_codes=color_codes, ylim=ylim, spin=spin, filename=save_filename)
def test_get_band_structure(self): filepath = os.path.join(test_dir, 'vasprun_Si_bands.xml') vasprun = BSVasprun(filepath, parse_potcar_file=False) bs = vasprun.get_band_structure(kpoints_filename= os.path.join(test_dir, 'KPOINTS_Si_bands')) cbm = bs.get_cbm() vbm = bs.get_vbm() self.assertEqual(cbm['kpoint_index'], [13], "wrong cbm kpoint index") self.assertAlmostEqual(cbm['energy'], 6.2301, "wrong cbm energy") self.assertEqual(cbm['band_index'], {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands") self.assertEqual(vbm['kpoint_index'], [0, 63, 64]) self.assertAlmostEqual(vbm['energy'], 5.6158, "wrong vbm energy") self.assertEqual(vbm['band_index'], {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands") self.assertEqual(vbm['kpoint'].label, "\Gamma", "wrong vbm label") self.assertEqual(cbm['kpoint'].label, None, "wrong cbm label")
def bandplot(filenames=None, prefix=None, directory=None, vbm_cbm_marker=False, projection_selection=None, mode='rgb', interpolate_factor=4, circle_size=150, dos_file=None, ylabel='Energy (eV)', dos_label=None, elements=None, lm_orbitals=None, atoms=None, total_only=False, plot_total=True, legend_cutoff=3, gaussian=None, height=6., width=6., ymin=-6., ymax=6., colours=None, yscale=1, image_format='pdf', dpi=400, plt=None, fonts=None): """Plot electronic band structure diagrams from vasprun.xml files. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to vasprun.xml or vasprun.xml.gz file. If no filenames are provided, the code will search for vasprun.xml or vasprun.xml.gz files in folders named 'split-0*'. Failing that, the code will look for a vasprun in the current directory. If a :obj:`list` of vasprun files is provided, these will be combined into a single band structure. prefix (:obj:`str`, optional): Prefix for file names. directory (:obj:`str`, optional): The directory in which to save files. vbm_cbm_marker (:obj:`bool`, optional): Plot markers to indicate the VBM and CBM locations. projection_selection (list): A list of :obj:`tuple` or :obj:`string` identifying which elements and orbitals to project on to the band structure. These can be specified by both element and orbital, for example, the following will project the Bi s, p and S p orbitals:: [('Bi', 's'), ('Bi', 'p'), ('S', 'p')] If just the element is specified then all the orbitals of that element are combined. For example, to sum all the S orbitals:: [('Bi', 's'), ('Bi', 'p'), 'S'] You can also choose to sum particular orbitals by supplying a :obj:`tuple` of orbitals. For example, to sum the S s, p, and d orbitals into a single projection:: [('Bi', 's'), ('Bi', 'p'), ('S', ('s', 'p', 'd'))] If ``mode = 'rgb'``, a maximum of 3 orbital/element combinations can be plotted simultaneously (one for red, green and blue), otherwise an unlimited number of elements/orbitals can be selected. mode (:obj:`str`, optional): Type of projected band structure to plot. Options are: "rgb" The band structure line color depends on the character of the band. Each element/orbital contributes either red, green or blue with the corresponding line colour a mixture of all three colours. This mode only supports up to 3 elements/orbitals combinations. The order of the ``selection`` :obj:`tuple` determines which colour is used for each selection. "stacked" The element/orbital contributions are drawn as a series of stacked circles, with the colour depending on the composition of the band. The size of the circles can be scaled using the ``circle_size`` option. circle_size (:obj:`float`, optional): The area of the circles used when ``mode = 'stacked'``. dos_file (:obj:'str', optional): Path to vasprun.xml file from which to read the density of states information. If set, the density of states will be plotted alongside the bandstructure. elements (:obj:`dict`, optional): The elements and orbitals to extract from the projected density of states. Should be provided as a :obj:`dict` with the keys as the element names and corresponding values as a :obj:`tuple` of orbitals. For example, the following would extract the Bi s, px, py and d orbitals:: {'Bi': ('s', 'px', 'py', 'd')} If an element is included with an empty :obj:`tuple`, all orbitals for that species will be extracted. If ``elements`` is not set or set to ``None``, all elements for all species will be extracted. lm_orbitals (:obj:`dict`, optional): The orbitals to decompose into their lm contributions (e.g. p -> px, py, pz). Should be provided as a :obj:`dict`, with the elements names as keys and a :obj:`tuple` of orbitals as the corresponding values. For example, the following would be used to decompose the oxygen p and d orbitals:: {'O': ('p', 'd')} atoms (:obj:`dict`, optional): Which atomic sites to use when calculating the projected density of states. Should be provided as a :obj:`dict`, with the element names as keys and a :obj:`tuple` of :obj:`int` specifying the atomic indices as the corresponding values. The elemental projected density of states will be summed only over the atom indices specified. If an element is included with an empty :obj:`tuple`, then all sites for that element will be included. The indices are 0 based for each element specified in the POSCAR. For example, the following will calculate the density of states for the first 4 Sn atoms and all O atoms in the structure:: {'Sn': (1, 2, 3, 4), 'O': (, )} If ``atoms`` is not set or set to ``None`` then all atomic sites for all elements will be considered. total_only (:obj:`bool`, optional): Only extract the total density of states. Defaults to ``False``. plot_total (:obj:`bool`, optional): Plot the total density of states. Defaults to ``True``. legend_cutoff (:obj:`float`, optional): The cut-off (in % of the maximum density of states within the plotting range) for an elemental orbital to be labelled in the legend. This prevents the legend from containing labels for orbitals that have very little contribution in the plotting range. gaussian (:obj:`float`, optional): Broaden the density of states using convolution with a gaussian function. This parameter controls the sigma or standard deviation of the gaussian distribution. height (:obj:`float`, optional): The height of the plot. width (:obj:`float`, optional): The width of the plot. ymin (:obj:`float`, optional): The minimum energy on the y-axis. ymax (:obj:`float`, optional): The maximum energy on the y-axis. colours (:obj:`dict`, optional): Use custom colours for specific element and orbital combinations. Specified as a :obj:`dict` of :obj:`dict` of the colours. For example:: { 'Sn': {'s': 'r', 'p': 'b'}, 'O': {'s': '#000000'} } The colour can be a hex code, series of rgb value, or any other format supported by matplotlib. yscale (:obj:`float`, optional): Scaling factor for the y-axis. image_format (:obj:`str`, optional): The image file format. Can be any format supported by matplotlib, including: png, jpg, pdf, and svg. Defaults to pdf. dpi (:obj:`int`, optional): The dots-per-inch (pixel density) for the image. plt (:obj:`matplotlib.pyplot`, optional): A :obj:`matplotlib.pyplot` object to use for plotting. fonts (:obj:`list`, optional): Fonts to use in the plot. Can be a a single font, specified as a :obj:`str`, or several fonts, specified as a :obj:`list` of :obj:`str`. Returns: If ``plt`` set then the ``plt`` object will be returned. Otherwise, the method will return a :obj:`list` of filenames written to disk. """ if not filenames: filenames = find_vasprun_files() elif type(filenames) == str: filenames = [filenames] # only load the orbital projects if we definitely need them parse_projected = True if projection_selection else False # now load all the vaspruns and combine them together using the # get_reconstructed_band_structure function from pymatgen bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=parse_projected) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) # currently not supported as it is a pain to make subplots within subplots, # although need to check this is still the case if 'split' in mode and dos_file: logging.error('ERROR: Plotting split projected band structure with DOS' ' not supported.\nPlease use --projected-rgb or ' '--projected-stacked options.') sys.exit() if (projection_selection and mode == 'rgb' and len(projection_selection) > 3): logging.error('ERROR: RGB projected band structure only ' 'supports up to 3 elements/orbitals.' '\nUse alternative --mode setting.') sys.exit() # don't save if pyplot object provided save_files = False if plt else True dos_plotter = None dos_opts = None if dos_file: dos, pdos = load_dos(dos_file, elements, lm_orbitals, atoms, gaussian, total_only) dos_plotter = SDOSPlotter(dos, pdos) dos_opts = { 'plot_total': plot_total, 'legend_cutoff': legend_cutoff, 'colours': colours, 'yscale': yscale } plotter = SBSPlotter(bs) if projection_selection: plt = plotter.get_projected_plot(projection_selection, mode=mode, interpolate_factor=interpolate_factor, circle_size=circle_size, zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts) else: plt = plotter.get_plot(zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts) if save_files: basename = 'band.{}'.format(image_format) filename = '{}_{}'.format(prefix, basename) if prefix else basename if directory: filename = os.path.join(directory, filename) plt.savefig(filename, format=image_format, dpi=dpi, bbox_inches='tight') written = [filename] written += save_data_files(vr, bs, prefix=prefix, directory=directory) return written else: return plt
import pymatgen as mg from pymatgen.io.vasp.outputs import BSVasprun, Vasprun from pymatgen import Spin from pymatgen.electronic_structure.plotter import BSPlotter, BSDOSPlotter, DosPlotter import matplotlib.pyplot as plt run = BSVasprun('./vasprun.xml', parse_projected_eigen=True) bs = run.get_band_structure("KPOINTS") n = 0 for kpoints, e in zip(bs.kpoints, bs.bands[Spin.up][9,:]): n += 1 if n == 11: print('...') if 10 < n < 90: continue print("kx = %5.3f ky = %5.3f kz = %5.3f eps(k) = %8.4f" %(tuple(kpoints.frac_coords) + (e,))) bsplot = BSPlotter(bs) bsplot.get_plot(ylim=(-20, 10), zero_to_efermi=True) print(bs.efermi) ax = plt.gca() ax.set_title("NiO Band Structure", fontsize=20) xlim = ax.get_xlim() ax.hlines(0, xlim[0], xlim[1], linestyles='dashed', color='black') ax.plot((), (), 'b-', label="spin up") ax.plot((), (), 'r--', label="spin down")
band_gap = _get_bandgap(eigenvalues=eigenvalues_bg) band_data = np.append( eigenvalues, np.tile(kpoints, (eigenvalues.shape[0], 1, 1)), axis=2, ) np.save(os.path.join(folder, 'eigenvalues.npy'), band_data) return band_gap if __name__ == "__main__": get_bandgap(folder='../../vaspvis_data/band_InAs') run = BSVasprun('../../vaspvis_data/band_InAs/vasprun.xml') bs = run.get_band_structure('../../vaspvis_data/band_InAs/KPOINTS') print(bs.get_vbm()['energy'] - bs.efermi) print(bs.get_cbm()['energy'] - bs.efermi) print(bs.get_band_gap()) # get_bandgap2(folder='../../vaspvis_data/hseInAs') # high_symmetry_points = [ # [0.5,0,0.5], # [0,0,0], # [0.5,0,0.5], # ] # M = convert_slab( # bulk_path='./unfold/POSCAR_bulk', # slab_path='./unfold/POSCAR_sub_9_0_orientation_0', # index=[1,1,1], # )
def bandstats( filenames=None, num_sample_points=3, temperature=None, degeneracy_tol=1e-4, parabolic=True, ): """Calculate the effective masses of the bands of a semiconductor. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to vasprun.xml or vasprun.xml.gz file. If no filenames are provided, the code will search for vasprun.xml or vasprun.xml.gz files in folders named 'split-0*'. Failing that, the code will look for a vasprun in the current directory. If a :obj:`list` of vasprun files is provided, these will be combined into a single band structure. num_sample_points (:obj:`int`, optional): Number of k-points to sample when fitting the effective masses. temperature (:obj:`int`, optional): Find band edges within kB * T of the valence band maximum and conduction band minimum. Not currently implemented. degeneracy_tol (:obj:`float`, optional): Tolerance for determining the degeneracy of the valence band maximum and conduction band minimum. parabolic (:obj:`bool`, optional): Use a parabolic fit of the band edges. If ``False`` then nonparabolic fitting will be attempted. Defaults to ``True``. Returns: dict: The hole and electron effective masses. Formatted as a :obj:`dict` with keys: ``'hole_data'`` and ``'electron_data'``. The data is a :obj:`list` of :obj:`dict` with the keys: 'effective_mass' (:obj:`float`) The effective mass in units of electron rest mass, :math:`m_0`. 'energies' (:obj:`numpy.ndarray`) Band eigenvalues in eV. 'distances' (:obj:`numpy.ndarray`) Distances of the k-points in reciprocal space. 'band_id' (:obj:`int`) The index of the band, 'spin' (:obj:`~pymatgen.electronic_structure.core.Spin`) The spin channel 'start_kpoint' (:obj:`int`) The index of the k-point at which the band extrema occurs 'end_kpoint' (:obj:`int`) """ if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=False) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) if bs.is_metal(): logging.error("ERROR: System is metallic!") sys.exit() _log_band_gap_information(bs) vbm_data = bs.get_vbm() cbm_data = bs.get_cbm() logging.info("\nValence band maximum:") _log_band_edge_information(bs, vbm_data) logging.info("\nConduction band minimum:") _log_band_edge_information(bs, cbm_data) if parabolic: logging.info("\nUsing parabolic fitting of the band edges") else: logging.info("\nUsing nonparabolic fitting of the band edges") if temperature: logging.error("ERROR: This feature is not yet supported!") else: # Work out where the hole and electron band edges are. # Fortunately, pymatgen does this for us. Points at which to calculate # the effective mass are identified as a tuple of: # (spin, band_index, kpoint_index) hole_extrema = [] for spin, bands in vbm_data["band_index"].items(): hole_extrema.extend([(spin, band, kpoint) for band in bands for kpoint in vbm_data["kpoint_index"]]) elec_extrema = [] for spin, bands in cbm_data["band_index"].items(): elec_extrema.extend([(spin, band, kpoint) for band in bands for kpoint in cbm_data["kpoint_index"]]) # extract the data we need for fitting from the band structure hole_data = [] for extrema in hole_extrema: hole_data.extend( get_fitting_data(bs, *extrema, num_sample_points=num_sample_points)) elec_data = [] for extrema in elec_extrema: elec_data.extend( get_fitting_data(bs, *extrema, num_sample_points=num_sample_points)) # calculate the effective masses and log the information logging.info("\nHole effective masses:") for data in hole_data: eff_mass = fit_effective_mass(data["distances"], data["energies"], parabolic=parabolic) data["effective_mass"] = eff_mass _log_effective_mass_data(data, bs.is_spin_polarized, mass_type="m_h") logging.info("\nElectron effective masses:") for data in elec_data: eff_mass = fit_effective_mass(data["distances"], data["energies"], parabolic=parabolic) data["effective_mass"] = eff_mass _log_effective_mass_data(data, bs.is_spin_polarized) return {"hole_data": hole_data, "electron_data": elec_data}
from pymatgen.electronic_structure.plotter import DosPlotter, BSPlotter, BSDOSPlotter from pymatgen.electronic_structure.dos import Dos, CompleteDos from pymatgen.electronic_structure.bandstructure import BandStructure, BandStructureSymmLine from pymatgen.io.vasp.outputs import Vasprun, BSVasprun from pymatgen.core.structure import Structure vasp = Vasprun('vasprun.xml') bsvasp = BSVasprun('vasprun.xml', parse_projected_eigen=True) structure = Structure.from_file('POSCAR') #el = structure.composition.elements #print el cdos = vasp.complete_dos #print cdos.get_densities() tdos = vasp.tdos #Total dos calculated at the end of run idos = vasp.idos # Integrated dos calculated at the end of run pdos = vasp.pdos # List of list of PDos objects. Access as pdos[atomindex][orbitalindex] efermi = vasp.efermi eigenvalues = vasp.eigenvalues projected_eigenvalues = vasp.projected_eigenvalues bs = bsvasp.get_band_structure(line_mode=True) total_dos = tdos pdoss = pdos #CDOS = CompleteDos(structure,total_dos,pdoss) spd_dos = cdos.get_spd_dos #print spd_dos element_dos = cdos.get_element_dos #element_spd_dos = cdos.get_element_spd_dos(el) dosplotter = DosPlotter() Totaldos = dosplotter.add_dos('Total DOS', tdos) Integrateddos = dosplotter.add_dos('Integrated DOS', idos) #Pdos = dosplotter.add_dos('Partial DOS',pdos) #Spd_dos = dosplotter.add_dos('spd DOS',spd_dos)
def bands_plot(bandpath, dospath, make_bs_plot, make_dos_plot, title=None, figsize=(11.69, 8.27), ylim=(-10, 10), bandopt={}, dosopt={}, legendopt={}): """ Plot the band structure. The function assumes a KPOINTS file is present in bandpath folder and the band structure calculation was done in line mode. Args: bandpath (str): path to the vasprun.xml file of the band structure dospath (str): path to the vasprun.xml file of the DOS make_bs_plot (function): function in order to make the band structure plot make_dos_plot (function): function in order to make the DOS plot title (str): title of the plot figsize (tuple): figure size ylim (tuple): y boundaries of the plot bandopt (dict): options for the band plot given to make_bs_plot() dosopt (dict): options for the dos plot, that are : s, p, d, xlim and linewidth legendprop (dict): legend options """ # density of states xmldos = os.path.join(dospath, "vasprun.xml") print("Reading in file : {0}".format(xmldos)) dosrun = Vasprun(xmldos) # bands xmlbands = os.path.join(bandpath, "vasprun.xml") print("Reading in file : {0}".format(xmlbands)) kpoints_file = os.path.join(bandpath, "KPOINTS") bandrun = BSVasprun(xmlbands, parse_projected_eigen=True) print("Building band structure object") bands = bandrun.get_band_structure(kpoints_file, line_mode=True, efermi=dosrun.efermi) fig = plt.figure(figsize=figsize) if not title: fig.suptitle("Band structure diagram") else: fig.suptitle(title) if dosrun.is_spin: gs = GridSpec(1, 3, width_ratios=[2, 5, 2]) ax0 = plt.subplot(gs[0]) ax1 = plt.subplot(gs[1]) ax2 = plt.subplot(gs[2]) yticklabels = False else: gs = GridSpec(1, 2, width_ratios=[2, 1]) ax1 = plt.subplot(gs[0]) ax2 = plt.subplot(gs[1]) yticklabels = True gs.update(wspace=0) # band structure plot print("Making band structure plot") make_bs_plot(ax1, bands, yticklabels=yticklabels, **bandopt) # Density of states plot print("Making DOS plot") make_dos_plot(ax2, dosrun, Spin.up, **dosopt) if dosrun.is_spin: make_dos_plot(ax0, dosrun, Spin.down, **dosopt, reverse=True) # plot boundaries and legend if dosrun.is_spin: ax0.set_ylim(ylim) ax0.set_ylabel(r"$E - E_f$ / eV") else: ax1.set_ylabel(r"$E - E_f$ / eV") ax1.set_ylim(ylim) ax2.set_ylim(ylim) ax2.legend(**legendopt) print("save fig bsplot.pdf") plt.savefig("bsplot.pdf", format="pdf")
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotter import os os.chdir('/home/jinho93/half-metal/1.CrO2/3.band') vrun = BSVasprun('vasprun.xml') bs = vrun.get_band_structure('KPOINTS', line_mode=True) bsp = BSPlotter(bs) bsp.show()
import pymatgen as mg from pymatgen.io.vasp.outputs import BSVasprun, Vasprun from pymatgen import Spin from pymatgen.electronic_structure.plotter import BSPlotter, BSDOSPlotter, DosPlotter import matplotlib.pyplot as plt #The file "vasprun.xml" is in aim_data. Rename it after unzip. run = BSVasprun("vasprun.xml", parse_projected_eigen=True) bs = run.get_band_structure("KPOINTS") print("number of bands", bs.nb_bands) print("number of kpoints", len(bs.kpoints))
def plot(locs, parse=False, figsize=None, dpi=300, lw=1.0, save=False): for p in (My_Axes_X, My_Axes_Y): mpl.projections.register_projection(p) def setDos(axis, minor, spin=[Spin.up], lim=None): """ Set up plotting area for DOS. If bands are plotted, set y-axis to vertical""" def spines(zero, hide): for z in zero: axD.spines[z].set_position('zero') for h in hide: axD.spines[h].set_visible(False) if len(spin) == 1: if spin[0].value == 1: axD.set_title(u'DOS $\u2191$', **title) if axis == 'y': axD.set_xlim(0, lim[1]) spines(zero=['left', 'top'], hide=['right', 'bottom']) axD.yaxis.tick_left() else: axD.set_ylim(0, lim[1]) spines(zero=['right', 'bottom'], hide=['left', 'top']) axD.xaxis.tick_bottom() else: axD.set_title(u'DOS $\u2193$', **title) if axis == 'y': axD.set_xlim(lim[0], 0) spines(zero=['right', 'top'], hide=['left', 'bottom']) axD.yaxis.tick_right() else: axD.set_ylim(lim[0], 0) spines(zero=['right', 'top'], hide=['left', 'bottom']) axD.xaxis.tick_top() axD.xaxis.set_label_coords(0.5, -0.1) else: axD.set_title('DOS', **title) if axis == 'y': axD.set_xlim(lim) spines(zero=['left', 'top'], hide=['right', 'bottom']) axD.set_xlabel(u'$\u2193$ $\u2191$', **arrows) else: axD.set_ylim(lim) spines(zero=['right', 'bottom'], hide=['left', 'top']) axD.set_ylabel(u'$\u2190$ $\u2192$', **arrows) axD.xaxis.set_label_coords(0.5, -0.04) # define tick labels for density (in arbitrary units) if 'DOSticks' in dosopt: func = lambda x, pos: "" \ if np.isclose(x,0) else "%d" % x if np.equal(np.mod(x, 1), 0) else x else: func = lambda x, pos: "" if axis == 'y': # if bands are plotted... axD.xaxis.tick_top() axD.xaxis.set_major_formatter(FuncFormatter(func)) axD.yaxis.set_minor_locator(MultipleLocator(minor)) plt.subplots_adjust(top=0.92, bottom=0.08, left=0.12, right=0.96, hspace=0.2, wspace=0.2) else: axD.yaxis.tick_right() axD.set_xlabel("E - E$\mathrm{_f}$ (eV)", **axes) axD.yaxis.set_major_formatter(FuncFormatter(func)) axD.xaxis.set_minor_locator(MultipleLocator(minor)) plt.tight_layout() plt.subplots_adjust(top=0.85, bottom=0.21, left=0.08, right=0.91, hspace=0.2, wspace=0.2) global _axes _axes = [axD] if 'zoom' in dosopt and dosopt['zoom']: if len(dosopt['zoom']) > 2: axz = axD.inset_axes(dosopt['zoom'][2]) elif axis == 'y': axz = axD.inset_axes([0.5, 0., 0.5, 0.25]) else: axz = axD.inset_axes([0., 0.5, 0.25, 0.6]) axz.set_xlim(dosopt['zoom'][0]) axz.set_ylim(dosopt['zoom'][1]) axz.set_xticklabels('') axz.set_yticklabels('') axz.set_label('zoom') _axes.append(axz) axD.indicate_inset_zoom(axz) ########################################################################### # set general linewidth for plot borders for i in [ 'axes.linewidth', 'xtick.major.width', 'xtick.minor.width', 'ytick.major.width', 'ytick.minor.width' ]: mpl.rcParams[i] = lw # define plot axes global bandruns, dosruns, bands if parse: bandruns = [] dosruns = [] for i, loc in enumerate(locs): # proj = bandopt['projections'] if 'projections' in bandopt else False if 'bands' in plots or 'BZ' in plots: if parse: bandruns.append( BSVasprun(loc + "/bands.xml", parse_projected_eigen=True)) bands = bandruns[i].get_band_structure(loc + "/KPOINTS", line_mode=True, efermi=bandruns[i].efermi) if 'bands' in plots: figsize = figsize if figsize else (7, 8) fig = plt.figure(figsize=figsize) gs = fig.add_gridspec(1,5, wspace=0.3) if 'dos' in plots \ else fig.add_gridspec(1,2) # axB = fig.add_subplot(gs[0:3], projection='My_Axes_Y') axB = fig.add_subplot(gs[0:3]) axB.set_title('Band Structure', **title) axB.set_xlabel(r'Symmetry Points', **axes) axB.set_ylabel("E - E$\mathrm{_f}$ (eV)", **axes) axB.tick_params(axis='x', which='both', length=0, pad=5) axB.tick_params(axis='y', which='both', labelsize=ticks['fontsize']) plotBands(axB, bandruns[i], **bandopt) if 'dos' in plots: if parse: dosruns.append(Vasprun(loc + "\..\dos.xml")) if 'spin' in dosopt: spin = dosopt['spin'] else: if dosruns[i].is_spin: spin = [Spin.up, Spin.down] else: spin = [Spin.up] xlim = dosopt['xlim'] if 'xlim' in dosopt else (-4, 4) ylim = dosopt['ylim'] if 'ylim' in dosopt else (-15, 15) shift = dosopt['shift'] if 'shift' in dosopt else 0. if 'ylim' in dosopt: ylim = dosopt['ylim'] else: e = dosruns[-1].tdos.energies - \ dosruns[-1].tdos.get_cbm_vbm()[1] - shift ind = [ e.tolist().index(i) for i in e[(e > xlim[0]) & (e < xlim[1])] ] lim = max([ max(a[ind[0]:ind[-1]]) for a in dosruns[-1].tdos.densities.values() ]) ylim = (-lim, lim) vertical = dosopt['vertical'] if 'vertical' in dosopt else None if 'bands' in plots: # axD = fig.add_subplot(gs[3:5], sharey=axB, projection='My_Axes_Y') axD = fig.add_subplot(gs[3:5], sharey=axB) axD.tick_params(labelleft=False) setDos('y', 0.25, spin=spin, lim=ylim) plotDOS(fig, dosruns[i], **dosopt) else: if figsize: figsize = figsize elif vertical: figsize = (5, 10) else: figsize = (14, 5) fig = plt.figure(figsize=figsize) if vertical: # axD = fig.add_subplot(111,projection='My_Axes_Y') axD = fig.add_subplot(111) axD.set_ylim(xlim) setDos('y', 0.25, spin=spin, lim=ylim) plotDOS(fig, dosruns[i], orient='y', **dosopt) else: # axD = fig.add_subplot(111, projection='My_Axes_X') axD = fig.add_subplot(111) axD.set_xlim(xlim) setDos('x', 0.25, spin=spin, lim=ylim) plotDOS(fig, dosruns[i], orient='x', **dosopt) if 'BZ' in plots: plotBZ() if save: plt.savefig(loc + '/%s' % '_'.join(plots) + \ '.png', format='png', dpi=dpi)
def deltaBand(self): ispin_hse, nbands_hse, nkpts_hse = self.readInfo(self.vasprun_hse) ispin_dftu, nbands_dftu, nkpts_dftu = self.readInfo(self.vasprun_dftu) if nbands_hse != nbands_dftu: raise Exception('The band number of HSE and GGA+U are not match!') kpoints = [line for line in open(self.kpoints_hse) if line.strip()] kpts_diff = 0 for ii, line in enumerate(kpoints[3:]): if line.split()[3] != '0': kpts_diff += 1 if nkpts_hse - kpts_diff != nkpts_dftu: raise Exception('The kpoints number of HSE and GGA+U are not match!') run_hse = BSVasprun(self.vasprun_hse) bs_hse = run_hse.get_band_structure(self.kpoints_hse) run_dftu = BSVasprun(self.vasprun_dftu) bs_dftu = run_dftu.get_band_structure(self.kpoints_dftu) v_hse = [] v_dftu = [] v = {} if ispin_hse == 1 and ispin_dftu == 1: v_hse.append(self.access_eigen(run_hse,1)[kpts_diff:,:,0]) v_dftu.append(self.access_eigen(run_dftu,1)[:,:,0]) elif ispin_hse == 2 and ispin_dftu == 2: v_hse.append(self.access_eigen(run_hse,1)[kpts_diff:,:,0]) v_hse.append(self.access_eigen(run_hse,-1)[kpts_diff:,:,0]) v_dftu.append(self.access_eigen(run_dftu,1)[:,:,0]) v_dftu.append(self.access_eigen(run_dftu,-1)[:,:,0]) else: raise Exception('The spin number of HSE and GGA+U are not match!') v['hse'] = np.array(v_hse) v['dftu'] = np.array(v_dftu) edge = {} loc = {} efermi = {} efermi['hse'] = run_hse.efermi efermi['dftu'] = run_dftu.efermi for m in 'hse','dftu': spin = {} i = {} for s in range(ispin_hse): vbm = self.get_vbm(v[m][s],efermi[m]) cbm = self.get_cbm(v[m][s],efermi[m]) vbm_loc = max(np.where(v[m][s] == vbm)[1]) cbm_loc = min(np.where(v[m][s] == cbm)[1]) spin[s] = [vbm,cbm] i[s] = [vbm_loc,cbm_loc] edge[m] = spin loc[m] = i shifted_hse = np.concatenate(((v['hse'][0] - edge['hse'][0][0])[:,loc['hse'][0][0]-self.br+1:loc['hse'][0][0]+1], (v['hse'][0] - edge['hse'][0][1])[:,loc['hse'][0][1]:loc['hse'][0][1]+self.br]), axis = 1) if ispin_hse == 2: shifted_hse = np.concatenate((shifted_hse, (v['hse'][1] - edge['hse'][0][0])[:,loc['hse'][1][0]-self.br+1:loc['hse'][1][0]+1], (v['hse'][1] - edge['hse'][0][1])[:,loc['hse'][1][1]:loc['hse'][1][1]+self.br]), axis = 1) if ispin_dftu == 1: continuous = (loc['dftu'][0][1] - loc['dftu'][0][0]) == 1 elif ispin_dftu == 2: continuous = (loc['dftu'][0][1] - loc['dftu'][0][0]) == 1 & (loc['dftu'][1][1] - loc['dftu'][1][0]) == 1 else: raise Exception('Check your ISPIN for GGA+U') if bs_dftu.is_metal() == False or continuous == True: shifted_dftu = np.concatenate(((v['dftu'][0] - edge['dftu'][0][0])[:,loc['dftu'][0][0]-self.br+1:loc['dftu'][0][0]+1], (v['dftu'][0] - edge['dftu'][0][1])[:,loc['dftu'][0][1]:loc['dftu'][0][1]+self.br]), axis = 1) if ispin_dftu == 2: shifted_dftu = np.concatenate((shifted_dftu, (v['dftu'][1] - edge['dftu'][0][0])[:,loc['dftu'][1][0]-self.br+1:loc['dftu'][1][0]+1], (v['dftu'][1] - edge['dftu'][0][1])[:,loc['dftu'][1][1]:loc['dftu'][1][1]+self.br]), axis = 1) else: shifted_dftu = (v['dftu'][0] - edge['dftu'][0][0])[:,loc['dftu'][0][0]-self.br+1:loc['dftu'][0][0]+1+self.br] if ispin_dftu == 2: shifted_dftu = np.concatenate((shifted_dftu, (v['dftu'][1] - edge['dftu'][0][0])[:,loc['dftu'][1][0]-self.br+1:loc['dftu'][1][0]+1+self.br]), axis = 1) n = shifted_hse.shape[0] * shifted_hse.shape[1] delta_band = sum((1/n)*sum((shifted_hse - shifted_dftu)**2))**(1/2) if bs_dftu.is_metal()==False: gap = edge['dftu'][0][1] - edge['dftu'][0][0] else: gap = 0 incar = Incar.from_file('./dftu/band/INCAR') u = incar['LDAUU'] u.append(gap) u.append(delta_band) output = ' '.join(str(x) for x in u) with open('u.txt','a+') as f: f.write(output + '\n') f.close return delta_band
def bandplot_func( filenames=None, code='vasp', prefix=None, directory=None, vbm_cbm_marker=False, projection_selection=None, mode='rgb', pred=None, interpolate_factor=4, circle_size=150, dos_file=None, cart_coords=False, scissor=None, ylabel='Energy (eV)', dos_label=None, elements=None, lm_orbitals=None, atoms=None, spin=None, total_only=False, plot_total=True, legend_cutoff=3, gaussian=None, height=None, width=None, ymin=-6., ymax=6., colours=None, yscale=1, style=None, no_base_style=False, image_format='pdf', dpi=400, plt=None, fonts=None, boltz={ "ifinter": "T", "lpfac": "10", "energy_range": "50", "curvature": "", "load": "T", 'ismetaltolerance': '0.01' }, nelec=0): if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] # only load the orbital projects if we definitely need them parse_projected = True if projection_selection else False # now load all the band structure data and combine using the # get_reconstructed_band_structure function from pymatgen bandstructures = [] if code == 'vasp': for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=parse_projected) print("BSVasprun", type(vr), vr) print("vr.eigenvalues.keys()", type(vr.eigenvalues.keys()), vr.eigenvalues.keys()) if pred.any(): # Fill in Model prediction model = BSVasprun(vr_file, parse_projected_eigen=parse_projected) print("pred", type(pred), pred.shape) pred = np.expand_dims(pred, axis=-1) for key in model.eigenvalues.keys(): key_last = key print("model.eigenvalues[key][:, :, :].shape[0]", key, type(model.eigenvalues[key][:, :, :]), model.eigenvalues[key][:, :, :].shape, pred[:, :, :].shape) bands = min(model.eigenvalues[key][:, :, :].shape[1], pred.shape[1]) print( "bands", bands, "attention! max: ", max(model.eigenvalues[key][:, :, :].shape[1], pred.shape[1])) print( "equel False?", np.sum(model.eigenvalues[key][:, :bands, :] - pred[:, :bands, :])) model.eigenvalues[key][:, :bands, :] = pred[:, :bands, :] print( "equel True?", np.sum(model.eigenvalues[key][:, :bands, :] - pred[:, :bands, :])) print( "equel model vr?", np.sum(model.eigenvalues[key][:, :bands, :] - vr.eigenvalues[key][:, :bands, :])) # spin = 1 # for only plotting spin up oder down 1, -1 # model.eigenvalues[key_last][:, :bands, :] = pred[:, :bands, :] #boltztrap={'ifinter':False,'lpfac':10,'energy_range':50,'curvature':False}): if bool(boltz['ifinter']): b_data = VasprunBSLoader(vr) model_data = VasprunBSLoader(model) print("BSVasprunLoader", type(b_data), b_data) b_inter = BztInterpolator(b_data, lpfac=int(boltz['lpfac']), energy_range=float( boltz['energy_range']), curvature=bool(boltz['curvature']), save_bztInterp=True, load_bztInterp=bool(boltz['load'])) model_inter = BztInterpolator( model_data, lpfac=int(boltz['lpfac']), energy_range=float(boltz['energy_range']), curvature=bool(boltz['curvature']), save_bztInterp=True, load_bztInterp=bool(boltz['load'])) try: kpath = json.load(open('./kpath', 'r')) kpaths = kpath['path'] kpoints_lbls_dict = {} for i in range(len(kpaths)): for j in [0, 1]: if 'GAMMA' == kpaths[i][j]: kpaths[i][j] = '\Gamma' for k, v in kpath['kpoints_rel'].items(): if k == 'GAMMA': k = '\Gamma' kpoints_lbls_dict[k] = v except: kpaths = None kpoints_lbls_dict = None print(kpaths, kpoints_lbls_dict) bs = b_inter.get_band_structure( kpaths=kpaths, kpoints_lbls_dict=kpoints_lbls_dict) model_bs = model_inter.get_band_structure( kpaths=kpaths, kpoints_lbls_dict=kpoints_lbls_dict) #bs_uniform = b_inter.get_band_structure() gap = bs.get_band_gap() nvb = int(np.ceil(nelec / (int(bs.is_spin_polarized) + 1))) vbm = -100 print("WHC interpolated gap: %s" % gap) for spin, v in bs.bands.items(): vbm = max(vbm, max(v[nvb - 1])) print( 'WHC WARNNING vasp fermi %s interpolation vbm %s nelec %s nvb %s' % (bs.efermi, vbm, nelec, nvb)) if vbm < bs.efermi: bs.efermi = vbm print("if vbm <") if vbm < model_bs.efermi: model_bs.efermi = vbm print("if vbm <") print(bs.bands.keys()) band_keys = list(bs.bands.keys()) print("Band shapes", bs.bands[band_keys[0]].shape, model_bs.bands[band_keys[0]].shape) print( "equel bands?", np.sum((bs.bands[band_keys[0]] - bs.efermi) - model_bs.bands[band_keys[0]])) bs.bands[band_keys[0]] = ( bs.bands[band_keys[0]] - bs.efermi ) # why?????????????????????????????????????????????????? # bs.bands[band_keys[1]] = (bs.bands[band_keys[1]] - bs.efermi) # why?????????????????????????????????????????????????? print( "equel bands fermi shifted?", np.sum((bs.bands[band_keys[0]] - bs.efermi) - model_bs.bands[band_keys[0]])) # bandstructures.append(bs) # bandstructures.append(model_bs) bs = get_reconstructed_band_structure([bs]) model_bs = get_reconstructed_band_structure([model_bs]) if bool(boltz['ifinter']): bs.nvb = nvb bs.ismetaltolerance = float(boltz['ismetaltolerance']) model_bs.nvb = nvb model_bs.ismetaltolerance = float(boltz['ismetaltolerance']) print("dft bands", bs.bands[band_keys[0]]) print("dft ktps", len(bs.kpoints), kpts.shape) print("dft labels", bs.labels_dict) for key in bs.labels_dict.keys(): print(bs.labels_dict[key].label, bs.labels_dict[key].as_dict(), bs.labels_dict[key].a, bs.labels_dict[key].b, bs.labels_dict[key].c, bs.labels_dict[key].frac_coords) labels = [] for i in range(len(bs.kpoints)): # print(i, bs.kpoints[i]) for key in bs.labels_dict.keys(): if bs.labels_dict[key].label == bs.kpoints[ i].label and bs.labels_dict[ key].label != bs.kpoints[i - 1].label: # print("Labels!!!!!", i, bs.labels_dict[key].label) labels.append([i, bs.labels_dict[key].label]) print(labels) print("dft efermi", bs.efermi) print("dft lattice_rec", bs.lattice_rec) print("dft structure", bs.structure) print("model bands", model_bs.bands[band_keys[0]]) print("model ktps", len(model_bs.kpoints), kpts.shape) print("model labels", model_bs.labels_dict) print("model efermi", model_bs.efermi) print("model lattice_rec", model_bs.lattice_rec) print("model structure", model_bs.structure) return bs.bands[band_keys[0]], model_bs.bands[band_keys[0]], labels save_files = False if plt else True dos_plotter = None dos_opts = None if dos_file: dos, pdos = load_dos(dos_file, elements, lm_orbitals, atoms, gaussian, total_only) dos_plotter = SDOSPlotter(dos, pdos) dos_opts = { 'plot_total': plot_total, 'legend_cutoff': legend_cutoff, 'colours': colours, 'yscale': yscale } model_and_dft_bs = [bs, model_bs] plotter = SBSPlotter(model_bs) print("spin", spin) if len(vr.eigenvalues.keys()) == 1: spin = None print("spin", spin) plt = plotter.get_plot(zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts, style=style, no_base_style=no_base_style, spin=spin) # don't save if pyplot object provided save_files = False if plt else True if save_files: basename = 'band.{}'.format(image_format) filename = '{}_{}'.format(prefix, basename) if prefix else basename if directory: filename = os.path.join(directory, filename) plt.savefig(filename, format=image_format, dpi=dpi, bbox_inches='tight') written = [filename] written += save_data_files(bs, prefix=prefix, directory=directory) return written else: return plt
from pymatgen.electronic_structure.plotter import BSPlotterProjected from pymatgen.io.vasp.outputs import BSVasprun, Element path = '/home/jinho93/interface/pzt-bso/loose/opti/band/' vrun = BSVasprun(path + 'vasprun.xml', True, True) bs = vrun.get_band_structure(path + 'KPOINTS') plotter = BSPlotterProjected(bs) #plt = plotter.get_elt_projected_plots_color(elt_ordered=[Element.O, Element.Hf]) #plt = plotter.get_plot(ylim=(-8, 5), vbm_cbm_marker=True) plt = plotter.get_elt_projected_plots_color( elt_ordered=[Element.Ti, Element.Sn, Element.O]) plt.ylim((-5, 6)) plt.show()
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotter import pylab pylab.rcParams.update({'font.size': 48, 'text.usetex': True}) bs = BSVasprun('vasprun.xml') bst = bs.get_band_structure() plotter = BSPlotter(bst) plt = plotter.get_plot() plt.ylabel("$E - E_f$ (eV)") plt.xlabel("") plt.tight_layout() plt.show()
def get_Wif_from_WSWQ( wswqs: List, initial_vasprun: str, def_index: int, bulk_index: Sequence[int], spin: int = 0, kpoint: int = 1, fig=None ) -> List: """Compute the electron-phonon matrix element using the WSWQ files. Read in the WSWQ files to obtain the overlaps. Then compute the electron- phonon matrix elements from the overlaps as a function of Q. Parameters ---------- wswqs : list((Q, wswq_path)) a list of tuples where the first value is the Q and the second is the path to the directory that contains the WSWQ file initial_vasprun : string path to the initial vasprun.xml to extract the eigenvalue difference def_index : int index corresponding to the defect wavefunction (1-based indexing) bulk_index : int, list(int) index or list of indices corresponding to the bulk wavefunction (1-based indexing) spin : int spin channel to read from (0 - up, 1 - down) kpoint : int kpoint to read from (defaults to the first kpoint) fig : matplotlib.figure.Figure optional figure object to plot diagnostic information Returns ------- list((bulk_index, Wif)) electron-phonon matrix element Wif in units of eV amu^{-1/2} Angstrom^{-1} for each bulk_index """ bulk_index = np.array(bulk_index) Nw, Nbi = (len(wswqs), len(bulk_index)) Q, matels, deig = (np.zeros(Nw+1), np.zeros((Nbi, Nw+1)), np.zeros(Nbi)) # first compute the eigenvalue differences bvr = BSVasprun(initial_vasprun) sp = Spin.up if spin == 0 else Spin.down def_eig = bvr.eigenvalues[sp][kpoint-1][def_index-1][0] for i, bi in enumerate(bulk_index): deig[i] = bvr.eigenvalues[sp][kpoint-1][bi-1][0] - def_eig deig = np.abs(deig) # now compute for each Q for i, (q, fname) in enumerate(wswqs): Q[i] = q wswq = _read_WSWQ(fname) for j, bi in enumerate(bulk_index): matels[j, i] = np.sign(q) * \ np.abs(wswq[(spin+1, kpoint)][(bi, def_index)]) if fig is not None: ax = fig.subplots(1, Nbi) ax = np.array(ax) for a, i in zip(ax, range(Nbi)): tq = np.linspace(np.min(Q), np.max(Q), 100) a.scatter(Q, matels[i, :]) a.plot(tq, np.polyval(np.polyfit(Q, matels[i, :], 1), tq)) a.set_title(f'{bulk_index[i]}') return [(bi, deig[i] * np.polyfit(Q, matels[i, :], 1)[0]) for i, bi in enumerate(bulk_index)]
def bs_graph(rawdatadir, savedir, e_fermi, soc=False): run = BSVasprun("{}/vasprun.xml".format(rawdatadir), parse_projected_eigen=True) bs = run.get_band_structure(efermi=e_fermi, line_mode=True, force_hybrid_mode=True) bsplot = BSPlotter(bs) # Get the plot bsplot.get_plot(vbm_cbm_marker=True, ylim=(-1.5, 1.5), zero_to_efermi=True) bs_graph.e_fermi = float(bs.efermi) bs_graph.band_gap = float(bs.get_band_gap()["energy"]) ax = plt.gca() xlim = ax.get_xlim() ylim = ax.get_ylim() ax.hlines(0, xlim[0], xlim[1], linestyle="--", color="black") ax.tick_params(labelsize=20) if not soc: ax.plot((), (), "r-", label="spin up") ax.plot((), (), "b-", label="spin down") ax.legend(fontsize=16, loc="upper left") plt.savefig("{}/BSGraph".format(savedir)) plt.close() if not soc: # Print quick info about band gap (source: vasprun.xml) #print(bs_graph.e_fermi) #print(bs_graph.band_gap) # Get quick info about band gap (source: EIGENVAL) eigenval = Eigenval("{}/EIGENVAL".format(rawdatadir)) bs_graph.band_properties = eigenval.eigenvalue_band_properties # Get detailed info about band gap and CB/VB in each spin channel # (source: EIGENVAL) bs_graph.eigenvalues = eigenval.eigenvalues bs_graph.kpoints = eigenval.kpoints poscar = Poscar.from_file("{}/POSCAR".format(rawdatadir)) bs_graph.lattice = poscar.structure.lattice.reciprocal_lattice bs_graph.eigenvalues[Spin.up] = bs_graph.eigenvalues[ Spin.up][:, :, :-1] bs_graph.eigenvalues[Spin.down] = bs_graph.eigenvalues[ Spin.down][:, :, :-1] bs_graph.eigenvalues[Spin.up] = bs_graph.eigenvalues[Spin.up][:, :, 0] bs_graph.eigenvalues[Spin.down] = bs_graph.eigenvalues[Spin.down][:, :, 0] bs_graph.eigenvalues[Spin.up] = \ np.transpose(bs_graph.eigenvalues[Spin.up]) bs_graph.eigenvalues[Spin.down] = \ np.transpose(bs_graph.eigenvalues[Spin.down]) bs = BandStructure(bs_graph.kpoints, bs_graph.eigenvalues, bs_graph.lattice, bs_graph.e_fermi) bs_graph.vbm = bs.get_vbm()["energy"] bs_graph.cbm = bs.get_cbm()["energy"] bs_graph.electronic_gap = bs.get_band_gap()["energy"] bs_graph.direct = bs.get_band_gap()["direct"] if bs_graph.vbm and bs_graph.cbm and bs_graph.electronic_gap: bs_graph.gap_by_spin = bs.get_direct_band_gap_dict() return
#!/usr/bin/env python3 from pymatgen.io.vasp.outputs import BSVasprun raw = BSVasprun("vasprun.xml") bandstructure = raw.get_band_structure("KPOINTS") bandstructure.get_band_gap()
from pymatgen.io.vasp.outputs import BSVasprun from pymatgen.electronic_structure.plotter import BSPlotter from pymatgen.electronic_structure.core import Spin from pymatgen.electronic_structure.bandstructure import BandStructure import os # vaspout = BSVasprun("./hubbard/hub_Mn-5_Fe-5/vasprun.xml") vaspout = BSVasprun("../calc_seq_test/bands-mag/vasprun.xml") # 50 k-points = 0.3863000000000012 eV # 100 k-points = 0.38480000000000114 eV # 8x8x8 50 k-points = 0.39029999999999987 eV # 50 k-points with LASPH = 0.3932000000000002 eV bandstr = vaspout.get_band_structure(line_mode=True) print(bandstr.get_band_gap()) # print(bandstr.get_direct_band_gap_dict()) plt = BSPlotter(bandstr).get_plot(ylim=[-10, 5]) plt.show() # get band gap for all directories def get_band_gap(directory): vasp_out = BSVasprun(directory + "/vasprun.xml") band_str = vasp_out.get_band_structure(line_mode=True) band_gap = band_str.get_band_gap() print(band_gap) return band_gap
def plot(args): plt = None if args.band or args.bandcheck: bsp = BSPlotting(vasprun='vasprun.xml', kpoints='KPOINTS' ) #line the path of vasprun.xml using the argument if args.bandcheck: bsp.printinform() elif args.band: para = _load_yaml("B") plt = bsp.get_plot(figsize=para["fig_size"], zero_to_efermi=para["zero_to_efermi"], fontsize=para["fontsize"], spindownoff=True, color=para["color"], ylim=para["ylim"], vbm_cbm_marker=para["vbm_cbm_marker"]) elif args.dos or args.partial: para = _load_yaml("D") if args.dos: f = open(args.name, "r") filelist = f.readlines()[1:] dp = DOSPlotting(vasprun='vasprun.xml', dos=filelist, zero_to_efermi=para["zero_to_efermi"], stack=para["stack"]) plt = dp.get_plot(figsize=para["fig_size"], xlim=para["xlim"], ylim=para["ylim"], fontsize=para["font_size"], color=para["color"]) plt.legend(frameon=False) if args.partial: if args.name: filelist = [] ylim = [] color = palettable.colorbrewer.qualitative.Set1_9.mpl_colors for e, i in enumerate(args.name): f = open(i, "r") filelist = f.readlines()[1:] dp = DOSPlotting(vasprun='vasprun.xml', dos=filelist, zero_to_efermi=para["zero_to_efermi"], stack=para["stack"]) plt = dp.get_plot(figsize=para["fig_size"], xlim=para["xlim"], ylim=para["ylim"], fontsize=para["font_size"], color=color[e % 9], label=i.split(".")[0]) ax = plt.gca() ylim.append(ax.get_ylim()[-1]) ax.set_ylim(0, max(ylim)) plt.legend(fontsize=para["font_size"] / 2, loc="upper right", frameon=False) else: print("Please use the -n argument") sys.exit(0) filelist = f.readlines()[1:] elif args.bdos: run = Vasprun('vasprun.xml', parse_dos=True) dos = run.complete_dos vrun = BSVasprun('vasprun.xml', parse_projected_eigen=True) bs = vrun.get_band_structure('KPOINTS', efermi=dos.efermi) bdpara = _load_yaml("BD") bsdosplot = BSDOSPlotter(bs_projection=bdpara['bs_projection'], dos_projection=bdpara['dos_projection'], vb_energy_range=bdpara['vb_energy_range'], cb_energy_range=bdpara['cb_energy_range'], fixed_cb_energy=bdpara['fixed_cb_energy'], egrid_interval=bdpara['egrid_interval'], font=bdpara['font'], axis_fontsize=bdpara['axis_fontsize'], tick_fontsize=bdpara['tick_fontsize'], legend_fontsize=bdpara['legend_fontsize'], bs_legend=bdpara['bs_legend'], dos_legend=bdpara['dos_legend'], rgb_legend=bdpara['rgb_legend'], fig_size=bdpara['fig_size']) plt = bsdosplot.get_plot(bs, dos=dos) if plt: if args.out_file: plt.savefig("%s.%s" % (args.out_file, args.format)) else: plt.show()
def get_band_gap(directory): vasp_out = BSVasprun(directory + "/vasprun.xml") band_str = vasp_out.get_band_structure(line_mode=True) band_gap = band_str.get_band_gap() print(band_gap) return band_gap
def bandplot( filenames=None, code="vasp", prefix=None, directory=None, vbm_cbm_marker=False, projection_selection=None, mode="rgb", normalise="all", interpolate_factor=4, circle_size=150, dos_file=None, cart_coords=False, scissor=None, ylabel="Energy (eV)", dos_label=None, elements=None, lm_orbitals=None, atoms=None, spin=None, total_only=False, plot_total=True, legend_cutoff=3, gaussian=None, height=None, width=None, ymin=-6.0, ymax=6.0, colours=None, yscale=1, style=None, no_base_style=False, image_format="pdf", dpi=400, plt=None, fonts=None, ): """Plot electronic band structure diagrams from vasprun.xml files. Args: filenames (:obj:`str` or :obj:`list`, optional): Path to input files: Vasp: Use vasprun.xml or vasprun.xml.gz file. Questaal: Path to a bnds.ext file. The extension will also be used to find site.ext and syml.ext files in the same directory. Castep: Path to a seedname.bands file. The prefix ("seedname") is used to locate a seedname.cell file in the same directory and read in the positions of high-symmetry points. If no filenames are provided, sumo will search for vasprun.xml or vasprun.xml.gz files in folders named 'split-0*'. Failing that, the code will look for a vasprun in the current directory. If a :obj:`list` of vasprun files is provided, these will be combined into a single band structure. code (:obj:`str`, optional): Calculation type. Default is 'vasp'; 'questaal' and 'castep' also supported (with a reduced feature-set). prefix (:obj:`str`, optional): Prefix for file names. directory (:obj:`str`, optional): The directory in which to save files. vbm_cbm_marker (:obj:`bool`, optional): Plot markers to indicate the VBM and CBM locations. projection_selection (list): A list of :obj:`tuple` or :obj:`string` identifying which elements and orbitals to project on to the band structure. These can be specified by both element and orbital, for example, the following will project the Bi s, p and S p orbitals:: [('Bi', 's'), ('Bi', 'p'), ('S', 'p')] If just the element is specified then all the orbitals of that element are combined. For example, to sum all the S orbitals:: [('Bi', 's'), ('Bi', 'p'), 'S'] You can also choose to sum particular orbitals by supplying a :obj:`tuple` of orbitals. For example, to sum the S s, p, and d orbitals into a single projection:: [('Bi', 's'), ('Bi', 'p'), ('S', ('s', 'p', 'd'))] If ``mode = 'rgb'``, a maximum of 3 orbital/element combinations can be plotted simultaneously (one for red, green and blue), otherwise an unlimited number of elements/orbitals can be selected. mode (:obj:`str`, optional): Type of projected band structure to plot. Options are: "rgb" The band structure line color depends on the character of the band. Each element/orbital contributes either red, green or blue with the corresponding line colour a mixture of all three colours. This mode only supports up to 3 elements/orbitals combinations. The order of the ``selection`` :obj:`tuple` determines which colour is used for each selection. "stacked" The element/orbital contributions are drawn as a series of stacked circles, with the colour depending on the composition of the band. The size of the circles can be scaled using the ``circle_size`` option. normalise (:obj:`str`, optional): Normalisation the projections. Options are: * ``'all'``: Projections normalised against the sum of all other projections. * ``'select'``: Projections normalised against the sum of the selected projections. * ``None``: No normalisation performed. circle_size (:obj:`float`, optional): The area of the circles used when ``mode = 'stacked'``. cart_coords (:obj:`bool`, optional): Whether the k-points are read as cartesian or reciprocal coordinates. This is only required for Questaal output; Vasp output is less ambiguous. Defaults to ``False`` (fractional coordinates). scissor (:obj:`float`, optional): Apply a scissor operator (rigid shift of the CBM), use with caution if applying to metals. dos_file (:obj:'str', optional): Path to vasprun.xml file from which to read the density of states information. If set, the density of states will be plotted alongside the bandstructure. elements (:obj:`dict`, optional): The elements and orbitals to extract from the projected density of states. Should be provided as a :obj:`dict` with the keys as the element names and corresponding values as a :obj:`tuple` of orbitals. For example, the following would extract the Bi s, px, py and d orbitals:: {'Bi': ('s', 'px', 'py', 'd')} If an element is included with an empty :obj:`tuple`, all orbitals for that species will be extracted. If ``elements`` is not set or set to ``None``, all elements for all species will be extracted. lm_orbitals (:obj:`dict`, optional): The orbitals to decompose into their lm contributions (e.g. p -> px, py, pz). Should be provided as a :obj:`dict`, with the elements names as keys and a :obj:`tuple` of orbitals as the corresponding values. For example, the following would be used to decompose the oxygen p and d orbitals:: {'O': ('p', 'd')} atoms (:obj:`dict`, optional): Which atomic sites to use when calculating the projected density of states. Should be provided as a :obj:`dict`, with the element names as keys and a :obj:`tuple` of :obj:`int` specifying the atomic indices as the corresponding values. The elemental projected density of states will be summed only over the atom indices specified. If an element is included with an empty :obj:`tuple`, then all sites for that element will be included. The indices are 0 based for each element specified in the POSCAR. For example, the following will calculate the density of states for the first 4 Sn atoms and all O atoms in the structure:: {'Sn': (1, 2, 3, 4), 'O': (, )} If ``atoms`` is not set or set to ``None`` then all atomic sites for all elements will be considered. spin (:obj:`Spin`, optional): Plot only one spin channel from a spin-polarised calculation; "up" or "1" for spin up only, "down" or "-1" for spin down only. Defaults to ``None``. total_only (:obj:`bool`, optional): Only extract the total density of states. Defaults to ``False``. plot_total (:obj:`bool`, optional): Plot the total density of states. Defaults to ``True``. legend_cutoff (:obj:`float`, optional): The cut-off (in % of the maximum density of states within the plotting range) for an elemental orbital to be labelled in the legend. This prevents the legend from containing labels for orbitals that have very little contribution in the plotting range. gaussian (:obj:`float`, optional): Broaden the density of states using convolution with a gaussian function. This parameter controls the sigma or standard deviation of the gaussian distribution. height (:obj:`float`, optional): The height of the plot. width (:obj:`float`, optional): The width of the plot. ymin (:obj:`float`, optional): The minimum energy on the y-axis. ymax (:obj:`float`, optional): The maximum energy on the y-axis. style (:obj:`list` or :obj:`str`, optional): (List of) matplotlib style specifications, to be composed on top of Sumo base style. no_base_style (:obj:`bool`, optional): Prevent use of sumo base style. This can make alternative styles behave more predictably. colours (:obj:`dict`, optional): Use custom colours for specific element and orbital combinations. Specified as a :obj:`dict` of :obj:`dict` of the colours. For example:: { 'Sn': {'s': 'r', 'p': 'b'}, 'O': {'s': '#000000'} } The colour can be a hex code, series of rgb value, or any other format supported by matplotlib. yscale (:obj:`float`, optional): Scaling factor for the y-axis. image_format (:obj:`str`, optional): The image file format. Can be any format supported by matplotlib, including: png, jpg, pdf, and svg. Defaults to pdf. dpi (:obj:`int`, optional): The dots-per-inch (pixel density) for the image. plt (:obj:`matplotlib.pyplot`, optional): A :obj:`matplotlib.pyplot` object to use for plotting. fonts (:obj:`list`, optional): Fonts to use in the plot. Can be a a single font, specified as a :obj:`str`, or several fonts, specified as a :obj:`list` of :obj:`str`. Returns: If ``plt`` set then the ``plt`` object will be returned. Otherwise, the method will return a :obj:`list` of filenames written to disk. """ if not filenames: filenames = find_vasprun_files() elif isinstance(filenames, str): filenames = [filenames] # only load the orbital projects if we definitely need them parse_projected = True if projection_selection else False # now load all the band structure data and combine using the # get_reconstructed_band_structure function from pymatgen bandstructures = [] if code == "vasp": for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=parse_projected) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) elif code == "castep": for bands_file in filenames: cell_file = _replace_ext(bands_file, "cell") if os.path.isfile(cell_file): logging.info(f"Found cell file {cell_file}...") else: logging.info(f"Did not find cell file {cell_file}...") cell_file = None bs = castep_band_structure(bands_file, cell_file=cell_file) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) elif code == "questaal": bnds_file = filenames[0] ext = bnds_file.split(".")[-1] bnds_folder = os.path.join(bnds_file, os.path.pardir) site_file = os.path.abspath(os.path.join(bnds_folder, f"site.{ext}")) if os.path.isfile(site_file): logging.info("site file found, reading lattice...") site_data = QuestaalSite.from_file(site_file) bnds_lattice = site_data.structure.lattice alat = site_data.alat else: raise OSError( "Site file {} not found: " "needed to determine lattice".format(site_file) ) syml_file = os.path.abspath(os.path.join(bnds_folder, f"syml.{ext}")) if os.path.isfile(syml_file): logging.info("syml file found, reading special-point labels...") bnds_labels = labels_from_syml(syml_file) else: logging.info("syml file not found, band structure lacks labels") bnds_labels = {} bs = questaal_band_structure( bnds_file, bnds_lattice, alat=alat, labels=bnds_labels, coords_are_cartesian=cart_coords, ) # currently not supported as it is a pain to make subplots within subplots, # although need to check this is still the case if "split" in mode and dos_file: logging.error( "ERROR: Plotting split projected band structure with DOS" " not supported.\nPlease use --projected-rgb or " "--projected-stacked options." ) sys.exit() if projection_selection and mode == "rgb" and len(projection_selection) > 3: logging.error( "ERROR: RGB projected band structure only " "supports up to 3 elements/orbitals." "\nUse alternative --mode setting." ) sys.exit() # don't save if pyplot object provided save_files = False if plt else True dos_plotter = None dos_opts = None if dos_file: if code == "vasp": dos, pdos = load_dos( dos_file, elements, lm_orbitals, atoms, gaussian, total_only ) elif code == "castep": pdos_file = None if cell_file: pdos_file = _replace_ext(cell_file, "pdos_bin") if not os.path.isfile(pdos_file): pdos_file = None logging.info( f"PDOS file {pdos_file} does not exist, " "falling back to TDOS." ) else: logging.info(f"Found PDOS file {pdos_file}") else: logging.info( f"Cell file {cell_file} does not exist, " "cannot plot PDOS." ) dos, pdos = read_castep_dos( dos_file, pdos_file=pdos_file, cell_file=cell_file, gaussian=gaussian, lm_orbitals=lm_orbitals, elements=elements, efermi_to_vbm=True, ) dos_plotter = SDOSPlotter(dos, pdos) dos_opts = { "plot_total": plot_total, "legend_cutoff": legend_cutoff, "colours": colours, "yscale": yscale, } if scissor: bs = bs.apply_scissor(scissor) spin = string_to_spin(spin) # Convert spin name to pymatgen Spin object plotter = SBSPlotter(bs) if projection_selection: plt = plotter.get_projected_plot( projection_selection, mode=mode, normalise=normalise, interpolate_factor=interpolate_factor, circle_size=circle_size, zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts, style=style, no_base_style=no_base_style, spin=spin, ) else: plt = plotter.get_plot( zero_to_efermi=True, ymin=ymin, ymax=ymax, height=height, width=width, vbm_cbm_marker=vbm_cbm_marker, ylabel=ylabel, plt=plt, dos_plotter=dos_plotter, dos_options=dos_opts, dos_label=dos_label, fonts=fonts, style=style, no_base_style=no_base_style, spin=spin, ) if save_files: basename = f"band.{image_format}" filename = f"{prefix}_{basename}" if prefix else basename if directory: filename = os.path.join(directory, filename) plt.savefig(filename, format=image_format, dpi=dpi, bbox_inches="tight") written = [filename] written += save_data_files(bs, prefix=prefix, directory=directory) return written else: return plt
def __init__(self, vasprun='vasprun.xml',kpoints='KPOINTS'): self.bsrun = BSVasprun(vasprun, parse_potcar_file=False,parse_projected_eigen=True) self.bs = self.bsrun.get_band_structure(kpoints) self.bsdict = self.bs.as_dict()
def __init__(self, path): r""" Initialises an instance of the :class:`~effmass.inputs.Data` class and checks data using :meth:`check_data`. Args: path (str): Path to vasprun.xml. If the calculation was split along the k-path, the path should be to the folder which contains the splits. i.e. for mapi/split-01/vasprun.xml, mapi/split-02/vasprun.xml you would specify path=mapi Returns: None. """ super().__init__() # read in vasprun if path.endswith('vasprun.xml'): if os.path.exists(path): vr = BSVasprun(path) bs = vr.get_band_structure(line_mode=True) # read in vaspruns from multiple splits, parse_potcar is false because # it generates useless warnings, parse_projected is false because we # don't need projected eigenstates else: filenames = [] for fol in sorted(os.listdir(path)): vr_file = os.path.join(path, fol, "vasprun.xml") if os.path.exists(vr_file): filenames.append(vr_file) bandstructures = [] for vr_file in filenames: vr = BSVasprun(vr_file, parse_projected_eigen=False, parse_potcar_file=False) bs = vr.get_band_structure(line_mode=True) bandstructures.append(bs) bs = get_reconstructed_band_structure(bandstructures) bs_dict = bs.as_dict() # set occupancies below fermi as 0, above fermi as 1 occupancy = np.array(bs_dict['bands']['1']) occupancy[occupancy < bs_dict['efermi']] = 1 occupancy[occupancy > bs_dict['efermi']] = 0 # set spin channels spin = 2 if bs_dict['is_spin_polarized'] else 1 self.spin_channels = spin self.number_of_bands = len(bs_dict['bands']['1']) self.number_of_kpoints = len(bs_dict['kpoints']) self.energies = np.array(bs_dict['bands']['1']) self.occupancy = occupancy self.kpoints = np.array(bs_dict['kpoints']) self.fermi_energy = bs_dict['efermi'] self.reciprocal_lattice = bs_dict['lattice_rec']['matrix'] self.CBM = bs_dict['cbm']['energy'] self.VBM = bs_dict['vbm']['energy']
dosrun = Vasprun("DOS/vasprun.xml", parse_dos=True) dos = dosrun.complete_dos print("E_Fermi=%f%3s" % (dosrun.efermi, 'eV')) # print(dos.efermi) dosplot1 = DosPlotter(sigma=0.05) dosplot1.add_dos("Total DOS", dos) plt = dosplot1.get_plot(xlim=(-18, 15)) plt.grid() plt.savefig("pymatgen_DOS.eps", format="eps") plt.show() plt.close() # bsrun = BSVasprun("Band/vasprun.xml", parse_projected_eigen=True) bsrun = BSVasprun("Band/vasprun.xml") bs = bsrun.get_band_structure("Band/KPOINTS") bsplot = BSPlotter(bs) plt = bsplot.get_plot(bs) bsplot.plot_brillouin() bsplot.get_plot(ylim=(-18, 15), zero_to_efermi=True) plt.grid() plt.savefig("pymatgen_Band.eps", format="eps") plt.show() plt.close() # run = BSVasprun("Band/vasprun.xml", parse_projected_eigen=True) # dosrun = Vasprun("DOS/vasprun.xml", parse_dos=True) # dosrun = Vasprun("vasprun.xml", parse_dos=True) # dos = dosrun.complete_dos