Example #1
0
def clean_up_files(
    original_wf,
    files=("WAVECAR*",),
    fw_name_constraint=None,
    task_name_constraint="RunVasp",
):
    """
    Cleans up files after another fireworks. Default behavior is to remove
        WAVECAR after running VASP.

    Args:
        original_wf (Workflow)
        files (list): list of patterns to match for files to clean up
        fw_name_constraint (str): pattern for fireworks to clean up files after
        task_name_constraint (str): pattern for firetask to clean up files

    Returns:
       Workflow
    """
    idx_list = get_fws_and_tasks(
        original_wf,
        fw_name_constraint=fw_name_constraint,
        task_name_constraint=task_name_constraint,
    )
    for idx_fw, idx_t in idx_list:
        original_wf.fws[idx_fw].tasks.insert(idx_t + 1, DeleteFiles(files=files))
    return original_wf
Example #2
0
    def test_cleanupfiles(self):
        fw1 = Firework(
            [
                CreateFolder(folder_name="to_remove.relax0"),
                CreateFolder(folder_name="to_remove.relax1"),
                CreateFolder(folder_name="dont_remove.relax0"),
                CreateFolder(folder_name="shouldnt_touch"),
                DeleteFiles(files=["to_remove*", "dont_remove"]),
                PassCalcLocs(name="fw1"),
            ],
            name="fw1",
        )
        fw2 = Firework([PassCalcLocs(name="fw2")], name="fw2", parents=fw1)

        wf = Workflow([fw1, fw2])
        self.lp.add_wf(wf)
        rapidfire(self.lp)

        fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0])
        calc_locs = fw2.spec["calc_locs"]

        self.assertTrue(
            os.path.exists(
                os.path.join(
                    get_calc_loc("fw1", calc_locs)["path"],
                    "dont_remove.relax0")))
        self.assertTrue(
            os.path.exists(
                os.path.join(
                    get_calc_loc("fw1", calc_locs)["path"], "shouldnt_touch")))
        self.assertFalse(
            os.path.exists(
                os.path.join(
                    get_calc_loc("fw1", calc_locs)["path"],
                    "to_remove.relax0")))
        self.assertFalse(
            os.path.exists(
                os.path.join(
                    get_calc_loc("fw1", calc_locs)["path"],
                    "to_remove.relax1")))
