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
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")))
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)
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)