def run_task(self, fw_spec): additional_fields = self.get("additional_fields", {}) # pass the additional_fields first to avoid overriding BoltztrapAnalyzer items d = additional_fields.copy() btrap_dir = os.path.join(os.getcwd(), "boltztrap") d["boltztrap_dir"] = btrap_dir bta = BoltztrapAnalyzer.from_files(btrap_dir) d.update(bta.as_dict()) d["scissor"] = bta.intrans["scissor"] # trim the output for x in ['cond', 'seebeck', 'kappa', 'hall', 'mu_steps', 'mu_doping', 'carrier_conc']: del d[x] if not self.get("hall_doping"): del d["hall_doping"] bandstructure_dir = os.getcwd() d["bandstructure_dir"] = bandstructure_dir # add the structure v, o = get_vasprun_outcar(bandstructure_dir, parse_eigen=False, parse_dos=False) structure = v.final_structure d["structure"] = structure.as_dict() d["formula_pretty"] = structure.composition.reduced_formula d.update(get_meta_from_structure(structure)) # add the spacegroup sg = SpacegroupAnalyzer(Structure.from_dict(d["structure"]), 0.1) d["spacegroup"] = {"symbol": sg.get_space_group_symbol(), "number": sg.get_space_group_number(), "point_group": sg.get_point_group_symbol(), "source": "spglib", "crystal_system": sg.get_crystal_system(), "hall": sg.get_hall()} d["created_at"] = datetime.utcnow() db_file = env_chk(self.get('db_file'), fw_spec) if not db_file: del d["dos"] with open(os.path.join(btrap_dir, "boltztrap.json"), "w") as f: f.write(json.dumps(d, default=DATETIME_HANDLER)) else: mmdb = VaspCalcDb.from_db_file(db_file, admin=True) # dos gets inserted into GridFS dos = json.dumps(d["dos"], cls=MontyEncoder) fsid, compression = mmdb.insert_gridfs(dos, collection="dos_boltztrap_fs", compress=True) d["dos_boltztrap_fs_id"] = fsid del d["dos"] mmdb.db.boltztrap.insert(d)
def _load_structure_from_dir(directory): """ Find the final geometry from a directory which contains the output of a VASP run, preferably performed within a fireworks workflow. For simple Structure objects, the full geometry can be derived from the VASP outputs. However, more complex subclasses such as Cathode and QSlab require information about the original instance. This can be retrieved from the FW.json file, if present. Args: directory: Directory of the completed VASP run. Returns: Structure: The output geometry of the calculation. Either a Structure or subclass of a Structure. """ if os.path.exists(os.path.join(directory, "FW.json")): fw = Firework.from_file(os.path.join(directory, "FW.json")) structure = _find_fw_structure(fw) if structure.__class__ == Structure: vasprun, outcar = get_vasprun_outcar(directory) return get_structure_from_prev_run(vasprun, outcar) elif issubclass(structure.__class__, QSlab): structure.update_sites(directory) return structure elif issubclass(structure.__class__, Cathode): structure.update_sites(directory) return structure else: raise ValueError else: warnings.warn("No FW.json file in the specified directory. Output geometry " "will be returned as a Structure instance, even though the " "input geometry may have been derived from a more complex " "subclass.") vasprun, outcar = get_vasprun_outcar(directory) return get_structure_from_prev_run(vasprun, outcar)
def from_prev_calc(cls, prev_calc_dir, standardize=False, sym_prec=0.1, international_monoclinic=True, grid_density=8000, small_gap_multiply=None, **kwargs): """ Generate a set of Vasp input files for static calculations from a directory of previous Vasp run. Args: prev_calc_dir (str): Directory containing the outputs( vasprun.xml and OUTCAR) of previous vasp run. standardize (float): Whether to standardize to a primitive standard cell. Defaults to False. sym_prec (float): Tolerance for symmetry finding. If not 0, the final structure from the previous run will be symmetrized to get a primitive standard cell. Set to 0 if you don't want that. international_monoclinic (bool): Whether to use international convention (vs Curtarolo) for monoclinic. Defaults True. grid_density (int): density of k-mesh by reciprocal atom (defaults to 8000) small_gap_multiply ([float, float]): If the gap is less than 1st index, multiply the default reciprocal_density by the 2nd index. \\*\\*kwargs: All kwargs supported by MPStaticSet, other than prev_incar and prev_structure and prev_kpoints which are determined from the prev_calc_dir. """ vasprun, outcar = get_vasprun_outcar(prev_calc_dir) prev_incar = vasprun.incar prev_kpoints = vasprun.kpoints # We will make a standard structure for the given symprec. prev_structure = get_structure_from_prev_run( vasprun, outcar, sym_prec=standardize and sym_prec, international_monoclinic=international_monoclinic) # multiply the reciprocal density if needed: if small_gap_multiply: gap = vasprun.eigenvalue_band_properties[0] if gap <= small_gap_multiply[0]: grid_density = grid_density * small_gap_multiply[1] return PRLRoughStaticSet(structure=prev_structure, prev_incar=prev_incar, prev_kpoints=prev_kpoints, grid_density=grid_density, **kwargs)
def run_task(self, fw_spec): scissor = self.get("scissor", 0.0) tmax = self.get("tmax", 1300) tgrid = self.get("tgrid", 50) doping = self.get("doping", None) soc = self.get("soc", False) vasprun, outcar = get_vasprun_outcar(".", parse_dos=True, parse_eigen=True) bs = vasprun.get_band_structure() nelect = outcar.nelect runner = BoltztrapRunner(bs, nelect, scissor=scissor, doping=doping, tmax=tmax, tgrid=tgrid, soc=soc) runner.run(path_dir=os.getcwd())
def run_task(self, fw_spec): normalmode_dict = fw_spec.get("normalmodes", None) if not normalmode_dict: vrun, _ = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=True) structure = vrun.final_structure.copy() normalmode_eigenvals = vrun.normalmode_eigenvals normalmode_eigenvecs = vrun.normalmode_eigenvecs normalmode_norms = np.linalg.norm(normalmode_eigenvecs, axis=2) normalmode_dict = {"structure": structure, "eigenvals": normalmode_eigenvals.tolist(), "eigenvecs": normalmode_eigenvecs.tolist(), "norms": normalmode_norms.tolist()} return FWAction(mod_spec=[{'_set': {'normalmodes': normalmode_dict}}])
def run_task(self, fw_spec): vrun, _ = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=True) epsilon_static = vrun.epsilon_static epsilon_dict = {"mode": self["mode"], "displacement": self["displacement"], "epsilon": epsilon_static} return FWAction(mod_spec=[{ '_set': { 'raman_epsilon->{}_{}'.format( str(self["mode"]), str(self["displacement"]).replace("-", "m").replace(".", "d")): epsilon_dict } }])
def run_task(self, fw_spec): mpr = MPRester(env_chk(self.get("MAPI_KEY"), fw_spec)) vasprun, outcar = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=False) my_entry = vasprun.get_computed_entry(inc_structure=False) stored_data = mpr.get_stability([my_entry])[0] if stored_data["e_above_hull"] > self.get("ehull_cutoff", 0.05): return FWAction(stored_data=stored_data, exit=True, defuse_workflow=True) else: return FWAction(stored_data=stored_data)
def run_task(self, fw_spec): v, _ = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=False) stress = v.ionic_steps[-1]['stress'] defo = self['deformation'] d_ind = np.nonzero(defo - np.eye(3)) delta = Decimal((defo - np.eye(3))[d_ind][0]) # Shorthand is d_X_V, X is voigt index, V is value dtype = "_".join(["d", str(reverse_voigt_map[d_ind][0]), "{:.0e}".format(delta)]) strain = Strain.from_deformation(defo) defo_dict = {'deformation_matrix': defo, 'strain': strain.tolist(), 'stress': stress} return FWAction(mod_spec=[{'_set': { 'deformation_tasks->{}'.format(dtype): defo_dict}}])
def run_task(self, fw_spec): mpr = MPRester(env_chk(self.get("MAPI_KEY"), fw_spec)) vasprun, outcar = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=False) my_entry = vasprun.get_computed_entry(inc_structure=False) stored_data = mpr.get_stability([my_entry])[0] if stored_data["e_above_hull"] > self.get("ehull_cutoff", 0.05): logger.info("CheckStability: failed test!") return FWAction(stored_data=stored_data, exit=True, defuse_workflow=True) else: return FWAction(stored_data=stored_data)
def run_task(self, fw_spec): normalmode_dict = fw_spec.get("normalmodes", None) if not normalmode_dict: vrun, _ = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=True) structure = vrun.final_structure.copy() normalmode_eigenvals = vrun.normalmode_eigenvals normalmode_eigenvecs = vrun.normalmode_eigenvecs normalmode_norms = np.linalg.norm(normalmode_eigenvecs, axis=2) normalmode_dict = { "structure": structure, "eigenvals": normalmode_eigenvals.tolist(), "eigenvecs": normalmode_eigenvecs.tolist(), "norms": normalmode_norms.tolist() } return FWAction(mod_spec=[{'_set': {'normalmodes': normalmode_dict}}])
def run_task(self, fw_spec): vrun, _ = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=True) epsilon_static = vrun.epsilon_static epsilon_dict = { "mode": self["mode"], "displacement": self["displacement"], "epsilon": epsilon_static } return FWAction(mod_spec=[{ '_set': { 'raman_epsilon->{}_{}'.format( str(self["mode"]), str(self["displacement"]).replace("-", "m").replace( ".", "d")): epsilon_dict } }])
def run_task(self, fw_spec): v, _ = get_vasprun_outcar(self.get("calc_dir", "."), parse_dos=False, parse_eigen=False) stress = v.ionic_steps[-1]['stress'] defo = self['deformation'] d_ind = np.nonzero(defo - np.eye(3)) delta = Decimal((defo - np.eye(3))[d_ind][0]) # Shorthand is d_X_V, X is voigt index, V is value dtype = "_".join( ["d", str(reverse_voigt_map[d_ind][0]), "{:.0e}".format(delta)]) strain = Strain.from_deformation(defo) defo_dict = { 'deformation_matrix': defo, 'strain': strain.tolist(), 'stress': stress } return FWAction(mod_spec=[{ '_set': { 'deformation_tasks->{}'.format(dtype): defo_dict } }])
def from_prev_calc(cls, dirname: str, task: Optional[Task] = None, xc: Optional[Xc] = None, json_filename: str = "vise.json", parse_calc_results: bool = True, parse_incar: bool = True, sort_structure: bool = True, standardize_structure: bool = False, files_to_transfer: Optional[dict] = None, user_incar_settings: Optional[dict] = None, contcar_filename: str = "CONTCAR", **kwargs) -> "ViseInputSet": """Constructor based on the previous calculations. If the task and/or xc are not set, the previous ones are assumed. Args: dirname (str): Directory name to be parsed. xc (Xc): Exchange-correlation (xc) defined in Xc. task (Task): Task defined in Task. json_filename (str): Json filename including ViseInputSet data. parse_calc_results (bool): Whether to parse the previous calculation results for band edges, magnetization. parse_incar (bool): Whether to parse the previous INCAR files, which could include other options that are not determined in vise. sort_structure (bool): Whether to sort the elements using get_sorted_structure method of Structure class in pymatgen. standardize_structure (bool): Whether to convert the structure to a standardized primitive. files_to_transfer (dict): Keys are file names to be transferred in the directory. Values mean the transfer modes, where there are three modes, "c": copy file, "m": move file, "l": make symbolic link e.g., {"CHGCAR": "c", "WAVECAR": "l", ..} user_incar_settings (dict): User INCAR settings. e.g., {"NSW": 100, "LWAVE": True, "LASPH": "A", ..} contcar_filename (str): CONTCAR type filename. Used if the user change the name. kwargs: Other OPTION arguments. Return: ViseInputSet class object. """ kwargs = kwargs or {} kwargs["sort_structure"] = sort_structure kwargs["standardize_structure"] = standardize_structure path = Path(dirname) input_set = ViseInputSet.load_json(path / json_filename) if parse_calc_results: vasprun, outcar = get_vasprun_outcar(dirname) structure = get_structure_from_prev_run(vasprun, outcar) gap_properties = band_gap_properties(vasprun) if gap_properties: _, vbm, cbm = gap_properties kwargs["vbm_cbm"] = [vbm["energy"], cbm["energy"]] if "magmom" in structure.site_properties.keys(): abs_max_mag = abs( max(structure.site_properties["magmom"], key=abs)) else: abs_max_mag = 0 if vasprun.is_spin and abs_max_mag > 0.05: kwargs["is_magnetization"] = True else: contcar = path / contcar_filename poscar = path / "POSCAR" if contcar.is_file and os.stat(contcar).st_size != 0: logger.info(f"{contcar} is parsed for structure.") structure = Structure.from_file(contcar) elif poscar.is_file and os.stat(poscar).st_size != 0: logger.warning(f"{poscar} is parsed for structure.") structure = Structure.from_file(poscar) else: raise FileNotFoundError("CONTCAR or POSCAR does not exist.") if parse_incar: input_set.incar_settings = ViseIncar.from_file(path / "INCAR") if files_to_transfer: abs_files_to_transfer = {} for filename, value in files_to_transfer.items(): f = path / filename if not f.is_file(): logger.warning(f"{f} does not exist.") elif os.stat(f).st_size == 0: logger.warning(f"{f} is empty.") elif value[0].lower() not in ["l", "c", "m"]: logger.warning( f"{value} option for {filename} is invalid.") else: abs_files_to_transfer[str(f)] = value[0].lower() files_to_transfer = abs_files_to_transfer return cls.make_input(structure=structure, task=task or input_set.task, xc=xc or input_set.xc, prev_set=input_set, abs_files_to_transfer=files_to_transfer, user_incar_settings=user_incar_settings, **kwargs)