Example #3
0
    def __init__(
        self,
        structure: Structure = None,
        name: str = "lobster_calculation",
        lobster_cmd: str = LOBSTER_CMD,
        db_file: str = DB_FILE,
        delete_wavecar: bool = False,
        delete_wavecar_previous_fw: bool = False,
        handler_group: Union[List[ErrorHandler], str] = "default",
        validator_group: Union[List[Validator], str] = "default",
        calculation_type: str = "standard",
        parents: Union[List[Firework], Firework] = None,
        prev_calc_dir: str = None,
        prev_calc_loc: bool = True,
        user_supplied_basis: dict = None,
        lobsterin_key_dict: dict = None,
        lobstertodb_kwargs: dict = None,
        additional_outputs: List[str] = None,
        **kwargs
    ):
        """

        Args:
            structure (Structure): Structure object, will only be used to name firework
            name (str): name of the firework
            lobster_cmd (str): command to run lobster
            db_file (str): address to db_file
            delete_wavecar (bool): If True, WAVECAR will be deleted in the folder of the Lobster run
            delete_wavecar_previous_fw (bool): If True, WAVECAR from initial VASP calc will be deleted
            handler_group (Union[List[ErrorHandler],str])): group of handlers to use. See handler_groups dict in the code for
                the groups and complete list of handlers in each group. Alternatively, you can
                specify a list of ErrorHandler objects. This information can be found in the lobster module of
                custodian.
            validator_group (Union[List[Validator],str]): group of validators to use. See validator_groups dict in the
                code for the groups and complete list of validators in each group. Alternatively, you can
                specify a list of Validator objects.
            calculation_type (str): only 'standard' is fully implemented so far
            parents (Union[List[Firework],Firework]): parent Firework
            prev_calc_dir (str): address to previous vasp calculation
            prev_calc_loc (bool): If true, calc wil be started from previous directory
            user_supplied_basis (dict): the user can supply their own basis functions
            lobsterin_key_dict (dict): the user can supply additional changes to the lobsterin with {"COHPendEnergy":10.0}
            lobstertodb_kwargs (dict): dict that will be saved in the mongodb database
            additional_outputs (List[str]): list of additional files to be stored in the
                results DB. They will be stored as files in gridfs. Examples are:
                "ICOHPLIST.lobster" or "DOSCAR.lobster". Note that the file name
                should be given with the full name and the correct capitalization.
            **kwargs:
        """

        # TODO: make this lobster firework more flexible to allow for FATBAND and other types of calculations

        fw_name = "{}-{}".format(
            structure.composition.reduced_formula if structure else "unknown", name
        )

        t = []
        # copies all files from previous VASP calculation;
        additional_files = [
            f
            for f in VASP_OUTPUT_FILES
            if f not in ["POSCAR", "POTCAR", "KPOINTS", "INCAR"]
        ]
        if prev_calc_dir:
            t.append(
                CopyVaspOutputs(
                    calc_dir=prev_calc_dir,
                    additional_files=additional_files,
                    contcar_to_poscar=False,
                )
            )
            calc_loc = False
        elif parents:
            t.append(
                CopyVaspOutputs(
                    calc_loc=prev_calc_loc,
                    additional_files=additional_files,
                    contcar_to_poscar=False,
                )
            )
            calc_loc = True
        else:
            raise ValueError("One must specify a VASP calculation for Lobster run")

        t.append(
            WriteLobsterinputfromIO(
                poscar_path="POSCAR",
                incar_path="INCAR",
                potcar_path="POTCAR",
                option=calculation_type,
                user_supplied_basis=user_supplied_basis,
                user_lobsterin_settings=lobsterin_key_dict,
            )
        )

        # runs lobster
        if delete_wavecar:
            t.append(
                RunLobster(
                    lobster_cmd=lobster_cmd,
                    gzip_output=True,
                    gzip_WAVECAR=False,
                    handler_group=handler_group,
                    validator_group=validator_group,
                )
            )
        else:
            t.append(
                RunLobster(
                    lobster_cmd=lobster_cmd,
                    gzip_output=True,
                    gzip_WAVECAR=True,
                    handler_group=handler_group,
                    validator_group=validator_group,
                )
            )

        # task to delete wavecar to avoid storage problems with wavecars -> WAVECARs without symmetry can be huge
        if delete_wavecar:
            t.append(DeleteFiles(files=["WAVECAR", "WAVECAR.gz"]))
        if delete_wavecar_previous_fw:
            t.append(
                DeleteFilesPrevFolder(
                    files=["WAVECAR", "WAVECAR.gz"], calc_loc=calc_loc
                )
            )

        # Will save Lobster Calculation in Database
        t.append(
            LobsterRunToDb(
                db_file=db_file,
                calc_loc=calc_loc,
                additional_fields=lobstertodb_kwargs,
                additional_outputs=additional_outputs,
            )
        )

        # passes information to next firetask
        t.append(PassCalcLocs(name=name))

        super(LobsterFW, self).__init__(t, parents=parents, name=fw_name, **kwargs)
