Exemple #1
0
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)
Exemple #2
0
    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)