Customizing workflows — atomate 0.9.2 documentation

# Customizing Workflows

## Introduction

The Creating Workflows guide gave details on constructing workflows. This group of tutorials will give specific examples for customizations to workflows as you create them.

For some of these customizations, preset workflows cannot be used. Preset workflows are designed to give generically reasonable options. More full access for customizing the workflows can be achieved by using the `atomate.vasp.workflows.base` workflows instead of the presets.

## Objectives

- Provide examples for customizating workflows

## Prerequisites

It’s best if you are able to create workflows on your own in Python. See the creating workflows guide

## Powerups

Powerups are all designed to be used as functions where you pass in your original workflow and other keyword arguments and get back the modified workflow. An example is shown below, but does not show all of the powerups. To see more powerups go to the powerups documentation for the package you are using, e.g. VASP is :py:mod`atomate.vasp.powerups`.

An example for adding an INCAR setting to use a different force convergence criteria for the only the structure optimization in the elastic workflow is

    from atomate.vasp.workflows.presets.core import wf_elastic_constant
    from atomate.vasp.powerups import add_modify_incar
    from pymatgen import Structure

    # load your structure, e.g. from a POSCAR
    struct = Structure.from_file('POSCAR')

    # create the workflow
    orig_wf = wf_elastic_constant(struct)

    # use the powerup to change any Fireworks with 'optimization' in the name to use EDIFFG=-0.05
    # note: the 'incar_update' is *required* if you want to update
    # note: not passing the ``modify_incar_params`` keyword will result in the Firework getting
    #       the 'incar_update' key and values from your FireWorker's env
    modified_wf = add_modify_incar(orig_wf, modify_incar_params={'incar_update': {'EDIFFG': -0.05}},
                                   fw_name_constraint='optimization')

    # print if you want to check the tasks. Warning: several lines long.
    # print(orig_wf.fws[0].tasks)
    # print(modified_wf.fws[0].tasks)

## VASP Calculation Settings

Most VASP calculation-specific settings (e.g. those from INCAR, KPOINTS, and POTCAR files) are controlled by pymatgen’s vasp sets . VASP workflows take `vasp_input_set` options and you can directly import and use them or customize them before using them in atomate workflows.

Note

Using the `vasp_input_set` or `vis` keywords in workflow constructors usually only controls the first Firework that uses that set. If you want to have multiple Fireworks use custom input sets (or just not the first one, e.g. in a bandstructure workflow) then you have to make a custom workflow yourself.

### Using a different functional

To use a different functional, for instance in a optimization calculation, you can do the following:

    from fireworks import Workflow
    from atomate.vasp.fireworks.core import OptimizeFW
    from pymatgen.io.vasp.sets import MPRelaxSet
    from pymatgen import Structure

    def get_optimize_wf(structure, name="optimization wf", vasp_input_set=None,
                        vasp_cmd="vasp", db_file=None, user_kpoints_settings=None,
                        tag="", metadata=None):
        """
        Returns a structure optimization workflow.

        Args:
            structure (Structure): input structure to be optimized and run
            name (str): some appropriate name for the transmuter fireworks.
            vasp_input_set (DictSet): vasp input set.
            vasp_cmd (str): command to run
            db_file (str): path to file containing the database credentials.
            user_kpoints_settings (dict): example: {"grid_density": 7000}
            tag (str): some unique string that will be appended to the names of the fireworks so that
                the data from those tagged fireworks can be queried later during the analysis.
            metadata (dict): meta data

        Returns:
            Workflow
        """
        # input set for relaxation
        vis_relax = vasp_input_set or MPRelaxSet(structure)
        if user_kpoints_settings:
            v = vis_relax.as_dict()
            v.update({"user_kpoints_settings": user_kpoints_settings})
            vis_relax = vis_relax.__class__.from_dict(v)

        # Structure optimization firework
        fws = [OptimizeFW(structure=structure, vasp_input_set=vis_relax, vasp_cmd=vasp_cmd,
                          db_file=db_file, name="{} structure optimization".format(tag))]

        wfname = "{}:{}".format(structure.composition.reduced_formula, name)

        return Workflow(fws, name=wfname, metadata=metadata)

    # load your structure, e.g. from a POSCAR
    struct = Structure.from_file('POSCAR')

    # create a custom input set
    my_custom_input_set = MPRelaxSet(struct, potcar_functional='LDA')

    # create the workflow
    my_wf = get_optimize_wf(struct, vasp_input_set=my_custom_input_set)

