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 path_structures(self): for path in self.paths: parent_dir = os.path.dirname(os.path.abspath(path)) vasprun_path = os.path.join(parent_dir, 'vasprun.xml') outcar_path = os.path.join(parent_dir, 'OUTCAR') if os.path.exists(vasprun_path) == True and os.path.exists( outcar_path) == True: try: V = Vasprun(vasprun_path) O = Outcar(outcar_path) structure = get_structure_from_prev_run(V, O) if self.rescale == True: structure = self.structure_rescaler(structure) structure_key = str(structure.formula) + ' ' + str( self.structure_number) self.structures_dict[structure_key] = structure self.structure_number += 1 except UnicodeDecodeError: print('Either %s or %s not readable' % (vasprun_path, outcar_path)) continue except OSError: print('Either %s or %s not readable' % (vasprun_path, outcar_path)) continue else: try: poscar = Poscar.from_file(path) structure = poscar.structure if self.rescale == True: structure = self.structure_rescaler(structure) structure_key = str(structure.formula) + ' ' + str( self.structure_number) self.structures_dict[structure_key] = structure self.structure_number += 1 except FileNotFoundError: print('%s path does not exist' % path) continue except UnicodeDecodeError: print('%s likely not a valid CONTCAR or POSCAR' % path) continue except OSError: print('%s likely not a valid CONTCAR or POSCAR' % path) continue
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)