Esempio n. 1
0
    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]})
Esempio n. 2
0
    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,
        )
Esempio n. 3
0
 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]})
Esempio n. 4
0
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)
Esempio n. 6
0
    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
Esempio n. 7
0
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)
Esempio n. 8
0
 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())
Esempio n. 9
0
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
Esempio n. 10
0
 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)
Esempio n. 11
0
 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)
Esempio n. 12
0
 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"]))
Esempio n. 13
0
 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})
Esempio n. 15
0
    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]})
Esempio n. 16
0
    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)
Esempio n. 17
0
    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)
Esempio n. 18
0
    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")
Esempio n. 19
0
    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]
        })
Esempio n. 20
0
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
        })
Esempio n. 21
0
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,
    )
Esempio n. 22
0
    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"]))
Esempio n. 23
0
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()
Esempio n. 24
0
    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'.")
Esempio n. 25
0
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,
    )
Esempio n. 26
0
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
Esempio n. 27
0
    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
Esempio n. 28
0
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
Esempio n. 29
0
File: run.py Progetto: gmp007/amset
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()):
Esempio n. 31
0
    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)
Esempio n. 32
0
    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)
Esempio n. 33
0
    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())
Esempio n. 34
0
    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()):
Esempio n. 36
0
    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)
Esempio n. 37
0
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)
Esempio n. 38
0
    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())
Esempio n. 39
0
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,
    )