For the supported options, see the VASP documentation and pymatgen’s vasp sets documentation. PBE (default), LDA, PW91, LDA_US were supported at the time of writing.

### Custom KPOINTS settings

KPOINTS settings can also be similarly customized using the above example. You can control them with the following keywords (from pymatgen’s vasp sets):

- `force_gamma`: always use gamma centered kpoint generation. Default (False) is to use Automatic Density kpoint scheme, which will use the Gamma centered generation scheme for hexagonal cells, and Monkhorst-Pack otherwise.

- `user_kpoints_settings`: Override kpoints setting by supplying a dict. E.g., `{"reciprocal_density": 1000}`. Other options are `grid_density` or `length`.

    from pymatgen.io.vasp.sets import MPRelaxSet
    from pymatgen import Structure

    # load your structure, e.g. from a POSCAR
    struct = Structure.from_file('POSCAR')

    # create a custom input set
    my_custom_input_set = MPRelaxSet(struct, force_gamma=True, {"grid_density": 10} )

    # create the workflow
    my_wf = get_optimize_wf(struct, vasp_input_set=my_custom_input_set)

If you need more control, create the `Kpoints` object directly with pymatgen. It is flexible and only a brief example will be shown. See the full Kpoints documentation for more

    from pymatgen.io.vasp.sets import MPRelaxSet
    from pymatgen.io.vasp.inputs import Kpoints
    from pymatgen import Structure

    # load your structure, e.g. from a POSCAR
    struct = Structure.from_file('POSCAR')

    # the simples way to do this is to create a subclass of the input set you want
    # and override the kpoints property to return what you want.
    class MyInputSet(MPRelaxSet):
        def __init__(self, structure, points=(5,5,5), shift=(0,0,0), **kwargs):
            super(MPRelaxSet, self).__init__(structure, MPRelaxSet.CONFIG, **kwargs)
            self.points = points
            self.shift = shift

        @property
        def kpoints(self):
            # choose either of these
            # use Monkhorst-Pack scheme
            return Kpoints.monkhorst_automatic(kpts=self.points, shift=self.shift)
            # use a Gamma centered scheme
            return Kpoints.gamma_automatic(kpts=self.points, shift=self.shift)

    # create an instance of the custom input set
    my_custom_input_set = MyInputSet(struct, points=(5,5,5), shift=(1,1,1))
    # show that the set applied
    print(my_custom_input_set.kpoints)

    # create the workflow
    my_wf = get_optimize_wf(struct, vasp_input_set=my_custom_input_set)

### Custom INCAR settings

Custom INCAR settings can also be accomplished using `VaspInputSet` objects, but it is often more efficient to use a add_modify_incar Powerup

### Use a different POTCAR

Which POTCAR file you want to use is controlled by the input set as well. The easist way to control it is by updating the `config_dict` dictionary of your input set.

    from pymatgen.io.vasp.sets import MPRelaxSet
    from pymatgen import Structure

    # load your structure, e.g. from a POSCAR
    struct = Structure.from_file('POSCAR')

    # create a custom input set
    my_custom_input_set = MPRelaxSet(struct)
    print('Config dict example: {}\n'.format(my_custom_input_set.config_dict))
    print('Before change: {}'.format(my_custom_input_set.config_dict['POTCAR']['Mg']))
    my_custom_input_set.config_dict['POTCAR']['Mg'] = 'Mg'
    print('After change: {}'.format(my_custom_input_set.config_dict['POTCAR']['Mg']))

    # create the workflow
    my_wf = get_optimize_wf(struct, vasp_input_set=my_custom_input_set)

Warning

Make sure not to try a nested dictionary update (e.g. `my_custom_input_set.config_dict.update({'POTCAR': {'Mg': 'Mg'}})` )! It will wipe out all of the other `POTCAR` entries in the dict.