Example #4
0
    def __init__(
        self,
        structure=None,
        name="SCAN structure optimization",
        vasp_input_set=None,
        vasp_input_set_params=None,
        vasp_cmd=VASP_CMD,
        vdw_kernel_dir=VDW_KERNEL_DIR,
        prev_calc_loc=None,
        prev_calc_dir=None,
        db_file=DB_FILE,
        vasptodb_kwargs=None,
        parents=None,
        **kwargs,
    ):
        """
        Structure optimization using the SCAN metaGGA functional. If this Firework is
        initialized with no parents, it will perform a GGA optimization of the provided
        structure using the PBESol functional. This GGA-relaxed structure is intended
        to be passed to a second instance of this Firework for optimization with SCAN.
        (see workflow definition in SCAN_optimization.yaml)

        Args:
            structure (Structure): Input structure. Note that for prev_calc_loc jobs, the structure
                is only used to set the name of the FW and any structure with the same composition
                can be used.
            name (str): Name for the Firework.
            vasp_input_set (VaspInputSet): input set to use (for jobs w/no parents)
                Defaults to MpScanRelaxSet() if None.
            vasp_input_set_params (dict): Dict of vasp_input_set kwargs.
            vasp_cmd (str): Command to run vasp.
            vdw_kernel_dir (str): Directory containing the pre-compiled VdW
                kernel. Supports env_chk.
            prev_calc_loc (bool or str): If true (default), copies outputs from previous calc. If
                a str value, retrieves a previous calculation output by name. If False/None, will create
                new SCAN calculation using the provided structure.
            prev_calc_dir (str): Path to a previous calculation to copy from
            db_file (str): Path to file specifying db credentials.
            parents (Firework): Parents of this particular Firework. FW or list of FWs.
            vasptodb_kwargs (dict): kwargs to pass to VaspToDb
            **kwargs: Other kwargs that are passed to Firework.__init__.
        """
        t = []

        vasp_input_set_params = vasp_input_set_params or {}
        vasptodb_kwargs = vasptodb_kwargs or {}
        if "additional_fields" not in vasptodb_kwargs:
            vasptodb_kwargs["additional_fields"] = {}
        vasptodb_kwargs["additional_fields"]["task_label"] = name

        fw_name = "{}-{}".format(
            structure.composition.reduced_formula if structure else "unknown",
            name)

        has_previous_calc = False

        # Raise a warning if the InputSet is not MPScanRelaxSet, because the
        # kspacing calculation from bandgap is only supported in MPScanRelaxSet.
        if vasp_input_set and not isinstance(vasp_input_set, MPScanRelaxSet):
            raise UserWarning("You have specified a vasp_input_set other than \
                 MPScanRelaxSet. Automatic adjustment of kspacing\
                 is not supported by this InputSet.")

        if prev_calc_dir:
            has_previous_calc = True
            # Copy the CHGCAR from previous calc directory (usually PBE)
            t.append(
                CopyVaspOutputs(
                    calc_dir=prev_calc_dir,
                    contcar_to_poscar=True,
                    additional_files=["CHGCAR"],
                ))
        elif parents:
            if prev_calc_loc:
                has_previous_calc = True
                # Copy the CHGCAR from previous calc location (usually PBE)
                t.append(
                    CopyVaspOutputs(
                        calc_loc=prev_calc_loc,
                        contcar_to_poscar=True,
                        additional_files=["CHGCAR"],
                    ))
            else:
                raise UserWarning(
                    "You specified parent Firework but did not provide its location. Set "
                    "prev_calc_dir or prev_calc_loc and try again.")
        elif prev_calc_loc:
            raise UserWarning(
                "You specified prev_calc_loc but did not provide a parent Firework. Set "
                "parents and try again.")

        if has_previous_calc:
            # Update the InputSet with the bandgap from the previous calc
            t.append(
                WriteScanRelaxFromPrev(
                    vasp_input_set_params=vasp_input_set_params))

            # Set ICHARG to 1 to utilize the pre-existing CHGCAR
            settings = {"_set": {"ICHARG": 1}}

            if vasp_input_set_params.get("vdw"):
                # Copy the pre-compiled VdW kernel for VASP
                t.append(
                    CopyFiles(files_to_copy=["vdw_kernel.bindat"],
                              from_dir=vdw_kernel_dir))

                # Enable vdW for the SCAN step
                settings["_set"]["LUSE_VDW"] = True
                settings["_set"]["BPARAM"] = 15.7

            t.append(ModifyIncar(incar_dictmod=settings))

            # use the 'scan' custodian handler group
            handler_group = "scan"

        elif structure:
            vasp_input_set = vasp_input_set or MPScanRelaxSet(
                structure, **vasp_input_set_params)
            t.append(
                WriteVaspFromIOSet(structure=structure,
                                   vasp_input_set=vasp_input_set))
            # Update the INCAR for the PBESol GGA preconditioning step
            pre_opt_settings = {
                "_set": {
                    "GGA": "Ps",
                    "METAGGA": None,
                    "EDIFFG": -0.05
                }
            }

            # Disable vdW for the precondition step
            if vasp_input_set_params.get("vdw"):
                pre_opt_settings.update(
                    {"_unset": {
                        "LUSE_VDW": True,
                        "BPARAM": 15.7
                    }})

            t.append(ModifyIncar(incar_dictmod=pre_opt_settings))

            # use the 'default' custodian handler group
            handler_group = "default"
        else:
            raise ValueError("Must specify structure or previous calculation")

        # Run VASP
        t.append(
            RunVaspCustodian(
                vasp_cmd=vasp_cmd,
                auto_npar=">>auto_npar<<",
                handler_group=handler_group,
                gzip_output=False,
            ))
        t.append(PassCalcLocs(name=name))
        # Parse
        t.append(VaspToDb(db_file=db_file, **vasptodb_kwargs))
        # Delete the VdW kernel
        t.append(DeleteFiles(files=["vdw_kernel.bindat"]))
        # zip the output (don't rely on custodian to do it)
        t.append(GzipDir())

        super().__init__(t, parents=parents, name=fw_name, **kwargs)