def merge_up_down_doses(dos_up, dos_dn): """ Merge the up and down DOSs. Args: dos_up: Up DOS. dos_dn: Down DOS Return: CompleteDos object """ warnings.warn("This function is not useful anymore. VasprunBSLoader deals \ with spin case.") cdos = Dos( dos_up.efermi, dos_up.energies, { Spin.up: dos_up.densities[Spin.up], Spin.down: dos_dn.densities[Spin.down] }, ) if hasattr(dos_up, "pdos") and hasattr(dos_dn, "pdos"): pdoss = {} for site in dos_up.pdos: pdoss.setdefault(site, {}) for orb in dos_up.pdos[site]: pdoss[site].setdefault(orb, {}) pdoss[site][orb][Spin.up] = dos_up.pdos[site][orb][Spin.up] pdoss[site][orb][Spin.down] = dos_dn.pdos[site][orb][Spin.down] cdos = CompleteDos(dos_up.structure, total_dos=cdos, pdoss=pdoss) return cdos
def get_dos_from_id(self, task_id): """ Overrides the get_dos_from_id for the MIT gridfs format. """ args = {'task_id': task_id} fields = ['calculations'] structure = self.get_structure_from_id(task_id) dosid = None for r in self.query(fields, args): dosid = r['calculations'][-1]['dos_fs_id'] if dosid != None: self._fs = gridfs.GridFS(self.db, 'dos_fs') with self._fs.get(dosid) as dosfile: s = dosfile.read() try: d = json.loads(s) except: s = zlib.decompress(s) d = json.loads(s) tdos = Dos.from_dict(d) pdoss = {} for i in range(len(d['pdos'])): ados = d['pdos'][i] all_ados = {} for j in range(len(ados)): orb = Orbital.from_vasp_index(j) odos = ados[str(orb)] all_ados[orb] = {Spin.from_int(int(k)): v for k, v in odos['densities'].items()} pdoss[structure[i]] = all_ados return CompleteDos(structure, tdos, pdoss) return None
def read_gap_from_doscar(self, doscar): from pymatgen.electronic_structure.dos import Dos fp = open(doscar) lines = fp.readlines() energies = [] dos = [] efermi = float(lines[5].split()[3]) if len(lines[6].split()) == 5: # spin up and dn spin = 2 elif len(lines[6].split()) == 3: spin = 0 # no spin for i in range(6, len(lines)): energies.append(float(lines[i].split()[0])) if spin == 2: dos.append( float(lines[i].split()[1]) + float(lines[i].split()[2])) else: dos.append(float(lines[i].split()[1])) return { 'efermi': efermi, 'mygap': np.array( [Dos(efermi, energies, { 'spin': dos }).get_gap(spin='spin')]) }
def get_dos(self, partial_dos=False, npts_mu=10000, T=None): """ Return a Dos object interpolating bands Args: partial_dos: if True, projections will be interpolated as well and partial doses will be return. Projections must be available in the loader. npts_mu: number of energy points of the Dos T: parameter used to smooth the Dos """ spin = self.data.spin if isinstance(self.data.spin, int) else 1 energies, densities, vvdos, cdos = BL.BTPDOS(self.eband, self.vvband, npts=npts_mu) if T is not None: densities = BL.smoothen_DOS(energies, densities, T) tdos = Dos(self.efermi / units.eV, energies / units.eV, {Spin(spin): densities}) if partial_dos: tdos = self.get_partial_doses(tdos=tdos, npts_mu=npts_mu, T=T) return tdos
def get_dos_from_id(self, task_id): """ Overrides the get_dos_from_id for the MIT gridfs format. """ args = {'task_id': task_id} fields = ['calculations'] structure = self.get_structure_from_id(task_id) dosid = None for r in self.query(fields, args): dosid = r['calculations'][-1]['dos_fs_id'] if dosid != None: self._fs = gridfs.GridFS(self.db, 'dos_fs') with self._fs.get(dosid) as dosfile: s = dosfile.read() try: d = json.loads(s) except: s = zlib.decompress(s) d = json.loads(s) tdos = Dos.from_dict(d) pdoss = {} for i in range(len(d['pdos'])): ados = d['pdos'][i] all_ados = {} for j in range(len(ados)): orb = Orbital.from_vasp_index(j) odos = ados[str(orb)] all_ados[orb] = { Spin.from_int(int(k)): v for k, v in odos['densities'].items() } pdoss[structure[i]] = all_ados return CompleteDos(structure, tdos, pdoss) return None
def get_dos(db_file): """ return density of states object from the database """ d1, d2, d3, d4 = get_collections(db_file) db = get_db(db_file) fs = gridfs.GridFS(db, 'dos_fs') dos_fs_id = d4["calcs_reversed"][0]["dos_fs_id"] dos_json = zlib.decompress(fs.get(dos_fs_id).read()) dos_dict = json.loads(dos_json.decode()) return Dos.from_dict(dos_dict)
def from_dict(data): def _make_float_array(a): res = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] for i in range(3): for j in range(3): res[i][j] = float(a[i][j]) return res def _make_float_hall(a): return [i for i in a[:27]] return BoltztrapAnalyzer( float(data['gap']), [float(d) for d in data['mu_steps']], {int(d): [_make_float_array(v) for v in data['cond'][d]] for d in data['cond']}, {int(d): [_make_float_array(v) for v in data['seebeck'][d]] for d in data['seebeck']}, {int(d): [_make_float_array(v) for v in data['kappa'][d]] for d in data['kappa']}, {int(d): [_make_float_hall(v) for v in data['hall'][d]] for d in data['hall']}, {'p': [float(d) for d in data['doping']['p']], 'n': [float(d) for d in data['doping']['n']]}, {'p': {int(d): [float(v) for v in data['mu_doping']['p'][d]] for d in data['mu_doping']['p']}, 'n': {int(d): [float(v) for v in data['mu_doping']['n'][d]] for d in data['mu_doping']['n']}}, {'p': {int(d): [_make_float_array(v) for v in data['seebeck_doping']['p'][d]] for d in data['seebeck_doping']['p']}, 'n': {int(d): [_make_float_array(v) for v in data['seebeck_doping']['n'][d]] for d in data['seebeck_doping']['n']}}, {'p': {int(d): [_make_float_array(v) for v in data['cond_doping']['p'][d]] for d in data['cond_doping']['p']}, 'n': {int(d): [_make_float_array(v) for v in data['cond_doping']['n'][d]] for d in data['cond_doping']['n']}}, {'p': {int(d): [_make_float_array(v) for v in data['kappa_doping']['p'][d]] for d in data['kappa_doping']['p']}, 'n': {int(d): [_make_float_array(v) for v in data['kappa_doping']['n'][d]] for d in data['kappa_doping']['n']}}, {'p': {int(d): [_make_float_hall(v) for v in data['hall_doping']['p'][d]] for d in data['hall_doping']['p']}, 'n': {int(d): [_make_float_hall(v) for v in data['hall_doping']['n'][d]] for d in data['hall_doping']['n']}}, Dos.from_dict(data['dos']), data['carrier_conc'], data['dos_partial'], data['vol'], str(data['warning']))
def from_dict(data): def _make_float_array(a): res = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] for i in range(3): for j in range(3): res[i][j] = float(a[i][j]) return res def _make_float_hall(a): return [i for i in a[:27]] return BoltztrapAnalyzer( float(data['gap']), [float(d) for d in data['mu_steps']], {int(d): [_make_float_array(v) for v in data['cond'][d]] for d in data['cond']}, {int(d): [_make_float_array(v) for v in data['seebeck'][d]] for d in data['seebeck']}, {int(d): [_make_float_array(v) for v in data['kappa'][d]] for d in data['kappa']}, {int(d): [_make_float_hall(v) for v in data['hall'][d]] for d in data['hall']}, {'p': [float(d) for d in data['doping']['p']], 'n': [float(d) for d in data['doping']['n']]}, {'p': {int(d): [float(v) for v in data['mu_doping']['p'][d]] for d in data['mu_doping']['p']}, 'n': {int(d): [float(v) for v in data['mu_doping']['n'][d]] for d in data['mu_doping']['n']}}, {'p': {int(d): [_make_float_array(v) for v in data['seebeck_doping']['p'][d]] for d in data['seebeck_doping']['p']}, 'n': {int(d): [_make_float_array(v) for v in data['seebeck_doping']['n'][d]] for d in data['seebeck_doping']['n']}}, {'p': {int(d): [_make_float_array(v) for v in data['cond_doping']['p'][d]] for d in data['cond_doping']['p']}, 'n': {int(d): [_make_float_array(v) for v in data['cond_doping']['n'][d]] for d in data['cond_doping']['n']}}, {'p': {int(d): [_make_float_array(v) for v in data['kappa_doping']['p'][d]] for d in data['kappa_doping']['p']}, 'n': {int(d): [_make_float_array(v) for v in data['kappa_doping']['n'][d]] for d in data['kappa_doping']['n']}}, {'p': {int(d): [_make_float_hall(v) for v in data['hall_doping']['p'][d]] for d in data['hall_doping']['p']}, 'n': {int(d): [_make_float_hall(v) for v in data['hall_doping']['n'][d]] for d in data['hall_doping']['n']}}, Dos.from_dict(data['dos']), data['dos_partial'], data['carrier_conc'], data['vol'], str(data['warning']))
def _get_tdos(filename): energies, data, efermi, nsp = _read_dos_data(tdos_file, check_tdos=True) if nsp == 1: # densities = np.array(data[0]).reshape((ne, 1)) densities = {Spin.up: data[0]} elif nsp == 2: #densities = np.concatenate((data[0], data[1]), axis=1) densities = {Spin.up: data[0], Spin.down: data[1]} else: raise ValueError('There can\'t be {} spin channels, that makes ' 'no sense!'.format(nsp)) return Dos(efermi, energies, densities)
def merge_up_down_doses(dos_up, dos_dn): cdos = Dos(dos_up.efermi, dos_up.energies, {Spin.up: dos_up.densities[Spin.up], Spin.down: dos_dn.densities[Spin.down]}) if hasattr(dos_up, 'pdos') and hasattr(dos_dn, 'pdos'): pdoss = {} for site in dos_up.pdos: pdoss.setdefault(site, {}) for orb in dos_up.pdos[site]: pdoss[site].setdefault(orb, {}) pdoss[site][orb][Spin.up] = dos_up.pdos[site][orb][Spin.up] pdoss[site][orb][Spin.down] = dos_dn.pdos[site][orb][Spin.down] cdos = CompleteDos(dos_up.structure, total_dos=cdos, pdoss=pdoss) return cdos
def get_dos(self, partial_dos=False, npts_mu=10000, T=None, progress=False): """ Return a Dos object interpolating bands Args: partial_dos: if True, projections will be interpolated as well and partial doses will be return. Projections must be available in the loader. npts_mu: number of energy points of the Dos T: parameter used to smooth the Dos progress: Default False, If True a progress bar is shown when partial dos are computed. """ dos_dict = {} enr = (self.eband.min(), self.eband.max()) if self.data.is_spin_polarized: h = sum(np.array_split(self.accepted, 2)[0]) eband_ud = np.array_split(self.eband, [h], axis=0) vvband_ud = np.array_split(self.vvband, [h], axis=0) spins = [Spin.up, Spin.down] else: eband_ud = [self.eband] vvband_ud = [self.vvband] spins = [Spin.up] for spin, eb, vvb in zip(spins, eband_ud, vvband_ud): energies, densities, vvdos, cdos = BL.BTPDOS(eb, vvb, npts=npts_mu, erange=enr) if T: densities = BL.smoothen_DOS(energies, densities, T) dos_dict.setdefault(spin, densities) tdos = Dos(self.efermi / units.eV, energies / units.eV, dos_dict) if partial_dos: tdos = self.get_partial_doses(tdos, eband_ud, spins, enr, npts_mu, T, progress) return tdos
def calculate_dos(self, dos_estep: float = defaults["performance"]["dos_estep"], dos_width: float = defaults["performance"]["dos_width"]): """ Args: dos_estep: The DOS energy step, where smaller numbers give more accuracy but are more expensive. dos_width: The DOS gaussian smearing width in eV. """ all_energies = np.vstack([self.energies[spin] for spin in self.spins]) all_energies /= units.eV # convert from Hartree to eV for DOS # add a few multiples of dos_width to emin and emax to account for tails pad = dos_width if dos_width else 0 dos_emin = np.min(all_energies) - pad * 5 dos_emax = np.max(all_energies) + pad * 5 npts = int(round((dos_emax - dos_emin) / dos_estep)) logger.debug("DOS parameters:") log_list(["emin: {:.2f} eV".format(dos_emin), "emax: {:.2f} eV".format(dos_emax), "broadening width: {} eV".format(dos_width)]) emesh, densities = DOS(all_energies.T, erange=(dos_emin, dos_emax), npts=npts) if dos_width: densities = gaussian_filter1d(densities, dos_width / (emesh[1] - emesh[0])) # integrate up to Fermi level to get number of electrons efermi = self._efermi / units.eV energy_mask = emesh <= efermi + pad nelect = scipy.trapz(densities[energy_mask], emesh[energy_mask]) logger.debug("Intrinsic DOS Fermi level: {:.4f}".format(efermi)) logger.debug("DOS contains {:.3f} electrons".format(nelect)) dos = Dos(efermi, emesh, {Spin.up: densities}) self.dos_weight = 1 if self._soc or len(self.spins) == 2 else 2 self.dos = FermiDos(dos, structure=self.structure, dos_weight=self.dos_weight)
def get_cdos(): for n in range(1, 74): pdos = defaultdict(dict) atom = '' orb = '' for a in atoms: if os.path.exists(f'pwscf.pdos_atm#{n}({a})_wfc#{1}(s)'): atom = Element(a) if atom == '': continue for l, o in enumerate(orbital): if os.path.exists(f'pwscf.pdos_atm#{n}({str(atom)})_wfc#{l + 1}({o})'): orb = OrbitalType(l) data = np.genfromtxt(f'pwscf.pdos_atm#{n}({str(atom)})_wfc#{l + 1}({orb.name})') pdos[orb][Spin.up] = data[:, 1] pdos[orb][Spin.down] = data[:, 2] energies = data[:,0] pdoss.append(pdos) efermi = fermi_fromfile('report.scf') total_density= six.moves.reduce(add_densities, [six.moves.reduce(add_densities, p.values()) for p in pdoss]) total_dos = Dos(efermi, energies, total_density) s = Structure.from_file('123.cif') return CompleteDos(s, total_dos, pdoss)
def get_dos_plot(vasprun_file: str, cbm_vbm: list = None, pdos_type: str = "element", specific: list = None, orbital: list = True, xlim: list = None, ymaxs: list = None, zero_at_efermi: bool = True, legend: bool = True, crop_first_value: bool = True, show_spg: bool = True, symprec: float = SYMMETRY_TOLERANCE, angle_tolerance: float = ANGLE_TOL): """ Args: vasprun_file (str): vasprun.xml-type file name cbm_vbm (list): List of [cbm, vbm] pdos_type (str): Plot type of PDOS. "element": PDOS grouped by element type "site": PDOS grouped by equivalent sites "none": PDOS are not grouped. specific (list): Show specific PDOS. If list elements are integers, PDOS at particular sites are shown. If elements are shown, PDOS of particular elements are shown. ["1", "2"] --> At site 1 and 2 compatible with pdos_type = "none" ["Mg", "O"] --> Summed at Mg and O sites coompatible with pdos_type = "element" orbital (bool): Whether to show orbital decomposed PDOS. xlim (list): Specifies the x-axis limits. Set to None for automatic determination. ymaxs (list): Specifies the maxima of absolute y-axis limits. zero_at_efermi (bool): Whether to show the plot in the absolute scale. legend (bool): Whether to show the figure legend. crop_first_value (bool): Whether to crop the fist DOS. show_spg (bool): Whether to show space group number in the title. symprec (float): Symprec for determining the equivalent sites. """ v = Vasprun(vasprun_file, ionic_step_skip=True, parse_eigen=False) if v.converged_electronic is False: logger.warning("SCF is not attained in the vasp calculation.") complete_dos = v.complete_dos # check cbm if cbm_vbm is None: if complete_dos.get_gap() > 0.1: cbm_vbm = complete_dos.get_cbm_vbm() structure = v.final_structure dos = OrderedDict() # The CompleteDos behaves as DOS for total dos. dos["Total"] = complete_dos if specific and specific[0].isdigit(): if pdos_type is not "none": logger.warning( "pdos_type is changed from {} to none".format(pdos_type)) pdos_type = "none" elif specific and specific[0].isalpha(): if pdos_type is not "none": logger.warning( "pdos_type is changed from {} to element".format(pdos_type)) pdos_type = "element" sga = None grouped_indices = defaultdict(list) if pdos_type == "element": for indices, s in enumerate(structure): grouped_indices[str(s.specie)].append(indices) elif pdos_type == "site": # equivalent_sites: Equivalent site indices from SpacegroupAnalyzer. sga = SpacegroupAnalyzer(structure=structure, symprec=symprec, angle_tolerance=angle_tolerance) symmetrized_structure = sga.get_symmetrized_structure() # equiv_indices = [[0], [1], [2, 3], [4, 5]] equiv_index_lists = symmetrized_structure.equivalent_indices for l in equiv_index_lists: name = str(structure[l[0]].specie) + " " \ + sga.get_symmetry_dataset()["wyckoffs"][l[0]] grouped_indices[name] = l elif pdos_type == "none": for indices, s in enumerate(structure): grouped_indices[str(s.specie) + " site:" + str(indices)].append(indices) else: raise KeyError("The given pdos_type is not supported.") # TODO: Add specific handling # if specific: # tmp = defaultdict(list) # for key, value in grouped_indices.items(): # if pdos_type == "element" and key in specific: # tmp[key] = value # else: # # type(index) is str # index = ''.join(c for c in key if c.isdigit()) # if index in specific: # tmp[key] = value # grouped_indices = tmp # efermi is set to VBM if exists. efermi = cbm_vbm[1] if cbm_vbm else complete_dos.efermi complete_dos.efermi = efermi energies = complete_dos.energies for key, value in grouped_indices.items(): for indices in value: site = structure[indices] if orbital: for orb, pdos in complete_dos.get_site_spd_dos(site).items(): # " " is used for grouping the plots. if pdos_type == "none": name = key + " " + str(orb) else: name = \ key + " #" + str(len(value)) + " " + str(orb) density = divide_densities(pdos.densities, len(value)) if name in dos: density = add_densities(dos[name].densities, density) dos[name] = Dos(efermi, energies, density) else: dos[name] = Dos(efermi, energies, density) else: name = key + "(" + str(len(key)) + ")" pdos = complete_dos.get_site_dos(site) if name in dos: dos[name] = add_densities(dos[name], pdos) else: dos[name] = pdos # use complete_dos.efermi for total dos. plotter = ViseDosPlotter(zero_at_efermi=zero_at_efermi) plotter.add_dos_dict(dos) if xlim is None: xlim = [-10, 10] if ymaxs: ylims = [[-y, y] for y in ymaxs] \ if v.incar.get("ISPIN", 1) == 2 else [[0, y] for y in ymaxs] else: energies = complete_dos.energies - efermi tdos_max = max_density(complete_dos.densities, energies, xlim, crop_first_value) tdos_max *= 1.1 ylims = [[-tdos_max, tdos_max]] if v.incar.get("ISPIN", 1) == 2 \ else [[0, tdos_max]] pdos_max = 0.0 for k, d in dos.items(): if k == "Total": continue pdos_max = \ max(max_density(d.densities, energies, xlim), pdos_max) pdos_max *= 1.1 ylims.append([-pdos_max, pdos_max] if v.incar.get("ISPIN", 1) == 2 else [0, pdos_max]) print("y-range", ylims) if show_spg: if sga is None: sga = SpacegroupAnalyzer(structure, symprec=symprec) sg_num_str = str(sga.get_space_group_number()) sg = f" {sga.get_space_group_symbol()} ({sg_num_str})" print(f"Space group number: {sg}") title = f"{structure.composition} SG: {sg}" else: title = str(structure.composition) return plotter.get_plot(xlim=xlim, ylims=ylims, cbm_vbm=cbm_vbm, legend=legend, crop_first_value=crop_first_value, title=title)
def _parse_doscar(self): doscar = self._doscar tdensities = {} f = open(doscar) natoms = int(f.readline().split()[0]) efermi = float([f.readline() for nn in range(4)][3].split()[17]) dos = [] orbitals = [] for atom in range(natoms + 1): line = f.readline() ndos = int(line.split()[2]) orbitals.append(line.split(';')[-1].split()) line = f.readline().split() cdos = np.zeros((ndos, len(line))) cdos[0] = np.array(line) for nd in range(1, ndos): line = f.readline().split() cdos[nd] = np.array(line) dos.append(cdos) f.close() doshere = np.array(dos[0]) energies = doshere[:, 0] if not self._is_spin_polarized: tdensities[Spin.up] = doshere[:, 1] pdoss = [] spin = Spin.up for atom in range(natoms): pdos = defaultdict(dict) data = dos[atom + 1] _, ncol = data.shape orbnumber = 0 for j in range(1, ncol): orb = orbitals[atom + 1][orbnumber] pdos[orb][spin] = data[:, j] orbnumber = orbnumber + 1 pdoss.append(pdos) else: tdensities[Spin.up] = doshere[:, 1] tdensities[Spin.down] = doshere[:, 2] pdoss = [] for atom in range(natoms): pdos = defaultdict(dict) data = dos[atom + 1] _, ncol = data.shape orbnumber = 0 for j in range(1, ncol): if j % 2 == 0: spin = Spin.down else: spin = Spin.up orb = orbitals[atom + 1][orbnumber] pdos[orb][spin] = data[:, j] if j % 2 == 0: orbnumber = orbnumber + 1 pdoss.append(pdos) self._efermi = efermi self._pdos = pdoss self._tdos = Dos(efermi, energies, tdensities) self._energies = energies self._tdensities = tdensities final_struct = self._final_structure pdossneu = {final_struct[i]: pdos for i, pdos in enumerate(self._pdos)} self._completedos = LobsterCompleteDos(final_struct, self._tdos, pdossneu)
def read_tdos(bands_file, bin_width=0.01, gaussian=None, padding=None, emin=None, emax=None, efermi_to_vbm=True): """Convert DOS data from CASTEP .bands file to Pymatgen/Sumo format The data is binned into a regular series using np.histogram Args: bands_file (:obj:`str`): Path to CASTEP prefix.bands output file. The k-point positions, weights and eigenvalues are read from this file. bin_width (:obj:`float`, optional): Spacing for DOS energy axis gaussian (:obj:`float` or None, optional): Width of Gaussian broadening function padding (:obj:`float`, optional): Energy range above and below occupied region. (This is not used if xmin and xmax are set.) emin (:obj:`float`, optional): Minimum energy value for output DOS) emax (:obj:`float`, optional): Maximum energy value for output DOS efermi_to_vbm (:obj:`bool`, optional): If a bandgap is detected, modify the stored Fermi energy so that it lies at the VBM. Returns: :obj:`pymatgen.electronic_structure.dos.Dos` """ header = _read_bands_header_verbose(bands_file) logging.info("Reading band eigenvalues...") _, weights, eigenvalues = read_bands_eigenvalues(bands_file, header) calc_efermi = header['e_fermi'][0] * _ry_to_ev * 2 if efermi_to_vbm and not _is_metal(eigenvalues, calc_efermi): logging.info("Setting energy zero to VBM") efermi = _get_vbm(eigenvalues, calc_efermi) else: logging.info("Setting energy zero to Fermi energy") efermi = calc_efermi emin_data = min(eigenvalues[Spin.up].flatten()) emax_data = max(eigenvalues[Spin.up].flatten()) if Spin.down in eigenvalues: emin_data = min(emin_data, min(eigenvalues[Spin.down].flatten())) emax_data = max(emax_data, max(eigenvalues[Spin.down].flatten())) if padding is None and gaussian: padding = gaussian * 3 elif padding is None: padding = 0.5 if emin is None: emin = emin_data - padding if emax is None: emax = emax_data + padding # Shift sampling window to account for zeroing at VBM/EFermi emin += efermi emax += efermi bins = np.arange(emin, emax + bin_width, bin_width) energies = (bins[1:] + bins[:-1]) / 2 # Add rows to weights for each band so they are aligned with eigenval data weights = weights * np.ones([eigenvalues[Spin.up].shape[0], 1]) dos_data = { spin: np.histogram(eigenvalue_set, bins=bins, weights=weights)[0] for spin, eigenvalue_set in eigenvalues.items() } dos = Dos(efermi, energies, dos_data) if gaussian: dos.densities = dos.get_smeared_densities(gaussian) return dos
def read_dos( bands_file, pdos_file=None, cell_file=None, bin_width=0.01, gaussian=None, padding=None, emin=None, emax=None, efermi_to_vbm=True, lm_orbitals=None, elements=None, atoms=None, total_only=False, ): """Convert DOS data from CASTEP .bands file to Pymatgen/Sumo format The data is binned into a regular series using np.histogram Args: bands_file (:obj:`str`): Path to CASTEP prefix.bands output file. The k-point positions, weights and eigenvalues are read from this file. bin_width (:obj:`float`, optional): Spacing for DOS energy axis gaussian (:obj:`float` or None, optional): Width of Gaussian broadening function padding (:obj:`float`, optional): Energy range above and below occupied region. (This is not used if xmin and xmax are set.) emin (:obj:`float`, optional): Minimum energy value for output DOS) emax (:obj:`float`, optional): Maximum energy value for output DOS efermi_to_vbm (:obj:`bool`, optional): If a bandgap is detected, modify the stored Fermi energy so that it lies at the VBM. 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. Returns: (:obj:`pymatgen.electronic_structure.dos.Dos`, dict) where the dict is either empty or contains a PDOS arranged:: {species: {orbital: Dos}} """ header = _read_bands_header_verbose(bands_file) logging.info("Reading band eigenvalues...") _, weights, eigenvalues = read_bands_eigenvalues(bands_file, header) calc_efermi = header["e_fermi"][0] * _ry_to_ev * 2 if efermi_to_vbm and not _is_metal(eigenvalues, calc_efermi): logging.info("Setting energy zero to VBM") efermi = _get_vbm(eigenvalues, calc_efermi) else: logging.info("Setting energy zero to Fermi energy") efermi = calc_efermi emin_data = min(eigenvalues[Spin.up].flatten()) emax_data = max(eigenvalues[Spin.up].flatten()) if Spin.down in eigenvalues: emin_data = min(emin_data, min(eigenvalues[Spin.down].flatten())) emax_data = max(emax_data, max(eigenvalues[Spin.down].flatten())) if padding is None and gaussian: padding = gaussian * 3 elif padding is None: padding = 0.5 if emin is None: emin = emin_data - padding if emax is None: emax = emax_data + padding # Shift sampling window to account for zeroing at VBM/EFermi emin += efermi emax += efermi bins = np.arange(emin, emax + bin_width, bin_width) energies = (bins[1:] + bins[:-1]) / 2 # Add rows to weights for each band so they are aligned with eigenval data weights = weights * np.ones([eigenvalues[Spin.up].shape[0], 1]) dos_data = { spin: np.histogram(eigenvalue_set, bins=bins, weights=weights)[0] for spin, eigenvalue_set in eigenvalues.items() } dos = Dos(efermi, energies, dos_data) if pdos_file is not None and not total_only: if cell_file is None: raise OSError(f"Cell file {cell_file} not found: this must be " "provided for PDOS.") pdos_raw = compute_pdos(pdos_file, eigenvalues, weights, bins) # Also we, need to read the structure, but have it sorted with increasing # atomic numbers structure = CastepCell.from_file( cell_file).structure.get_sorted_structure( key=lambda x: x.species.elements[0].Z) pdoss = {} for isite, site in enumerate(structure.sites): pdoss[site] = pdos_raw[isite] # Get the pdos dictionary for potting pdos = get_pdos( CompleteDos(structure, dos, pdoss), lm_orbitals=lm_orbitals, elements=elements, atoms=atoms, ) # Smear the PDOS for orbs in pdos.values(): for dtmp in orbs.values(): if gaussian: dtmp.densities = dtmp.get_smeared_densities(gaussian) else: pdos = {} if gaussian: dos.densities = dos.get_smeared_densities(gaussian) return dos, pdos
import pytest from pymatgen.electronic_structure.dos import CompleteDos, Dos from pymatgen.core import Site from pymatgen.electronic_structure.core import Spin, Orbital from pymatgen.io.vasp import Vasprun from vise.analyzer.vasp.dos_data import DosDataFromVasp from vise.analyzer.plot_dos import DosPlotter efermi = 0.5 energies = [-1, 0, 1] tdos = [3, 4, 5] pdos = [1, 2, 3] total_dos = Dos(efermi=efermi, energies=energies, densities={Spin.up: tdos}) pdoses = { Site("H", [0, 0, 0]): { Orbital.s: { Spin.up: pdos }, Orbital.px: { Spin.up: pdos }, Orbital.py: { Spin.up: pdos }, Orbital.pz: { Spin.up: pdos }, Orbital.dxy: {
def get_dos( self, kpoint_mesh: Union[float, int, List[int]], energy_cutoff: Optional[float] = None, scissor: Optional[float] = None, bandgap: Optional[float] = None, estep: float = 0.01, width: float = 0.05, symprec: float = 0.01, fermi_dos: bool = False, ) -> Union[Dos, FermiDos]: """Calculates the density of states using the interpolated bands. Args: kpoint_mesh: The k-point mesh as a 1x3 array. E.g.,``[6, 6, 6]``. Alternatively, if a single value is provided this will be treated as a reciprocal density and the k-point mesh dimensions generated automatically. energy_cutoff: The energy cut-off to determine which bands are included in the interpolation. If the energy of a band falls within the cut-off at any k-point it will be included. For metals the range is defined as the Fermi level ± energy_cutoff. For gapped materials, the energy range is from the VBM - energy_cutoff to the CBM + energy_cutoff. scissor: The amount by which the band gap is scissored. Cannot be used in conjunction with the ``bandgap`` option. Has no effect for metallic systems. bandgap: Automatically adjust the band gap to this value. Cannot be used in conjunction with the ``scissor`` option. Has no effect for metallic systems. estep: The energy step, where smaller numbers give more accuracy but are more expensive. width: The gaussian smearing width in eV. symprec: The symmetry tolerance used when determining the symmetry inequivalent k-points on which to interpolate. fermi_dos: Whether to return a FermiDos object, instead of a regular Dos. Returns: The density of states. """ kpoints, weights = get_kpoints(kpoint_mesh, self._band_structure.structure, symprec=symprec) energies, efermi = self.get_energies( kpoints, scissor=scissor, bandgap=bandgap, energy_cutoff=energy_cutoff, atomic_units=False, return_efermi=True, ) emin = np.min([np.min(spin_eners) for spin_eners in energies.values()]) emin -= width * 5 if width else 0.1 emax = np.max([np.max(spin_eners) for spin_eners in energies.values()]) emax += width * 5 if width else 0.1 epoints = int(round((emax - emin) / estep)) dos = {} emesh = None for spin in self._spins: kpoint_weights = np.tile(weights / np.sum(weights), (len(energies[spin]), 1)) emesh, dos[spin] = get_dos( energies[spin].T, erange=(emin, emax), npts=epoints, weights=kpoint_weights.T, ) if width: dos[spin] = gaussian_filter1d(dos[spin], width / (emesh[1] - emesh[0])) if fermi_dos: return FermiDos(efermi, emesh, dos, self._band_structure.structure, atomic_units=False) else: return Dos(efermi, emesh, dos)
def from_file(filename1='feff.inp', filename2='ldos'): """" Creates FeffLdos object from raw Feff ldos files by by assuming they are numbered consequetively, i.e. ldos01.dat ldos02.dat... Args: filename1: input file of run to obtain structure filename2: output ldos file of run to obtain dos info, etc. """ ldos_filename = filename2 header_str = Header.header_string_from_file(filename1) header = Header.from_string(header_str) structure = header.struct nsites = structure.num_sites pot_string = FeffPot.pot_string_from_file(filename1) dicts = FeffPot.pot_dict_from_string(pot_string) pot_dict = dicts[0] with zopen(ldos_filename + "00.dat", "r") as fobject: f = fobject.readlines() efermi = float(f[0].split()[4]) dos_energies = [] ldos = {} for i in range(1, len(pot_dict) + 1): if len(str(i)) == 1: ldos[i] = np.loadtxt("{}0{}.dat".format(ldos_filename, i)) else: ldos[i] = np.loadtxt("{}{}.dat".format(ldos_filename, i)) for i in range(0, len(ldos[1])): dos_energies.append(ldos[1][i][0]) all_pdos = [] vorb = { "s": Orbital.s, "p": Orbital.py, "d": Orbital.dxy, "f": Orbital.f0 } forb = {"s": 0, "p": 1, "d": 2, "f": 3} dlength = len(ldos[1]) for i in range(nsites): pot_index = pot_dict[structure.species[i].symbol] all_pdos.append(defaultdict(dict)) for k, v in vorb.items(): density = [ ldos[pot_index][j][forb[k] + 1] for j in range(dlength) ] updos = density downdos = None if downdos: all_pdos[-1][v] = {Spin.up: updos, Spin.down: downdos} else: all_pdos[-1][v] = {Spin.up: updos} pdos = all_pdos vorb2 = {0: Orbital.s, 1: Orbital.py, 2: Orbital.dxy, 3: Orbital.f0} pdoss = { structure[i]: {v: pdos[i][v] for v in vorb2.values()} for i in range(len(pdos)) } forb = {"s": 0, "p": 1, "d": 2, "f": 3} tdos = [0] * dlength for i in range(nsites): pot_index = pot_dict[structure.species[i].symbol] for v in forb.values(): density = [ldos[pot_index][j][v + 1] for j in range(dlength)] for j in range(dlength): tdos[j] = tdos[j] + density[j] tdos = {Spin.up: tdos} dos = Dos(efermi, dos_energies, tdos) complete_dos = CompleteDos(structure, dos, pdoss) charge_transfer = FeffLdos.charge_transfer_from_file( filename1, filename2) return FeffLdos(complete_dos, charge_transfer)
def get_dos(self, kpoint_mesh: Union[float, int, List[int]], energy_cutoff: Optional[float] = None, scissor: Optional[float] = None, bandgap: Optional[float] = None, estep: float = 0.01, width: float = 0.05, symprec: float = 0.01 ) -> Dos: """Calculates the density of states using the interpolated bands. Args: kpoint_mesh: The k-point mesh as a 1x3 array. E.g.,``[6, 6, 6]``. Alternatively, if a single value is provided this will be treated as a reciprocal density and the k-point mesh dimensions generated automatically. energy_cutoff: The energy cut-off to determine which bands are included in the interpolation. If the energy of a band falls within the cut-off at any k-point it will be included. For metals the range is defined as the Fermi level ± energy_cutoff. For gapped materials, the energy range is from the VBM - energy_cutoff to the CBM + energy_cutoff. scissor: The amount by which the band gap is scissored. Cannot be used in conjunction with the ``bandgap`` option. Has no effect for metallic systems. bandgap: Automatically adjust the band gap to this value. Cannot be used in conjunction with the ``scissor`` option. Has no effect for metallic systems. estep: The energy step, where smaller numbers give more accuracy but are more expensive. width: The gaussian smearing width in eV. symprec: The symmetry tolerance used when determining the symmetry inequivalent k-points on which to interpolate. Returns: The density of states. """ kpoints, weights = _get_kpoints( kpoint_mesh, self._band_structure.structure, symprec=symprec) energies = self.get_energies( kpoints, scissor=scissor, bandgap=bandgap, energy_cutoff=energy_cutoff, atomic_units=False) energies = np.vstack([energies[spin] for spin in self._spins]) nbands = energies.shape[0] nkpts = energies.shape[1] emin = np.min(energies) - width * 5 emax = np.max(energies) + width * 5 epoints = int(round((emax - emin) / estep)) # BoltzTraP DOS kpoint_weights don't work as you'd expect so we include # the degeneracy manually all_energies = np.array([[energies[nb][nk] for nb in range(nbands)] for nk in range(nkpts) for _ in range(weights[nk])]) emesh, dos = DOS(all_energies, erange=(emin, emax), npts=epoints) dos = gaussian_filter1d(dos, width / (emesh[1] - emesh[0])) dos *= 1 if self._soc or len(self._spins) == 2 else 1 return Dos(self._band_structure.efermi, emesh, dos)
def setUp(self): with open(os.path.join(test_dir, "complete_dos.json"), "r") as f: self.dos = Dos.from_dict(json.load(f))
from pymatgen import Site from pymatgen.electronic_structure.dos import Dos import os dsp = DosPlotter() vrun = Vasprun('vasprun.xml') cdos = vrun.complete_dos atoms = [] i: Site dos = { 'd_in': Dos(cdos.efermi, cdos.energies, {Spin.up: np.zeros_like(cdos.energies)}), 'd_out': Dos(cdos.efermi, cdos.energies, {Spin.up: np.zeros_like(cdos.energies)}) } for i in vrun.final_structure.sites: if i.species_string == 'V': atoms.append(i) for j in atoms: for n, k in dos.items(): if n == 'd_in': dos[n] = k.__add__(cdos.get_site_orbital_dos(j, Orbital.dxy)) else: dos[n] = k.__add__(cdos.get_site_orbital_dos(j, Orbital.dyz)) dos[n] = k.__add__(cdos.get_site_orbital_dos(j, Orbital.dxz))
def from_file(feff_inp_file="feff.inp", ldos_file="ldos"): """ Creates LDos object from raw Feff ldos files by by assuming they are numbered consecutively, i.e. ldos01.dat ldos02.dat... Args: feff_inp_file (str): input file of run to obtain structure ldos_file (str): output ldos file of run to obtain dos info, etc. """ header_str = Header.header_string_from_file(feff_inp_file) header = Header.from_string(header_str) structure = header.struct nsites = structure.num_sites parameters = Tags.from_file(feff_inp_file) if "RECIPROCAL" in parameters: pot_dict = {} pot_readstart = re.compile(".*iz.*lmaxsc.*xnatph.*xion.*folp.*") pot_readend = re.compile(".*ExternalPot.*switch.*") pot_inp = re.sub(r"feff.inp", r"pot.inp", feff_inp_file) dos_index = 1 begin = 0 with zopen(pot_inp, "r") as potfile: for line in potfile: if len(pot_readend.findall(line)) > 0: break if begin == 1: begin += 1 continue if begin == 2: z_number = int(line.strip().split()[0]) ele_name = Element.from_Z(z_number).name if ele_name not in pot_dict: pot_dict[ele_name] = dos_index else: pot_dict[ele_name] = min(dos_index, pot_dict[ele_name]) dos_index += 1 if len(pot_readstart.findall(line)) > 0: begin = 1 else: pot_string = Potential.pot_string_from_file(feff_inp_file) dicts = Potential.pot_dict_from_string(pot_string) pot_dict = dicts[0] with zopen(ldos_file + "00.dat", "r") as fobject: f = fobject.readlines() efermi = float(f[0].split()[4]) dos_energies = [] ldos = {} for i in range(1, len(pot_dict) + 1): if len(str(i)) == 1: ldos[i] = np.loadtxt(f"{ldos_file}0{i}.dat") else: ldos[i] = np.loadtxt(f"{ldos_file}{i}.dat") for i in range(0, len(ldos[1])): dos_energies.append(ldos[1][i][0]) all_pdos = [] vorb = { "s": Orbital.s, "p": Orbital.py, "d": Orbital.dxy, "f": Orbital.f0 } forb = {"s": 0, "p": 1, "d": 2, "f": 3} dlength = len(ldos[1]) for i in range(nsites): pot_index = pot_dict[structure.species[i].symbol] all_pdos.append(defaultdict(dict)) for k, v in vorb.items(): density = [ ldos[pot_index][j][forb[k] + 1] for j in range(dlength) ] updos = density downdos = None if downdos: all_pdos[-1][v] = {Spin.up: updos, Spin.down: downdos} else: all_pdos[-1][v] = {Spin.up: updos} pdos = all_pdos vorb2 = {0: Orbital.s, 1: Orbital.py, 2: Orbital.dxy, 3: Orbital.f0} pdoss = { structure[i]: {v: pdos[i][v] for v in vorb2.values()} for i in range(len(pdos)) } forb = {"s": 0, "p": 1, "d": 2, "f": 3} tdos = [0] * dlength for i in range(nsites): pot_index = pot_dict[structure.species[i].symbol] for v in forb.values(): density = [ldos[pot_index][j][v + 1] for j in range(dlength)] for j in range(dlength): tdos[j] = tdos[j] + density[j] tdos = {Spin.up: tdos} dos = Dos(efermi, dos_energies, tdos) complete_dos = CompleteDos(structure, dos, pdoss) charge_transfer = LDos.charge_transfer_from_file( feff_inp_file, ldos_file) return LDos(complete_dos, charge_transfer)
def read_dos(bands_file, pdos_file=None, cell_file=None, bin_width=0.01, gaussian=None, padding=None, emin=None, emax=None, efermi_to_vbm=True, lm_orbitals=None, elements=None, atoms=None, total_only=False): """Convert DOS data from CASTEP .bands file to Pymatgen/Sumo format The data is binned into a regular series using np.histogram Args: bands_file (:obj:`str`): Path to CASTEP prefix.bands output file. The k-point positions, weights and eigenvalues are read from this file. pdos_bin (:obj:`str`): Path to CASTEP prefix.pdos_bin output file. The weights of projected density of states are read from this file. bin_width (:obj:`float`, optional): Spacing for DOS energy axis gaussian (:obj:`float` or None, optional): Width of Gaussian broadening function padding (:obj:`float`, optional): Energy range above and below occupied region. (This is not used if xmin and xmax are set.) emin (:obj:`float`, optional): Minimum energy value for output DOS) emax (:obj:`float`, optional): Maximum energy value for output DOS efermi_to_vbm (:obj:`bool`, optional): If a bandgap is detected, modify the stored Fermi energy so that it lies at the VBM. Returns: (:obj:`pymatgen.electronic_structure.dos.Dos`, dict) where the dict is either empty or contains a PDOS arranged:: {species: {orbital: Dos}} """ header = _read_bands_header_verbose(bands_file) logging.info("Reading band eigenvalues...") _, weights, eigenvalues = read_bands_eigenvalues(bands_file, header) calc_efermi = header['e_fermi'][0] * _ry_to_ev * 2 if efermi_to_vbm and not _is_metal(eigenvalues, calc_efermi): logging.info("Setting energy zero to VBM") efermi = _get_vbm(eigenvalues, calc_efermi) else: logging.info("Setting energy zero to Fermi energy") efermi = calc_efermi emin_data = min(eigenvalues[Spin.up].flatten()) emax_data = max(eigenvalues[Spin.up].flatten()) if Spin.down in eigenvalues: emin_data = min(emin_data, min(eigenvalues[Spin.down].flatten())) emax_data = max(emax_data, max(eigenvalues[Spin.down].flatten())) if padding is None and gaussian: padding = gaussian * 3 elif padding is None: padding = 0.5 if emin is None: emin = emin_data - padding if emax is None: emax = emax_data + padding # Shift sampling window to account for zeroing at VBM/EFermi emin += efermi emax += efermi bins = np.arange(emin, emax + bin_width, bin_width) energies = (bins[1:] + bins[:-1]) / 2 # Add rows to weights for each band so they are aligned with eigenval data weights = weights * np.ones([eigenvalues[Spin.up].shape[0], 1]) dos_data = { spin: np.histogram(eigenvalue_set, bins=bins, weights=weights)[0] for spin, eigenvalue_set in eigenvalues.items() } dos = Dos(efermi, energies, dos_data) if pdos_file is not None and not total_only: if cell_file is None: raise OSError(f'Cell file {cell_file} not found: this must be ' 'provided for PDOS.') pdos_raw = compute_pdos(pdos_file, eigenvalues, weights, bins) # Also we, need to read the structure, but have it sorted with increasing # atomic numbers structure = CastepCell.from_file( cell_file).structure.get_sorted_structure( key=lambda x: x.species.elements[0].Z) pdoss = {} for isite, site in enumerate(structure.sites): pdoss[site] = pdos_raw[isite] # Get the pdos dictionary for potting pdos = get_pdos(CompleteDos(structure, dos, pdoss), lm_orbitals=lm_orbitals, elements=elements, atoms=atoms) # Smear the PDOS for orbs in pdos.values(): for dtmp in orbs.values(): if gaussian: dtmp.densities = dtmp.get_smeared_densities(gaussian) else: pdos = {} if gaussian: dos.densities = dos.get_smeared_densities(gaussian) return dos, pdos
def from_dict(data): def _make_float_array(a): res = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] for i in range(3): for j in range(3): res[i][j] = float(a[i][j]) return res def _make_float_hall(a): return [i for i in a[:27]] return BoltztrapAnalyzer( float(data["gap"]), [float(d) for d in data["mu_steps"]], {int(d): [_make_float_array(v) for v in data["cond"][d]] for d in data["cond"]}, {int(d): [_make_float_array(v) for v in data["seebeck"][d]] for d in data["seebeck"]}, {int(d): [_make_float_array(v) for v in data["kappa"][d]] for d in data["kappa"]}, {int(d): [_make_float_hall(v) for v in data["hall"][d]] for d in data["hall"]}, {"p": [float(d) for d in data["doping"]["p"]], "n": [float(d) for d in data["doping"]["n"]]}, { "p": {int(d): [float(v) for v in data["mu_doping"]["p"][d]] for d in data["mu_doping"]["p"]}, "n": {int(d): [float(v) for v in data["mu_doping"]["n"][d]] for d in data["mu_doping"]["n"]}, }, { "p": { int(d): [_make_float_array(v) for v in data["seebeck_doping"]["p"][d]] for d in data["seebeck_doping"]["p"] }, "n": { int(d): [_make_float_array(v) for v in data["seebeck_doping"]["n"][d]] for d in data["seebeck_doping"]["n"] }, }, { "p": { int(d): [_make_float_array(v) for v in data["cond_doping"]["p"][d]] for d in data["cond_doping"]["p"] }, "n": { int(d): [_make_float_array(v) for v in data["cond_doping"]["n"][d]] for d in data["cond_doping"]["n"] }, }, { "p": { int(d): [_make_float_array(v) for v in data["kappa_doping"]["p"][d]] for d in data["kappa_doping"]["p"] }, "n": { int(d): [_make_float_array(v) for v in data["kappa_doping"]["n"][d]] for d in data["kappa_doping"]["n"] }, }, { "p": { int(d): [_make_float_hall(v) for v in data["hall_doping"]["p"][d]] for d in data["hall_doping"]["p"] }, "n": { int(d): [_make_float_hall(v) for v in data["hall_doping"]["n"][d]] for d in data["hall_doping"]["n"] }, }, Dos.from_dict(data["dos"]), data["carrier_conc"], data["dos_partial"], data["vol"], str(data["warning"]), )
def _make_boltztrap_analyzer_from_data( data_full, data_hall, data_dos, temperature_steps, mu_steps, efermi, gap, doping, data_doping_full, data_doping_hall, vol, warning=False): """ Make a BoltztrapAnalyzer object from raw data typically parse from files. """ cond = {t: [] for t in temperature_steps} seebeck = {t: [] for t in temperature_steps} kappa = {t: [] for t in temperature_steps} hall = {t: [] for t in temperature_steps} carrier_conc = {t: [] for t in temperature_steps} dos_full = {'energy': [], 'density': []} warning = warning new_doping = {'p': [], 'n': []} for d in doping: if d > 0: new_doping['p'].append(d) else: new_doping['n'].append(-d) mu_doping = {'p': {t: [] for t in temperature_steps}, 'n': {t: [] for t in temperature_steps}} seebeck_doping = {'p': {t: [] for t in temperature_steps}, 'n': {t: [] for t in temperature_steps}} cond_doping = {'p': {t: [] for t in temperature_steps}, 'n': {t: [] for t in temperature_steps}} kappa_doping = {'p': {t: [] for t in temperature_steps}, 'n': {t: [] for t in temperature_steps}} hall_doping = {'p': {t: [] for t in temperature_steps}, 'n': {t: [] for t in temperature_steps}} for d in data_full: carrier_conc[d[1]].append(d[2]) tens_cond = [[d[3], d[4], d[5]], [d[6], d[7], d[8]], [d[9], d[10], d[11]]] cond[d[1]].append(tens_cond) tens_seebeck = [[d[12], d[13], d[14]], [d[15], d[16], d[17]], [d[18], d[19], d[20]]] seebeck[d[1]].append(tens_seebeck) tens_kappa = [[d[21], d[22], d[23]], [d[24], d[25], d[26]], [d[27], d[28], d[29]]] kappa[d[1]].append(tens_kappa) for d in data_hall: hall_tens = d[3:] hall[d[1]].append(hall_tens) for d in data_doping_full: tens_cond = [[d[2], d[3], d[4]], [d[5], d[6], d[7]], [d[8], d[9], d[10]]] tens_seebeck = [[d[11], d[12], d[13]], [d[14], d[15], d[16]], [d[17], d[18], d[19]]] tens_kappa = [[d[20], d[21], d[22]], [d[23], d[24], d[25]], [d[26], d[27], d[28]]] if d[1] < 0: mu_doping['n'][d[0]].append(Energy(d[-1], "Ry").to("eV")) cond_doping['n'][d[0]].append(tens_cond) seebeck_doping['n'][d[0]].append(tens_seebeck) kappa_doping['n'][d[0]].append(tens_kappa) else: mu_doping['p'][d[0]].append(Energy(d[-1], "Ry").to("eV")) cond_doping['p'][d[0]].append(tens_cond) seebeck_doping['p'][d[0]].append(tens_seebeck) kappa_doping['p'][d[0]].append(tens_kappa) for i in range(len(data_doping_hall)): hall_tens = [data_hall[i][j] for j in range(3, len(data_hall[i]))] if data_doping_hall[i][1] < 0: hall_doping['n'][data_doping_hall[i][0]].append(hall_tens) else: hall_doping['p'][data_doping_hall[i][0]].append(hall_tens) for t in data_dos['total']: dos_full['energy'].append(t[0]) dos_full['density'].append(t[1]) dos = Dos(efermi, dos_full['energy'], {Spin.up: dos_full['density']}) dos_partial = data_dos['partial'] return BoltztrapAnalyzer( gap, mu_steps, cond, seebeck, kappa, hall, new_doping, mu_doping, seebeck_doping, cond_doping, kappa_doping, hall_doping, dos, dos_partial, carrier_conc, vol, warning)