def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure_line.json'), 'r') as bsh: si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh)) si_bs_line.structure = si_str with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'), 'r') as bsh: si_bs_uniform = BandStructure.from_dict(json.load(bsh)) si_bs_uniform.structure = si_str self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values()) self.df = pd.DataFrame({ 'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform] }) with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'), 'r') as bsh: vbr2_uniform = BandStructure.from_dict(json.load(bsh)) self.vbr2kpts = [ k.frac_coords for k in vbr2_uniform.labels_dict.values() ] self.vbr2kpts = [ [0.0, 0.0, 0.0], # \\Gamma [0.2, 0.0, 0.0], # between \\Gamma and M [0.5, 0.0, 0.0], # M [0.5, 0.0, 0.5] ] # L self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
def _get_interpolater(self, n_idx, t_idx): # interpolater expects energies in eV and structure in angstrom energies = {s: e * hartree_to_ev for s, e in self.energies.items()} structure = get_angstrom_structure(self.structure) bs = BandStructure( self.ir_kpoints, energies, structure.lattice, self.efermi * hartree_to_ev, structure=structure, ) nelect = sum([idx for idx in self.vb_idx.values()]) props = defaultdict(dict) for spin in self.spins: # easier to interpolate the log props[spin]["rates"] = np.log10( np.sum(self.scattering_rates[spin][:, n_idx, t_idx], axis=0)) return Interpolater( bs, nelect, interpolation_factor=self.interpolation_factor, soc=self.soc, other_properties=props, )
def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'),'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure.json'),'r') as bsh: si_bs = BandStructure.from_dict(json.load(bsh)) si_bs.structure = si_str self.df = pd.DataFrame({'bs': [si_bs]})
def extract_bs(mat): bs = None # Process the bandstructure for information if "bs" in mat["bandstructure"]: bs_dict = mat["bandstructure"]["bs"] # Add in structure if not already there if "structure" not in bs_dict: bs_dict["structure"] = mat["structure"] # Add in High Symm K Path if not already there if len(bs_dict.get("labels_dict", {})) == 0: labels = get(mat, "inputs.nscf_line.kpoints.labels", None) kpts = get(mat, "inputs.nscf_line.kpoints.kpoints", None) if labels and kpts: labels_dict = dict(zip(labels, kpts)) labels_dict.pop(None, None) else: struc = Structure.from_dict(mat["structure"]) labels_dict = HighSymmKpath(struc)._kpath["kpoints"] bs_dict["labels_dict"] = labels_dict bs = BandStructureSymmLine.from_dict( BandStructure.from_dict(bs_dict).as_dict()) return bs
def add_ebp(dir_entry): json_data = {} with open(dir_entry, 'r') as thefile: json_data = json.load(thefile) if 'ebp' in json_data: return bs = BandStructure.from_dict(json_data['bandstructure']) for i in range(bs.nb_bands): if min(bs.bands[1][i]) > bs.efermi: cbbottom = i vbtop = i-1 break vb_en = 0.0 cb_en = 0.0 for i in range(N_VB): vb_en += math.fsum(bs.bands[1][vbtop-i])/N_VB for i in range(N_CB): cb_en += math.fsum(bs.bands[1][cbbottom+i])/N_CB total_en = (vb_en + cb_en)/(2*len(bs.kpoints)) if not(bs.is_metal()): total_en -= (bs.get_vbm())['energy'] json_data['ebp'] = total_en else: print 'Warning, material is a metal! No VBM offset applied, no file written' if PRINT_DEBUG: print 'The branch point energy of ' + json_data['name'] + ' is ' + str(total_en) + ' eV' with open(dir_entry, 'w') as thefile: json.dump(json_data, thefile)
def from_dict(d): """ Construct VaspJob object from python dictionary. Returns ------- VaspJob object """ path = d['path'] inputs = VaspInput.from_dict(d['inputs']) job_settings = d['job_settings'] job_script_filename = d['job_script_filename'] name = d['name'] outputs = {} if d['outputs']: outputs[ 'ComputedStructureEntry'] = ComputedStructureEntry.from_dict( d['outputs']['ComputedStructureEntry']) vaspjob = VaspJob(path, inputs, job_settings, outputs, job_script_filename, name) vaspjob._band_structure = BandStructure.from_dict( d['band_structure']) if d['band_structure'] else None vaspjob._is_converged = d['is_converged'] if outputs: for k, v in vaspjob.computed_entry.data.items(): if k not in vaspjob._default_data_computed_entry: setattr(vaspjob, k, v) return vaspjob
def _log_band_structure_information(band_structure: BandStructure): log_banner("BAND STRUCTURE") info = [ f"# bands: {band_structure.nb_bands}", f"# k-points: {len(band_structure.kpoints)}", f"Fermi level: {band_structure.efermi:.3f} eV", f"spin polarized: {band_structure.is_spin_polarized}", f"metallic: {band_structure.is_metal()}", ] logger.info("Input band structure information:") log_list(info) if band_structure.is_metal(): return logger.info("Band gap:") band_gap_info = [] bg_data = band_structure.get_band_gap() if not bg_data["direct"]: band_gap_info.append("indirect band gap: {:.3f} eV".format( bg_data["energy"])) direct_data = band_structure.get_direct_band_gap_dict() direct_bg = min(spin_data["value"] for spin_data in direct_data.values()) band_gap_info.append(f"direct band gap: {direct_bg:.3f} eV") direct_kpoint = [] for spin, spin_data in direct_data.items(): direct_kindex = spin_data["kpoint_index"] kpt_str = _kpt_str.format( k=band_structure.kpoints[direct_kindex].frac_coords) direct_kpoint.append(kpt_str) band_gap_info.append("direct k-point: {}".format(", ".join(direct_kpoint))) log_list(band_gap_info) vbm_data = band_structure.get_vbm() cbm_data = band_structure.get_cbm() logger.info("Valence band maximum:") _log_band_edge_information(band_structure, vbm_data) logger.info("Conduction band minimum:") _log_band_edge_information(band_structure, cbm_data)
def get_BandStructure(self): eigenvalues = self.eigenvalues eigendict = {Spin.up: eigenvalues} return BandStructure(efermi=self.fermi_energy, eigenvals=eigendict, kpoints=self.k_points, structure=self.get_Structure(), lattice=self.get_reciprocal_Lattice())
def get_energy_cutoffs( energy_cutoff: float, band_structure: BandStructure ) -> Tuple[float, float]: if energy_cutoff and band_structure.is_metal(): min_e = band_structure.efermi - energy_cutoff max_e = band_structure.efermi + energy_cutoff elif energy_cutoff: min_e = band_structure.get_vbm()["energy"] - energy_cutoff max_e = band_structure.get_cbm()["energy"] + energy_cutoff else: min_e = min( [band_structure.bands[spin].min() for spin in band_structure.bands.keys()] ) max_e = max( [band_structure.bands[spin].max() for spin in band_structure.bands.keys()] ) return min_e, max_e
def get_band_structure(self, task_id, line_mode=False): m_task = self.collection.find_one({"task_id": task_id}, {"calcs_reversed": 1}) fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id'] fs = gridfs.GridFS(self.db, 'bandstructure_fs') bs_json = zlib.decompress(fs.get(fs_id).read()) bs_dict = json.loads(bs_json) if line_mode: return BandStructureSymmLine.from_dict(bs_dict) else: return BandStructure.from_dict(bs_dict)
def get_band_structure(self, task_id): m_task = self.collection.find_one({"task_id": task_id}, {"calcs_reversed": 1}) fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id'] fs = gridfs.GridFS(self.db, 'bandstructure_fs') bs_json = zlib.decompress(fs.get(fs_id).read()) bs_dict = json.loads(bs_json.decode()) if bs_dict["@class"] == "BandStructure": return BandStructure.from_dict(bs_dict) elif bs_dict["@class"] == "BandStructureSymmLine": return BandStructureSymmLine.from_dict(bs_dict) else: raise ValueError("Unknown class for band structure! {}".format(bs_dict["@class"]))
def add_material(dir_entry, data_list): with open(dir_entry, 'r') as thefile: json_data = json.load(thefile) if 'ebp' not in json_data: print 'Skipped ' + json_data['name'] + ', no ebp' return bs = BandStructure.from_dict(json_data['bandstructure']) bandinfo = bs.get_band_gap() bandgap = CORRECTION_SLOPE*bandinfo["energy"]+CORRECTION_OFFSET ebp = EBP_CORRECTION*json_data['ebp'] if PRINT_DEBUG: print json_data['name'] + ' has vbm ' + str(-ebp) + " eV and cbm " + str(bandgap-ebp) + ' eV' data_list.append({'name': json_data['name'], 'vbm': -ebp, 'cbm': bandgap-ebp})
def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'),'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure_line.json'),'r') as bsh: si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh)) si_bs_line.structure = si_str with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),'r') as bsh: si_bs_uniform = BandStructure.from_dict(json.load(bsh)) si_bs_uniform.structure = si_str self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values()) self.df = pd.DataFrame({'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform]}) with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'), 'r') as bsh: vbr2_uniform = BandStructure.from_dict(json.load(bsh)) self.vbr2kpts = [k.frac_coords for k in vbr2_uniform.labels_dict.values()] self.vbr2kpts = [[0.0, 0.0, 0.0], # \\Gamma [0.2, 0.0, 0.0], # between \\Gamma and M [0.5, 0.0, 0.0], # M [0.5, 0.0, 0.5]] # L self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
def featurize(self, bs): """ Args: bs (pymatgen BandStructure or BandStructureSymmLine or their dict): The band structure to featurize() Returns ([float]): a list of band structure features. If not bs.structure, the features that require the structure will be returned as NaN. List of currently supported features: band_gap (eV): the difference between the CBM and VBM energy is_gap_direct (0.0|1.0): whether the band gap is direct or not direct_gap (eV): the minimum direct distance of the last valence band and the first conduction band {n,p}_ex{#}_en (eV): for example p_ex2_en is the absolute value of the energy of the second valence (p) band extremum w.r.t. VBM {n,p}_ex{#}_norm (float): e.g. n_ex1_norm is norm of the fractional coordinates of k-points of the 1st conduction (n) band extremum, i.e., the CBM """ if isinstance(bs, dict): bs = BandStructure.from_dict(bs) if bs.is_metal(): raise ValueError("Cannot featurize a metallic band structure!") # preparation cbm = bs.get_cbm() vbm = bs.get_vbm() band_gap = bs.get_band_gap() vbm_bidx, vbm_bspin = self.get_bindex_bspin(vbm, is_cbm=False) cbm_bidx, cbm_bspin = self.get_bindex_bspin(cbm, is_cbm=True) vbm_ens = np.array(bs.bands[vbm_bspin][vbm_bidx]) cbm_ens = np.array(bs.bands[cbm_bspin][cbm_bidx]) # featurize self.feat = [] self.feat.append(('band_gap', band_gap['energy'])) self.feat.append(('is_gap_direct', band_gap['direct'])) self.feat.append(('direct_gap', min(cbm_ens - vbm_ens))) self.feat.append( ('p_ex1_norm', norm(bs.kpoints[vbm['kpoint_index'][0]].frac_coords))) self.feat.append( ('n_ex1_norm', norm(bs.kpoints[cbm['kpoint_index'][0]].frac_coords))) return list(x[1] for x in self.feat)
def setUp(self): self.bz = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/transp/")) self.bz_bands = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/bands/")) self.bz_up = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_up/"), dos_spin=1) self.bz_dw = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_dw/"), dos_spin=-1) self.bz_fermi = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/fermi/")) with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"), "rt") as f: d = json.load(f) self.bs = BandStructure.from_dict(d) self.btr = BoltztrapRunner(self.bs, 1)
def setUpClass(cls): cls.bz = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/transp/")) cls.bz_bands = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/bands/")) cls.bz_up = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_up/"), dos_spin=1) cls.bz_dw = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_dw/"), dos_spin=-1) cls.bz_fermi = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/fermi/")) with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"), "rt") as f: d = json.load(f) cls.bs = BandStructure.from_dict(d) cls.btr = BoltztrapRunner(cls.bs, 1) warnings.simplefilter("ignore")
def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure_line.json'), 'r') as bsh: si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh)) si_bs_line.structure = si_str with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'), 'r') as bsh: si_bs_uniform = BandStructure.from_dict(json.load(bsh)) si_bs_uniform.structure = si_str self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values()) self.df = pd.DataFrame({ 'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform] })
def add_material(dir_entry, data_list): with open(dir_entry, 'r') as thefile: json_data = json.load(thefile) if 'ebp' not in json_data: print 'Skipped ' + json_data['name'] + ', no ebp' return bs = BandStructure.from_dict(json_data['bandstructure']) bandinfo = bs.get_band_gap() bandgap = CORRECTION_SLOPE * bandinfo["energy"] + CORRECTION_OFFSET ebp = EBP_CORRECTION * json_data['ebp'] if PRINT_DEBUG: print json_data['name'] + ' has vbm ' + str( -ebp) + " eV and cbm " + str(bandgap - ebp) + ' eV' data_list.append({ 'name': json_data['name'], 'vbm': -ebp, 'cbm': bandgap - ebp })
def expand_bandstructure( bandstructure, symprec=defaults["symprec"], time_reversal=True ): kpoints = get_kpoints_from_bandstructure(bandstructure) full_kpoints, _, _, _, _, kp_mapping = expand_kpoints( bandstructure.structure, kpoints, symprec=symprec, time_reversal=time_reversal, return_mapping=True, ) return BandStructure( full_kpoints, {s: b[:, kp_mapping] for s, b in bandstructure.bands.items()}, bandstructure.structure.lattice.reciprocal_lattice, bandstructure.efermi, structure=bandstructure.structure, )
def get_band_structure(self, task_id): """ Read the BS data into a PMG BandStructure or BandStructureSymmLine object Args: task_id(int or str): the task_id containing the data Returns: BandStructure or BandStructureSymmLine """ obj_dict = self.get_data_from_maggma_or_gridfs(task_id, key="bandstructure") if obj_dict["@class"] == "BandStructure": return BandStructure.from_dict(obj_dict) elif obj_dict["@class"] == "BandStructureSymmLine": return BandStructureSymmLine.from_dict(obj_dict) else: raise ValueError("Unknown class for band structure! {}".format( obj_dict["@class"]))
def dos_from_boltztrap(bs_dict, energy_grid=0.005, avoid_projections=False): """ Function to just interpolate a DOS from a bandstructure using BoltzTrap Args: bs_dict(dict): A MSONable dictionary for a bandstructure object energy_grid(float): the energy_grid spacing for the DOS in eV avoid_projections(bool): don't interpolate projections even if present """ bs = BandStructure.from_dict(bs_dict) st = bs.structure energy_grid = energy_grid * units.eV projections = True if bs.projections and not avoid_projections else False if bs.is_spin_polarized: data_up = BandstructureLoader(bs, st, spin=1) data_dn = BandstructureLoader(bs, st, spin=-1) min_bnd = min(data_up.ebands.min(), data_dn.ebands.min()) max_bnd = max(data_up.ebands.max(), data_dn.ebands.max()) data_up.set_upper_lower_bands(min_bnd, max_bnd) data_dn.set_upper_lower_bands(min_bnd, max_bnd) bztI_up = BztInterpolator(data_up, energy_range=np.inf, curvature=False) bztI_dn = BztInterpolator(data_dn, energy_range=np.inf, curvature=False) npts_mu = int((max_bnd - min_bnd) / energy_grid) dos_up = bztI_up.get_dos(partial_dos=projections, npts_mu=npts_mu) dos_dn = bztI_dn.get_dos(partial_dos=projections, npts_mu=npts_mu) cdos = merge_up_down_doses(dos_up, dos_dn) else: data = BandstructureLoader(bs, st) min_bnd = min(data.ebands.min(), data.ebands.min()) max_bnd = max(data.ebands.max(), data.ebands.max()) npts_mu = int((max_bnd - min_bnd) / energy_grid) bztI = BztInterpolator(data, energy_range=np.inf, curvature=False) cdos = bztI.get_dos(partial_dos=projections, npts_mu=npts_mu) return cdos.as_dict()
def _get_interpolater(self, n_idx, t_idx, mode="linear"): props = defaultdict(dict) for spin in self.spins: # calculate total rate spin_rates = np.sum(self.scattering_rates[spin][:, n_idx, t_idx], axis=0) # easier to interpolate the log log_rates = np.log10(spin_rates) # # handle rates that close to numerical noise log_rates[log_rates > 18] = 15 log_rates[np.isnan(log_rates)] = 15 # map to full k-point mesh props[spin]["rates"] = log_rates if mode == "linear": return _LinearBandStructureInterpolator( self.kpoints, self.ir_to_full_kpoint_mapping, self.energies, self.structure, self.efermi, props, ) elif mode == "fourier": bs = BandStructure( self.ir_kpoints, self.energies, self.structure.lattice, self.efermi, structure=self.structure, ) return Interpolator( bs, self.num_electrons, interpolation_factor=self.interpolation_factor, soc=self.soc, other_properties=props, ) raise ValueError("Unknown interpolation mode; should be 'linear' or 'fourier'.")
def rotate_bandstructure(bandstructure: BandStructure, frac_symop: SymmOp): """Won't rotate projections...""" kpoints = get_kpoints_from_bandstructure(bandstructure) recip_rot = frac_symop.rotation_matrix.T rot_kpoints = np.dot(recip_rot, kpoints.T).T # map to first BZ, use VASP zone boundary convention rot_kpoints = kpoints_to_first_bz(rot_kpoints, negative_zone_boundary=False) # rotate structure structure = bandstructure.structure.copy() structure.apply_operation(frac_symop, fractional=True) return BandStructure( rot_kpoints, bandstructure.bands, structure.lattice.reciprocal_lattice, bandstructure.efermi, structure=structure, )
def get_vb_idx(energy_cutoff: float, band_structure: BandStructure): if band_structure.is_metal(): return None ibands = get_ibands(energy_cutoff, band_structure, return_idx=False) new_vb_idx = {} for spin, bands in band_structure.bands.items(): spin_ibands = ibands[spin] # valence bands are all bands that contain energies less than efermi vbs = (bands < band_structure.efermi).any(axis=1) vb_idx = np.where(vbs)[0].max() # need to know the index of the valence band after discounting # bands during the interpolation. As ibands is just a list of # True/False, we can count the number of Trues included up to # and including the VBM to get the new number of valence bands new_vb_idx[spin] = sum(spin_ibands[: vb_idx + 1]) - 1 return new_vb_idx
def get_interpolated_dos(self, mat): nelect = mat["calc_settings"]["nelect"] bs_dict = mat["bandstructure"]["uniform_bs"] bs_dict["structure"] = mat['structure'] bs = BandStructure.from_dict(bs_dict) if bs.is_spin_polarized: with ScratchDir("."): BoltztrapRunner(bs=bs, nelec=nelect, run_type="DOS", dos_type="TETRA", spin=1, timeout=60).run(path_dir=os.getcwd()) an_up = BoltztrapAnalyzer.from_files("boltztrap/", dos_spin=1) with ScratchDir("."): BoltztrapRunner(bs=bs, nelec=nelect, run_type="DOS", dos_type="TETRA", spin=-1, timeout=60).run(path_dir=os.getcwd()) an_dw = BoltztrapAnalyzer.from_files("boltztrap/", dos_spin=-1) cdos = an_up.get_complete_dos(bs.structure, an_dw) else: with ScratchDir("."): BoltztrapRunner(bs=bs, nelec=nelect, run_type="DOS", dos_type="TETRA", timeout=60).run(path_dir=os.getcwd()) an = BoltztrapAnalyzer.from_files("boltztrap/") cdos = an.get_complete_dos(bs.structure) return cdos
def build_bs(bs_dict, mat): bs_dict["structure"] = mat["structure"] # Add in High Symm K Path if not already there if len(bs_dict.get("labels_dict", {})) == 0: labels = get(mat, "inputs.nscf_line.kpoints.labels", None) kpts = get(mat, "inputs.nscf_line.kpoints.kpoints", None) if labels and kpts: labels_dict = dict(zip(labels, kpts)) labels_dict.pop(None, None) else: struc = Structure.from_dict(mat["structure"]) labels_dict = HighSymmKpath(struc)._kpath["kpoints"] bs_dict["labels_dict"] = labels_dict # This is somethign to do with BandStructureSymmLine's from dict being problematic bs = BandStructureSymmLine.from_dict( BandStructure.from_dict(bs_dict).as_dict()) return bs
def _log_band_structure_information(band_structure: BandStructure): log_banner("BAND STRUCTURE") logger.info("Input band structure information:") log_list([ "# bands: {}".format(band_structure.nb_bands), "# k-points: {}".format(len(band_structure.kpoints)), "Fermi level: {:.3f} eV".format(band_structure.efermi), "spin polarized: {}".format(band_structure.is_spin_polarized), "metallic: {}".format(band_structure.is_metal()) ]) if band_structure.is_metal(): return logger.info("Band gap:") band_gap_info = [] bg_data = band_structure.get_band_gap() if not bg_data['direct']: band_gap_info.append('indirect band gap: {:.3f} eV'.format( bg_data['energy'])) direct_data = band_structure.get_direct_band_gap_dict() direct_bg = min((spin_data['value'] for spin_data in direct_data.values())) band_gap_info.append('direct band gap: {:.3f} eV'.format(direct_bg)) direct_kpoint = [] for spin, spin_data in direct_data.items(): direct_kindex = spin_data['kpoint_index'] direct_kpoint.append( _kpt_str.format( k=band_structure.kpoints[direct_kindex].frac_coords)) band_gap_info.append("direct k-point: {}".format(", ".join(direct_kpoint))) log_list(band_gap_info) vbm_data = band_structure.get_vbm() cbm_data = band_structure.get_cbm() logger.info('Valence band maximum:') _log_band_edge_information(band_structure, vbm_data) logger.info('Conduction band minimum:') _log_band_edge_information(band_structure, cbm_data)
#N_CB = 2 #N_VB = 4 #filename = 'AlN_structure.json' #N_CB = 1 #N_VB = 2 #filename = 'zb-GaN_structure.json' N_CB = 1 N_VB = 2 filename = 'CdO_structure.json' with open(filename, 'r') as thefile: json_data = json.load(thefile) bs = BandStructure.from_dict(json_data['bandstructure']) for i in range(bs.nb_bands): if min(bs.bands[1][i]) > bs.efermi: cbbottom = i vbtop = i-1 break vb_en = 0.0 cb_en = 0.0 for i in range(N_VB): vb_en += math.fsum(bs.bands[1][vbtop-i])/N_VB for i in range(N_CB): cb_en += math.fsum(bs.bands[1][cbbottom+i])/N_CB total_en = (vb_en + cb_en)/(2*len(bs.kpoints)) if not(bs.is_metal()):
def run_task(self, fw_spec): # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) m_task = tdb.tasks.find_one({"dir_name": block_part}, {"calculations": 1, "task_id": 1}) nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output']['crystal'] bs = BandStructure.from_dict(bs_dict) print 'Band Structure found:', bool(bs) print nelect # run Boltztrap runner = BoltztrapRunner(bs, nelect) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) data = bta.to_dict data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] data['hall'] = {} # remove because it is too large and not useful data['hall_doping'] = {} # remove because it is too large and not useful tdb.boltztrap.insert(clean_json(data)) update_spec = {'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'], 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} return FWAction(update_spec=update_spec)
def run_task(self, fw_spec): # import here to prevent import errors in bigger MPCollab # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ filename = get_slug( 'JOB--' + fw_spec['mpsnl'].structure.composition.reduced_formula + '--' + fw_spec['task_type']) with open(filename, 'w+') as f: f.write('') # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) props = {"calculations": 1, "task_id": 1, "state": 1, "pseudo_potential": 1, "run_type": 1, "is_hubbard": 1, "hubbards": 1, "unit_cell_formula": 1} m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: time.sleep(60) # only thing to think of is wait for DB insertion(?) m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: raise ValueError("Could not find task with dir_name: {}".format(block_part)) if m_task['state'] != 'successful': raise ValueError("Cannot run Boltztrap; parent job unsuccessful") nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output']['crystal'] bs = BandStructure.from_dict(bs_dict) print 'Band Structure found:', bool(bs) print nelect # run Boltztrap runner = BoltztrapRunner(bs, nelect) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) # 8/21/15 - Anubhav removed fs_id (also see line further below, ted['boltztrap_full_fs_id'] ...) # 8/21/15 - this is to save space in MongoDB, as well as non-use of full Boltztrap output (vs rerun) """ data = bta.as_dict() data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] del data['hall'] # remove because it is too large and not useful fs = gridfs.GridFS(tdb, "boltztrap_full_fs") btid = fs.put(json.dumps(jsanitize(data))) """ # now for the "sanitized" data ted = bta.as_dict() del ted['seebeck'] del ted['hall'] del ted['kappa'] del ted['cond'] # ted['boltztrap_full_fs_id'] = btid ted['snlgroup_id'] = fw_spec['snlgroup_id'] ted['run_tags'] = fw_spec['run_tags'] ted['snl'] = fw_spec['mpsnl'].as_dict() ted['dir_name_full'] = dir ted['dir_name'] = get_block_part(dir) ted['task_id'] = m_task['task_id'] ted['pf_doping'] = bta.get_power_factor(output='tensor', relaxation_time=self.TAU) ted['zt_doping'] = bta.get_zt(output='tensor', relaxation_time=self.TAU, kl=self.KAPPAL) ted['pf_eigs'] = self.get_eigs(ted, 'pf_doping') ted['pf_best'] = self.get_extreme(ted, 'pf_eigs') ted['pf_best_dope18'] = self.get_extreme(ted, 'pf_eigs', max_didx=3) ted['pf_best_dope19'] = self.get_extreme(ted, 'pf_eigs', max_didx=4) ted['zt_eigs'] = self.get_eigs(ted, 'zt_doping') ted['zt_best'] = self.get_extreme(ted, 'zt_eigs') ted['zt_best_dope18'] = self.get_extreme(ted, 'zt_eigs', max_didx=3) ted['zt_best_dope19'] = self.get_extreme(ted, 'zt_eigs', max_didx=4) ted['seebeck_eigs'] = self.get_eigs(ted, 'seebeck_doping') ted['seebeck_best'] = self.get_extreme(ted, 'seebeck_eigs') ted['seebeck_best_dope18'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=3) ted['seebeck_best_dope19'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=4) ted['cond_eigs'] = self.get_eigs(ted, 'cond_doping') ted['cond_best'] = self.get_extreme(ted, 'cond_eigs') ted['cond_best_dope18'] = self.get_extreme(ted, 'cond_eigs', max_didx=3) ted['cond_best_dope19'] = self.get_extreme(ted, 'cond_eigs', max_didx=4) ted['kappa_eigs'] = self.get_eigs(ted, 'kappa_doping') ted['kappa_best'] = self.get_extreme(ted, 'kappa_eigs', maximize=False) ted['kappa_best_dope18'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=3) ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxpf_n = bzspb.get_maximum_power_factor('n', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_n = bzspb.get_maximum_power_factor('n', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) ted['zt_best_finemesh'] = {'p': maxzt_p, 'n': maxzt_n} ted['pf_best_finemesh'] = {'p': maxpf_p, 'n': maxpf_n} except: import traceback traceback.print_exc() print 'COULD NOT GET FINE MESH DATA' # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = m_task["pseudo_potential"]["functional"] labels = m_task["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = {"run_type": m_task["run_type"], "is_hubbard": m_task["is_hubbard"], "hubbards": m_task["hubbards"], "potcar_symbols": symbols} entry = ComputedEntry(Composition(m_task["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=m_task["task_id"]) ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility, task_id: {}'.format(m_task["task_id"]) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) update_spec = {'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'].as_dict(), 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} return FWAction(update_spec=update_spec)
def featurize(self, bs): """ Args: bs (pymatgen BandStructure or BandStructureSymmLine or their dict): The band structure to featurize. To obtain all features, bs should include the structure attribute. Returns: ([float]): a list of band structure features. If not bs.structure, features that require the structure will be returned as NaN. List of currently supported features: band_gap (eV): the difference between the CBM and VBM energy is_gap_direct (0.0|1.0): whether the band gap is direct or not direct_gap (eV): the minimum direct distance of the last valence band and the first conduction band p_ex1_norm (float): k-space distance between Gamma point and k-point of VBM n_ex1_norm (float): k-space distance between Gamma point and k-point of CBM p_ex1_degen: degeneracy of VBM n_ex1_degen: degeneracy of CBM if kpoints is provided (e.g. for kpoints == [[0.0, 0.0, 0.0]]): n_0.0;0.0;0.0_en: (energy of the first conduction band at [0.0, 0.0, 0.0] - CBM energy) p_0.0;0.0;0.0_en: (energy of the last valence band at [0.0, 0.0, 0.0] - VBM energy) """ if isinstance(bs, dict): bs = BandStructure.from_dict(bs) if bs.is_metal(): raise ValueError("Cannot featurize a metallic band structure!") bs_kpts = [k.frac_coords for k in bs.kpoints] cvd = {'p': bs.get_vbm(), 'n': bs.get_cbm()} for itp, tp in enumerate(['p', 'n']): cvd[tp]['k'] = bs.kpoints[cvd[tp]['kpoint_index'][0]].frac_coords cvd[tp]['bidx'], cvd[tp]['sidx'] = \ self.get_bindex_bspin(cvd[tp], is_cbm=bool(itp)) cvd[tp]['Es'] = np.array(bs.bands[cvd[tp]['sidx']][cvd[tp]['bidx']]) band_gap = bs.get_band_gap() # featurize feat = OrderedDict() feat['band_gap'] = band_gap['energy'] feat['is_gap_direct'] = band_gap['direct'] feat['direct_gap'] = min(cvd['n']['Es'] - cvd['p']['Es']) for tp in ['p', 'n']: feat['{}_ex1_norm'.format(tp)] = norm(cvd[tp]['k']) if bs.structure: feat['{}_ex1_degen'.format(tp)] = bs.get_kpoint_degeneracy(cvd[tp]['k']) else: feat['{}_ex1_degen'.format(tp)] = float('NaN') if self.kpoints: obands = {'n': [], 'p': []} for spin in bs.bands: for band_idx in range(bs.nb_bands): if max(bs.bands[spin][band_idx]) < bs.efermi: obands['p'].append(bs.bands[spin][band_idx]) if min(bs.bands[spin][band_idx]) > bs.efermi: obands['n'].append(bs.bands[spin][band_idx]) bands = {tp: np.zeros((len(obands[tp]), len(self.kpoints))) for tp in ['p', 'n']} for tp in ['p', 'n']: for ib, ob in enumerate(obands[tp]): bands[tp][ib, :] = griddata(points=np.array(bs_kpts), values=np.array(ob) - cvd[tp]['energy'], xi=self.kpoints, method=self.find_method) for ik, k in enumerate(self.kpoints): sorted_band = np.sort(bands[tp][:, ik]) if tp == 'p': sorted_band = sorted_band[::-1] for ib in range(self.nbands): k_name = '{}_{};{};{}_en{}'.format(tp, k[0], k[1], k[2], ib+1) try: feat[k_name] = sorted_band[ib] except IndexError: feat[k_name] = float('NaN') return list(feat.values())
def process_item(self, mat): """ Process the tasks and materials into just a list of materials Args: mat (dict): material document Returns: (dict): electronic_structure document """ self.logger.info("Processing: {}".format(mat[self.materials.key])) d = {self.electronic_structure.key: mat[ self.materials.key], "bandstructure": {}} bs = None dos = None interpolated_dos = None # Process the bandstructure for information if "bs" in mat["bandstructure"]: if "structure" not in mat["bandstructure"]["bs"]: mat["bandstructure"]["bs"]["structure"] = mat["structure"] if len(mat["bandstructure"]["bs"].get("labels_dict", {})) == 0: struc = Structure.from_dict(mat["structure"]) kpath = HighSymmKpath(struc)._kpath["kpoints"] mat["bandstructure"]["bs"]["labels_dict"] = kpath # Somethign is wrong with the as_dict / from_dict encoding in the two band structure objects so have to use this hodge podge serialization # TODO: Fix bandstructure objects in pymatgen bs = BandStructureSymmLine.from_dict( BandStructure.from_dict(mat["bandstructure"]["bs"]).as_dict()) d["bandstructure"]["band_gap"] = {"band_gap": bs.get_band_gap()["energy"], "direct_gap": bs.get_direct_band_gap(), "is_direct": bs.get_band_gap()["direct"], "transition": bs.get_band_gap()["transition"]} if self.small_plot: d["bandstructure"]["plot_small"] = get_small_plot(bs) if "dos" in mat["bandstructure"]: dos = CompleteDos.from_dict(mat["bandstructure"]["dos"]) if self.interpolate_dos and "uniform_bs" in mat["bandstructure"]: try: interpolated_dos = self.get_interpolated_dos(mat) except Exception: self.logger.warning("Boltztrap interpolation failed for {}. Continuing with regular DOS".format(mat[self.materials.key])) # Generate static images if self.static_images: try: ylim = None if bs: plotter = WebBSPlotter(bs) fig = plotter.get_plot() ylim = fig.ylim() # Used by DOS plot fig.close() d["bandstructure"]["bs_plot"] = image_from_plotter(plotter) if dos: plotter = WebDosVertPlotter() plotter.add_dos_dict(dos.get_element_dos()) if interpolated_dos: plotter.add_dos("Total DOS", interpolated_dos) d["bandstructure"]["dos_plot"] = image_from_plotter(plotter, ylim=ylim) d["bandstructure"]["dos_plot"] = image_from_plotter(plotter, ylim=ylim) except Exception: self.logger.warning( "Caught error in electronic structure plotting for {}: {}".format(mat[self.materials.key], traceback.format_exc())) return None return d
#N_CB = 2 #N_VB = 4 #filename = 'AlN_structure.json' #N_CB = 1 #N_VB = 2 #filename = 'zb-GaN_structure.json' N_CB = 1 N_VB = 2 filename = 'CdO_structure.json' with open(filename, 'r') as thefile: json_data = json.load(thefile) bs = BandStructure.from_dict(json_data['bandstructure']) for i in range(bs.nb_bands): if min(bs.bands[1][i]) > bs.efermi: cbbottom = i vbtop = i - 1 break vb_en = 0.0 cb_en = 0.0 for i in range(N_VB): vb_en += math.fsum(bs.bands[1][vbtop - i]) / N_VB for i in range(N_CB): cb_en += math.fsum(bs.bands[1][cbbottom + i]) / N_CB total_en = (vb_en + cb_en) / (2 * len(bs.kpoints)) if not (bs.is_metal()):
def run_task(self, fw_spec): # import here to prevent import errors in bigger MPCollab # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ filename = get_slug( 'JOB--' + fw_spec['mpsnl'].structure.composition.reduced_formula + '--' + fw_spec['task_type']) with open(filename, 'w+') as f: f.write('') # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) props = { "calculations": 1, "task_id": 1, "state": 1, "pseudo_potential": 1, "run_type": 1, "is_hubbard": 1, "hubbards": 1, "unit_cell_formula": 1 } m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: time.sleep( 60) # only thing to think of is wait for DB insertion(?) m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: raise ValueError( "Could not find task with dir_name: {}".format(block_part)) if m_task['state'] != 'successful': raise ValueError( "Cannot run Boltztrap; parent job unsuccessful") nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output'][ 'crystal'] bs = BandStructure.from_dict(bs_dict) print("find previous run with block_part {}".format(block_part)) print 'Band Structure found:', bool(bs) print(bs.as_dict()) print("nelect: {}".format(nelect)) # run Boltztrap doping = [] for d in [1e16, 1e17, 1e18, 1e19, 1e20]: doping.extend([1 * d, 2.5 * d, 5 * d, 7.5 * d]) doping.append(1e21) runner = BoltztrapRunner(bs, nelect, doping=doping) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) # 8/21/15 - Anubhav removed fs_id (also see line further below, ted['boltztrap_full_fs_id'] ...) # 8/21/15 - this is to save space in MongoDB, as well as non-use of full Boltztrap output (vs rerun) """ data = bta.as_dict() data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] del data['hall'] # remove because it is too large and not useful fs = gridfs.GridFS(tdb, "boltztrap_full_fs") btid = fs.put(json.dumps(jsanitize(data))) """ # now for the "sanitized" data ted = bta.as_dict() del ted['seebeck'] del ted['hall'] del ted['kappa'] del ted['cond'] # ted['boltztrap_full_fs_id'] = btid ted['snlgroup_id'] = fw_spec['snlgroup_id'] ted['run_tags'] = fw_spec['run_tags'] ted['snl'] = fw_spec['mpsnl'].as_dict() ted['dir_name_full'] = dir ted['dir_name'] = get_block_part(dir) ted['task_id'] = m_task['task_id'] ted['pf_doping'] = bta.get_power_factor(output='tensor', relaxation_time=self.TAU) ted['zt_doping'] = bta.get_zt(output='tensor', relaxation_time=self.TAU, kl=self.KAPPAL) ted['pf_eigs'] = self.get_eigs(ted, 'pf_doping') ted['pf_best'] = self.get_extreme(ted, 'pf_eigs') ted['pf_best_dope18'] = self.get_extreme(ted, 'pf_eigs', max_didx=3) ted['pf_best_dope19'] = self.get_extreme(ted, 'pf_eigs', max_didx=4) ted['zt_eigs'] = self.get_eigs(ted, 'zt_doping') ted['zt_best'] = self.get_extreme(ted, 'zt_eigs') ted['zt_best_dope18'] = self.get_extreme(ted, 'zt_eigs', max_didx=3) ted['zt_best_dope19'] = self.get_extreme(ted, 'zt_eigs', max_didx=4) ted['seebeck_eigs'] = self.get_eigs(ted, 'seebeck_doping') ted['seebeck_best'] = self.get_extreme(ted, 'seebeck_eigs') ted['seebeck_best_dope18'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=3) ted['seebeck_best_dope19'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=4) ted['cond_eigs'] = self.get_eigs(ted, 'cond_doping') ted['cond_best'] = self.get_extreme(ted, 'cond_eigs') ted['cond_best_dope18'] = self.get_extreme(ted, 'cond_eigs', max_didx=3) ted['cond_best_dope19'] = self.get_extreme(ted, 'cond_eigs', max_didx=4) ted['kappa_eigs'] = self.get_eigs(ted, 'kappa_doping') ted['kappa_best'] = self.get_extreme(ted, 'kappa_eigs', maximize=False) ted['kappa_best_dope18'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=3) ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor( 'p', temperature=0, tau=1E-14, ZT=False, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxpf_n = bzspb.get_maximum_power_factor( 'n', temperature=0, tau=1E-14, ZT=False, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_p = bzspb.get_maximum_power_factor( 'p', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_n = bzspb.get_maximum_power_factor( 'n', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) ted['zt_best_finemesh'] = {'p': maxzt_p, 'n': maxzt_n} ted['pf_best_finemesh'] = {'p': maxpf_p, 'n': maxpf_n} except: import traceback traceback.print_exc() print 'COULD NOT GET FINE MESH DATA' # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = m_task["pseudo_potential"]["functional"] labels = m_task["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = { "run_type": m_task["run_type"], "is_hubbard": m_task["is_hubbard"], "hubbards": m_task["hubbards"], "potcar_symbols": symbols } entry = ComputedEntry(Composition(m_task["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=m_task["task_id"]) ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility, task_id: {}'.format( m_task["task_id"]) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) update_spec = { 'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'].as_dict(), 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters') } return FWAction(update_spec=update_spec)
def get_reconstructed_band_structure(list_bs, efermi=None): """Combine a list of band structures into a single band structure. This is typically very useful when you split non self consistent band structure runs in several independent jobs and want to merge back the results. This method will also ensure that any BandStructure objects will contain branches. Args: list_bs (:obj:`list` of \ :obj:`~pymatgen.electronic_structure.bandstructure.BandStructure` \ or :obj:`~pymatgen.electronic_structure.bandstructure.BandStructureSymmLine`): The band structures. efermi (:obj:`float`, optional): The Fermi energy of the reconstructed band structure. If `None`, an average of all the Fermi energies across all band structures is used. Returns: :obj:`pymatgen.electronic_structure.bandstructure.BandStructure` or \ :obj:`pymatgen.electronic_structure.bandstructureBandStructureSymmLine`: A band structure object. The type depends on the type of the band structures in ``list_bs``. """ if efermi is None: efermi = sum([b.efermi for b in list_bs]) / len(list_bs) kpoints = [] labels_dict = {} rec_lattice = list_bs[0].lattice_rec nb_bands = min([list_bs[i].nb_bands for i in range(len(list_bs))]) kpoints = np.concatenate([[k.frac_coords for k in bs.kpoints] for bs in list_bs]) dicts = [bs.labels_dict for bs in list_bs] labels_dict = {k: v.frac_coords for d in dicts for k, v in d.items()} # pymatgen band structure objects support branches. These are formed when # two kpoints with the same label are next to each other. This bit of code # will ensure that the band structure will contain branches, if it doesn't # already. dup_ids = [] for i, k in enumerate(kpoints): dup_ids.append(i) if (tuple(k) in tuple(map(tuple, labels_dict.values())) and i != 0 and i != len(kpoints) - 1 and (not np.array_equal(kpoints[i + 1], k) or not np.array_equal(kpoints[i - 1], k))): dup_ids.append(i) kpoints = kpoints[dup_ids] eigenvals = {} eigenvals[Spin.up] = np.concatenate( [bs.bands[Spin.up][:nb_bands] for bs in list_bs], axis=1) eigenvals[Spin.up] = eigenvals[Spin.up][:, dup_ids] if list_bs[0].is_spin_polarized: eigenvals[Spin.down] = np.concatenate( [bs.bands[Spin.down][:nb_bands] for bs in list_bs], axis=1) eigenvals[Spin.down] = eigenvals[Spin.up][:, dup_ids] projections = {} if len(list_bs[0].projections) != 0: projs = [bs.projections[Spin.up][:nb_bands][dup_ids] for bs in list_bs] projections[Spin.up] = np.concatenate(projs, axis=1)[:, dup_ids] if list_bs[0].is_spin_polarized: projs = [ bs.projections[Spin.down][:nb_bands][dup_ids] for bs in list_bs ] projections[Spin.down] = np.concatenate(projs, axis=1)[:, dup_ids] if isinstance(list_bs[0], BandStructureSymmLine): return BandStructureSymmLine(kpoints, eigenvals, rec_lattice, efermi, labels_dict, structure=list_bs[0].structure, projections=projections) else: return BandStructure(kpoints, eigenvals, rec_lattice, efermi, labels_dict, structure=list_bs[0].structure, projections=projections)
def get_band_structure( vasprun: Vasprun, zero_weighted: str = defaults["zero_weighted_kpoints"] ) -> BandStructure: """ Get a band structure from a Vasprun object. This can ensure that if the calculation contains zero-weighted k-points then the weighted k-points will be discarded (helps with hybrid calculations). Also ensures that the Fermi level is set correctly. Args: vasprun: A vasprun object. zero_weighted: How to handle zero-weighted k-points if they are present in the calculation. Options are: - "keep": Keep zero-weighted k-points in the band structure. - "drop": Drop zero-weighted k-points, keeping only the weighted k-points. - "prefer": Drop weighted-kpoints if zero-weighted k-points are present in the calculation (useful for cheap hybrid calculations). Returns: A band structure. """ # first check if Fermi level crosses a band k_idx = get_zero_weighted_kpoint_indices(vasprun, mode=zero_weighted) kpoints = np.array(vasprun.actual_kpoints)[k_idx] projections = {} eigenvalues = {} for spin, spin_eigenvalues in vasprun.eigenvalues.items(): # discard weight and set shape nbands, nkpoints eigenvalues[spin] = spin_eigenvalues[k_idx, :, 0].transpose(1, 0) if vasprun.projected_eigenvalues: # is nkpoints, nbands, nion, norb; we need nbands, nkpoints, norb, nion spin_projections = vasprun.projected_eigenvalues[spin] projections[spin] = spin_projections[k_idx].transpose(1, 0, 3, 2) # finding the Fermi level is quite painful, as VASP can sometimes put it slightly # inside a band fermi_crosses_band = False for spin_eigenvalues in eigenvalues.values(): eigs_below = np.any(spin_eigenvalues < vasprun.efermi, axis=1) eigs_above = np.any(spin_eigenvalues > vasprun.efermi, axis=1) if np.any(eigs_above & eigs_below): fermi_crosses_band = True # if the Fermi level crosses a band, the eigenvalue band properties is a more # reliable way to check whether this is a real effect bandgap, cbm, vbm, _ = vasprun.eigenvalue_band_properties if not fermi_crosses_band: # safe to use VASP fermi level efermi = vasprun.efermi elif fermi_crosses_band and bandgap == 0: # it is actually a metal efermi = vasprun.efermi else: # Set Fermi level half way between valence and conduction bands efermi = (cbm + vbm) / 2 return BandStructure( kpoints, eigenvalues, vasprun.final_structure.lattice.reciprocal_lattice, efermi, structure=vasprun.final_structure, projections=projections, )