Skip to content

Automated DFT

This lesson focuses on key concepts necessary to run automated Density Functional Theory (DFT) workflows using our atomate code. We begin by focusing on using pymatgen to build inputs and parsing outputs of DFT calculations. Then we will go through a demonstration of using atomate to run DFT calculations.

Core Concepts

  • Writing Input Files - There is an enitre module in pymatgen devoted to reading and writing the input and output files of other codes to assist in calculation automation.
  • Parsing Output Files - Similar to handling input files, pymatgen also supports parsing output files. This machinery is also used by automate to parse entire output directories.
  • Database Automation - Atomate combines everything needed to automate running DFT calculations and storing them in a database.

For this lesson to work, we'll need to setup pymatgen with some files, pseudopotential that describe the charge density around each element, that typically are only available to registered VASP users. We've made some fake files with the correct structure so that pymatgen will still function.

import mp_workshop
FW Echo Test: MP Workshop

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/maggma/utils.py:20: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)
  from tqdm.autonotebook import tqdm

Lesson 1: Writing Input Files

For the first lesson we'll focus on using pymatgen to simplfy interfacing with DFT codes. Pymatgen has a IO (input/output) module which has methods to parse and write files that are compatible with a number of external codes. These external codes are written in coding languages other than python (e.g. Fortran, C, C++, etc.) but pymatgen's IO module allows us to interface with them all through python. These external codes include:

  • AbInit
  • EXCITING
  • FEFF
  • LAMMPS
  • Lobster
  • QChem
  • VASP
  • ATAT
  • Gaussian
  • NWCHem
  • ShengBTE
  • Wannier90
  • Zeo++

For today's lesson, we will focus on one of these codes, VASP (Vienna Ab initio Simulation Package), which is a DFT code for atomic scale materials modeling. VASP is the DFT code used by the Materials Project for inorganic crystals. We will also use a second DFT code, Q-Chem, in the exercises which is used by the Materials Project for molecules.

POSCAR Demonstration

Let's begin by obtaining a silicon structure to use in today's lesson. We will import this structure from a CIF (Crystallographic Information File) file which is not compatible with many DFT codes.

from pymatgen.core import Structure
struct = Structure.from_file(filename="./example_files/Si.CIF")
print(struct)
Full Formula (Si8)
Reduced Formula: Si
abc   :   5.523145   5.468728   5.468728
angles:  90.000000  90.000000  90.000000
Sites (8)
  #  SP       a     b     c
---  ----  ----  ----  ----
  0  Si    0.25  0.25  0.25
  1  Si    0.5   0.5   0
  2  Si    0.25  0.75  0.75
  3  Si    0.5   0     0.5
  4  Si    0.75  0.25  0.75
  5  Si    0     0.5   0.5
  6  Si    0.75  0.75  0.25
  7  Si    0     0     0

VASP has 4 types of input files that must be provided by the user to run a calculation: * INCAR: specifies modeling parameters (how to run the calculation) * POSCAR: provides atomic structure * KPOINTS: outlines points for sampling space in the simulation cell * POTCAR: describes how to simulate electrons via pseudopotentials

Pymatgen has python objects for representing each type of input file. For this lesson, we will first focus on the POSCAR to demonstrate the capabilties of these python objects.

from pymatgen.io.vasp.inputs import Poscar

Let's obtain a Poscar python object using the silicon structure object from before.

poscar = Poscar(structure=struct,comment="silicon")
print(poscar)
silicon
1.0
5.523145 0.000000 0.000000
0.000000 5.468728 0.000000
0.000000 0.000000 5.468728
Si
8
direct
0.250000 0.250000 0.250000 Si
0.500000 0.500000 0.000000 Si
0.250000 0.750000 0.750000 Si
0.500000 0.000000 0.500000 Si
0.750000 0.250000 0.750000 Si
0.000000 0.500000 0.500000 Si
0.750000 0.750000 0.250000 Si
0.000000 0.000000 0.000000 Si


Since we can construct POSCARs from any structure object, we can make modifications to structure objects (make supercells, remove atoms to form defects, etc.) and construct complex structures (e.g. heterostructures, adsorbates on surfaces, etc.) all using pymatgen before turning the structure into a POSCAR file.

In this Poscar object there is a full pymatgen structure that we can manipulate pythonically. To demonstrate, let's introduce a defect by removing the first site. To check our work, we look at how the Poscar has changed and print out the number of sites in our original struct (8) and the Poscar structure (7).

poscar.structure.remove_sites([0])
print(poscar)
silicon
1.0
5.523145 0.000000 0.000000
0.000000 5.468728 0.000000
0.000000 0.000000 5.468728
Si
7
direct
0.500000 0.500000 0.000000 Si
0.250000 0.750000 0.750000 Si
0.500000 0.000000 0.500000 Si
0.750000 0.250000 0.750000 Si
0.000000 0.500000 0.500000 Si
0.750000 0.750000 0.250000 Si
0.000000 0.000000 0.000000 Si


print(struct.num_sites,poscar.structure.num_sites)
8 7

When your structure is ready, in order to obtain our POSCAR file for running VASP, the Poscar object has a method for writing it out as a file.

poscar.write_file(filename="POSCAR")

Another useful method is getting a Poscar object from a POSCAR file that has already been written. Note you are able to import a compressed file without unzipping it.

poscar_from_file = Poscar.from_file(filename="./example_files/POSCAR.gz")
print(poscar_from_file)
Al16 Cr10
1.0
7.417988 0.000000 -2.655322
-3.770804 6.388081 -2.655321
0.000000 0.000000 7.878914
Al Cr
16 10
direct
0.696455 0.696455 0.696455 Al
0.646563 0.002044 0.646563 Al
0.646563 0.646563 0.002044 Al
0.002044 0.646563 0.646563 Al
0.336523 0.558569 0.336523 Al
0.336523 0.336523 0.558569 Al
0.558569 0.336523 0.336523 Al
0.734771 0.383622 0.734771 Al
0.734771 0.734771 0.383622 Al
0.383622 0.734771 0.734771 Al
0.280797 0.666745 0.038053 Al
0.038053 0.280797 0.666745 Al
0.666745 0.038053 0.280797 Al
0.666745 0.280797 0.038053 Al
0.038053 0.666745 0.280797 Al
0.280797 0.038053 0.666745 Al
0.151124 0.151124 0.151124 Cr
0.015343 0.797266 0.015343 Cr
0.015343 0.015343 0.797266 Cr
0.797266 0.015343 0.015343 Cr
0.987828 0.333690 0.987828 Cr
0.987828 0.987828 0.333690 Cr
0.333690 0.987828 0.987828 Cr
0.365023 0.015932 0.365023 Cr
0.365023 0.365023 0.015932 Cr
0.015932 0.365023 0.365023 Cr


All the python objects for VASP inputs (INCAR, POSCAR, KPOINTS, POTCAR) have similar methods for initiating the object and writing out files. See the pymatgen documentation for more details: https://pymatgen.org/_modules/pymatgen/io/vasp/inputs.html

Input Sets

It can still take quite some effort to explicitly generate each input file needed for calculation. To further automatation, pymatgen builds upon these pieces to generate InputSets. InputSets are objects that provide default parameters to perform a specific kind of calcualtion. Pymatgen has several InputSets including ones with the default paramters used for MP calculations. But it is also possible to define your own InputSet that lets you build new calculations using the parameters you want.

Let's continue with our silicon structure from before. To generate the remaining input files needed for a VASP calculation, let's use an InputSet object. To perform a structure relaxation, we can import the parameters used in the Materials Project from MPRelaxSet.

from pymatgen.io.vasp.sets import MPRelaxSet

Note all we need to initiate the MPRelaxSet InputSet is a structure object. All the information we need to generate the four VASP input files can be determined from the provided structure.

relax_set = MPRelaxSet(structure=struct)

We can access the pythonic object for each of the VASP Input files (INCAR, POSCAR, KPOINTS, POTCAR) from our InputSet object.

relax_set.incar
{'ALGO': 'Fast',
 'EDIFF': 0.0004,
 'ENCUT': 520,
 'IBRION': 2,
 'ISIF': 3,
 'ISMEAR': -5,
 'ISPIN': 2,
 'LASPH': True,
 'LORBIT': 11,
 'LREAL': 'Auto',
 'LWAVE': False,
 'NELM': 100,
 'NSW': 99,
 'PREC': 'Accurate',
 'SIGMA': 0.05,
 'MAGMOM': [0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6]}
relax_set.poscar
Si8
1.0
5.523145 0.000000 0.000000
0.000000 5.468728 0.000000
0.000000 0.000000 5.468728
Si
8
direct
0.250000 0.250000 0.250000 Si
0.500000 0.500000 0.000000 Si
0.250000 0.750000 0.750000 Si
0.500000 0.000000 0.500000 Si
0.750000 0.250000 0.750000 Si
0.000000 0.500000 0.500000 Si
0.750000 0.750000 0.250000 Si
0.000000 0.000000 0.000000 Si
relax_set.kpoints
pymatgen with grid density = 769 / number of atoms
0
Monkhorst
4 4 4
relax_set.potcar.as_dict()
{'functional': 'PBE',
 'symbols': ['Si'],
 '@module': 'pymatgen.io.vasp.inputs',
 '@class': 'Potcar'}

InputSet has a .write_input() method which will write out all the VASP input files we need to run a structure optimization for our silicon structure. Let's specify writing our input files to a directory as if we were going to launch VASP from that directory.

Note we will also set the potcar_spec=True flag to avoid writing an actual POTCAR file (which is composed from POTCAR files that can only be distrubuted under a VASP license). By default, POTCARs will be written based on POTCARs specifed by the environment variable PMG_VASP_PSP_DIR.

relax_set.write_input(output_dir="./Si_MPRelaxSet",potcar_spec=True)

Lesson 2: Parsing Output Files

After VASP has been run, you'll need to parse the VASP outputs to get the data you want. VASP makes a number of output files:

  • WAVECAR
  • CHGCAR
  • OUTCAR
  • vasprun.xml
  • PROCAR
  • And more ...

Please refer to VASP's documentation for descriptions of what these all are.

Vasprun Demonstration

For this portion of the lesson, we'll focus on vasprun.xml.gz in the example_VASP_Al16Cr10 directory. Similar to how pymatgen has objects corresponding to VASP input files, pymatgen has a Vasprun python object for parsing the outputs contained in vasprun.xml files.

from pymatgen.io.vasp.outputs import Vasprun
vrun = Vasprun(filename="./example_VASP_Al16Cr10/vasprun.xml.gz")
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/pymatgen/io/vasp/inputs.py:1792: UnknownPotcarWarning: POTCAR with symbol Al has metadata that does not match                          any VASP POTCAR known to pymatgen. The data in this                          POTCAR is known to match the following functionals:                          ['PBE']
  warnings.warn(
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/pymatgen/io/vasp/inputs.py:1792: UnknownPotcarWarning: POTCAR with symbol Cr_pv has metadata that does not match                          any VASP POTCAR known to pymatgen. The data in this                          POTCAR is known to match the following functionals:                          ['PBE']
  warnings.warn(

Since Vasprun objects have most of the information that VASP can provide, this one object is often enough to parse a full VASP calculation. Use vrun.+Tab to check out the properties from the Vasprun object.

For example, we can check if the calculation is converged as well as the the final structure and energy after the structure optimization was finished.

vrun.converged
True
vrun.final_structure
Structure Summary
Lattice
    abc : 7.858339351222918 7.858486224302677 7.857828722726137
 angles : 109.68307448574032 109.6862509307799 109.68598356491901
 volume : 370.5637945511443
      A : 7.41150067 -0.06594902 -2.61128434
      B : -3.66951308 6.43992452 -2.61110162
      C : -0.0388319 -0.06592473 7.85745622
PeriodicSite: Al (2.5789, 4.3928, 1.8349) [0.6964, 0.6964, 0.6964]
PeriodicSite: Al (4.7570, -0.0715, 3.3849) [0.6463, 0.0021, 0.6463]
PeriodicSite: Al (2.4184, 4.1194, -3.3584) [0.6463, 0.6463, 0.0021]
PeriodicSite: Al (-2.3810, 4.1196, 3.3853) [0.0021, 0.6463, 0.6463]
PeriodicSite: Al (0.4331, 3.5525, 0.3080) [0.3367, 0.5585, 0.3367]
PeriodicSite: Al (1.2385, 2.1091, 2.6301) [0.3367, 0.3367, 0.5585]
PeriodicSite: Al (2.8908, 2.1093, 0.3082) [0.5585, 0.3367, 0.3367]
PeriodicSite: Al (4.0091, 2.3707, 2.8527) [0.7345, 0.3832, 0.7345]
PeriodicSite: Al (2.7336, 4.6565, -0.8251) [0.7345, 0.7345, 0.3832]
PeriodicSite: Al (0.1161, 4.6564, 2.8529) [0.3832, 0.7345, 0.7345]
PeriodicSite: Al (-0.3646, 4.2729, -2.1752) [0.2811, 0.6668, 0.0382]
PeriodicSite: Al (-0.7746, 1.7638, 4.4054) [0.0382, 0.2811, 0.6668]
PeriodicSite: Al (4.7905, 0.1830, 0.3684) [0.6667, 0.0381, 0.2811]
PeriodicSite: Al (3.9084, 1.7639, -2.1754) [0.6667, 0.2811, 0.0381]
PeriodicSite: Al (-2.1748, 4.2731, 0.3682) [0.0382, 0.6668, 0.2811]
PeriodicSite: Al (1.9175, 0.1832, 4.4051) [0.2811, 0.0381, 0.6667]
PeriodicSite: Cr (0.5570, 0.9483, 0.3962) [0.1504, 0.1503, 0.1504]
PeriodicSite: Cr (-2.8111, 5.1348, -2.0003) [0.0157, 0.7977, 0.0157]
PeriodicSite: Cr (0.0279, 0.0475, 6.1852) [0.0157, 0.0157, 0.7976]
PeriodicSite: Cr (5.8535, 0.0475, -2.0004) [0.7976, 0.0157, 0.0157]
PeriodicSite: Cr (6.0631, 2.0162, 4.3142) [0.9883, 0.3333, 0.9883]
PeriodicSite: Cr (3.6852, 6.2772, -2.5420) [0.9883, 0.9883, 0.3333]
PeriodicSite: Cr (-1.1945, 6.2772, 4.3145) [0.3333, 0.9883, 0.9883]
PeriodicSite: Cr (2.6272, 0.0580, 1.8695) [0.3645, 0.0165, 0.3646]
PeriodicSite: Cr (1.3633, 2.3223, -1.7743) [0.3645, 0.3645, 0.0165]
PeriodicSite: Cr (-1.2298, 2.3221, 1.8693) [0.0164, 0.3645, 0.3645]
vrun.final_energy
-157.80974238

Another useful set of data is stored under .ionic_steps because this contains information on how the calculation progressed during each ionic step in the structure optimization.

We can check how many ionic steps were taken and what properties are stored for each ionic step.

len(vrun.ionic_steps)
4
vrun.ionic_steps[0].keys()
dict_keys(['e_fr_energy', 'e_wo_entrp', 'e_0_energy', 'forces', 'stress', 'electronic_steps', 'structure'])

By looping through we can see the energy at the end of each ionic step and how many electronic steps were required during each ionic step.

for i in vrun.ionic_steps:
    print(i["e_fr_energy"] ,len(i["electronic_steps"]))
-157.49049217 18
-157.58170253 13
-157.69641768 27
-157.80974238 10

Parsing Directories with Atomate Drones

To take parsing outputs from external codes one step further, we will introduce the concept of drones from the python code package, atomate. Pymatgen provides methods for parsing individual output files. Atomate drones combine these capabilities to parse entire output calculation directories and has an .assimilate() methode to produce a dictionary summarizing the results. This dictionary representation is helpful because it can be stored in a database as done with the Materials Project.

from atomate.vasp.drones import VaspDrone
drone = VaspDrone()
task_doc = drone.assimilate(path="./example_VASP_Al16Cr10")
2021-08-10 02:26:32,304 INFO atomate.vasp.drones Getting task doc for base dir :./example_VASP_Al16Cr10
2021-08-10 02:26:34,277 INFO atomate.vasp.drones Post-processing dir:./example_VASP_Al16Cr10
2021-08-10 02:26:34,278 WARNING atomate.vasp.drones Transformations file does not exist.
2021-08-10 02:26:34,281 INFO atomate.vasp.drones Post-processed /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/example_VASP_Al16Cr10

print(task_doc.keys())
dict_keys(['schema', 'dir_name', 'calcs_reversed', 'run_stats', 'chemsys', 'formula_anonymous', 'formula_reduced_abc', 'completed_at', 'nsites', 'composition_unit_cell', 'composition_reduced', 'formula_pretty', 'elements', 'nelements', 'input', 'output', 'state', 'analysis', 'last_updated', 'transformations'])

Lesson 3: Database Automation

The final section of this lesson focuses on automating DFT using our atomate code. atomate is a set of recipes for computing properties for both molecules and structures. The workflows in atomate run on fireworks, our workflow management software. fireworks stores workflow information and calculation summaries in MongoDB. Using this infrastructure MP routinely manages 10,000 simultaneous calculations on supercomputers such as Cori at NERSC.

Getting Workflows

Let's begin by importing a basic silicon structure

from pymatgen.core import Structure
si = Structure.from_file("./example_files/Si.CIF")
print(si)
Full Formula (Si8)
Reduced Formula: Si
abc   :   5.523145   5.468728   5.468728
angles:  90.000000  90.000000  90.000000
Sites (8)
  #  SP       a     b     c
---  ----  ----  ----  ----
  0  Si    0.25  0.25  0.25
  1  Si    0.5   0.5   0
  2  Si    0.25  0.75  0.75
  3  Si    0.5   0     0.5
  4  Si    0.75  0.25  0.75
  5  Si    0     0.5   0.5
  6  Si    0.75  0.75  0.25
  7  Si    0     0     0

In the past two lessons we've gone over some of the machinery used in this automation. Atomate workflows (with the support of fireworks) compiles everything needed to: * Store workflow inputs from the user * Create new calculation directories and write input files * Parse output directories and store results in a MongoDB database

We can import workflows from atomate which are essentially the recipes that outline the steps for how to automate calculations from start to finish. There are many pre-built workflows in automate for common types of calculations. The best way to explore all available workflows is by checking the atomate source code linked below. * VASP Workflows: https://github.com/hackingmaterials/atomate/tree/main/atomate/vasp/workflows/base * Q-Chem Workflows: https://github.com/hackingmaterials/atomate/tree/main/atomate/qchem/workflows/base

For this lesson, we will focus on two types of workflows for VASP. * Structure Optimization Workflow (simpler) * Bandstructure Workflow (more complex)

Let's get started by importing these workflows and then creating workflow objects from our silicon structure.

from atomate.vasp.workflows.presets.core import wf_structure_optimization, wf_bandstructure
so_wf = wf_structure_optimization(structure=si)
print(so_wf)
Workflow object: (fw_ids: odict_keys([-1]) , name: Si)

bs_wf = wf_bandstructure(structure=si)
print(bs_wf)
Workflow object: (fw_ids: odict_keys([-2, -3, -4, -5]) , name: Si)

The structure optimization workflow is simpler and we can see that it only contains one firework. The bandstructure workflow has four fireworks so we can assume it is more complex. Let's see a graphical representation of each of these workflows.

from mp_workshop.atomate import wf_to_graph
wf_to_graph(so_wf)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/backend.py in run(cmd, input, capture_output, check, encoding, quiet, **kwargs)
    169     try:
--> 170         proc = subprocess.Popen(cmd, startupinfo=get_startupinfo(), **kwargs)
    171     except OSError as e:

/usr/share/miniconda/envs/workshop/lib/python3.9/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask)
    946 
--> 947             self._execute_child(args, executable, preexec_fn, close_fds,
    948                                 pass_fds, cwd, env,

/usr/share/miniconda/envs/workshop/lib/python3.9/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1818                         err_msg = os.strerror(errno_num)
-> 1819                     raise child_exception_type(errno_num, err_msg, err_filename)
   1820                 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'dot'

The above exception was the direct cause of the following exception:

ExecutableNotFound                        Traceback (most recent call last)
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/IPython/core/formatters.py in __call__(self, obj)
    343             method = get_real_method(obj, self.print_method)
    344             if method is not None:
--> 345                 return method()
    346             return None
    347         else:

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/files.py in _repr_svg_(self)
    139 
    140     def _repr_svg_(self):
--> 141         return self.pipe(format='svg').decode(self._encoding)
    142 
    143     def pipe(self, format=None, renderer=None, formatter=None, quiet=False):

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/files.py in pipe(self, format, renderer, formatter, quiet)
    164         data = self.source.encode(self._encoding)
    165 
--> 166         out = backend.pipe(self._engine, format, data,
    167                            renderer=renderer, formatter=formatter,
    168                            quiet=quiet)

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/backend.py in pipe(engine, format, data, renderer, formatter, quiet)
    266     """
    267     cmd, _ = command(engine, format, None, renderer, formatter)
--> 268     out, _ = run(cmd, input=data, capture_output=True, check=True, quiet=quiet)
    269     return out
    270 

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/backend.py in run(cmd, input, capture_output, check, encoding, quiet, **kwargs)
    171     except OSError as e:
    172         if e.errno == errno.ENOENT:
--> 173             raise ExecutableNotFound(cmd) from e
    174         else:
    175             raise

ExecutableNotFound: failed to execute 'dot', make sure the Graphviz executables are on your systems' PATH
<graphviz.dot.Digraph at 0x7f5a134c2af0>
wf_to_graph(bs_wf)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/backend.py in run(cmd, input, capture_output, check, encoding, quiet, **kwargs)
    169     try:
--> 170         proc = subprocess.Popen(cmd, startupinfo=get_startupinfo(), **kwargs)
    171     except OSError as e:

/usr/share/miniconda/envs/workshop/lib/python3.9/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask)
    946 
--> 947             self._execute_child(args, executable, preexec_fn, close_fds,
    948                                 pass_fds, cwd, env,

/usr/share/miniconda/envs/workshop/lib/python3.9/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1818                         err_msg = os.strerror(errno_num)
-> 1819                     raise child_exception_type(errno_num, err_msg, err_filename)
   1820                 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'dot'

The above exception was the direct cause of the following exception:

ExecutableNotFound                        Traceback (most recent call last)
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/IPython/core/formatters.py in __call__(self, obj)
    343             method = get_real_method(obj, self.print_method)
    344             if method is not None:
--> 345                 return method()
    346             return None
    347         else:

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/files.py in _repr_svg_(self)
    139 
    140     def _repr_svg_(self):
--> 141         return self.pipe(format='svg').decode(self._encoding)
    142 
    143     def pipe(self, format=None, renderer=None, formatter=None, quiet=False):

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/files.py in pipe(self, format, renderer, formatter, quiet)
    164         data = self.source.encode(self._encoding)
    165 
--> 166         out = backend.pipe(self._engine, format, data,
    167                            renderer=renderer, formatter=formatter,
    168                            quiet=quiet)

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/backend.py in pipe(engine, format, data, renderer, formatter, quiet)
    266     """
    267     cmd, _ = command(engine, format, None, renderer, formatter)
--> 268     out, _ = run(cmd, input=data, capture_output=True, check=True, quiet=quiet)
    269     return out
    270 

/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/graphviz/backend.py in run(cmd, input, capture_output, check, encoding, quiet, **kwargs)
    171     except OSError as e:
    172         if e.errno == errno.ENOENT:
--> 173             raise ExecutableNotFound(cmd) from e
    174         else:
    175             raise

ExecutableNotFound: failed to execute 'dot', make sure the Graphviz executables are on your systems' PATH
<graphviz.dot.Digraph at 0x7f5a0adccb80>

The exact steps in each firework can vary but for these cases, each firework roughly represents one VASP calculation which consists of the following steps:

1. Write VASP input files
2. Run VASP
3. Parse VASP output files

In the more complex bandstructure workflow, we can see the fireworks are connected. That means the outputs from one firework are passed to the next firework so the VASP calculation can start from the relaxed structure of the previous calculation.

Before we move forward with running our workflows, we will make one modification called use_fake_vasp_workshop. This will change the fireworks in the workflows so they will not actually run VASP (which requires greater computer resources and a VASP license), but instead will simulate running VASP by copying over pre-existing VASP output files.

from mp_workshop.atomate import use_fake_vasp_workshop
so_wf = use_fake_vasp_workshop(so_wf)
bs_wf = use_fake_vasp_workshop(bs_wf)

Launching Workflows from Your LaunchPad

Now we will introduce the LaunchPad from fireworks which is a python object that let's us interface with MongoDB and manage our queue of calculations. The LaunchPad allows you to submit and query workflows from anywhere you have database access. We need to get ourselves a LaunchPad object and set it up so we can submit our workflows.

from fireworks import LaunchPad
lp = LaunchPad.auto_load()
lp.reset(password=None,require_password=False)
2021-08-10 02:26:34,430 INFO Performing db tune-up
2021-08-10 02:26:34,512 INFO LaunchPad was RESET.

Note lp.reset() should only be executed one time when you are first initializing your database set-up. If you reset your LaunchPad at a later time, you will erase the record of past calcuations you have run.

Adding our workflows to our Launchpad will encode and store our workflow objects into MongoDB so they can be accessed later. Let's start by adding one workflow, the simpler structure optimization workflow.

lp.add_wf(so_wf)
2021-08-10 02:26:34,526 INFO Added a workflow. id_map: {-1: 1}

{-1: 1}

Now that a workflow is in our LaunchPad, we can check on its status using .get_wf_summary_dict()

lp.get_wf_summary_dict(fw_id=1)
{'state': 'READY',
 'name': 'Si',
 'created_on': datetime.datetime(2021, 8, 10, 2, 26, 34, 316000),
 'updated_on': datetime.datetime(2021, 8, 10, 2, 26, 34, 316000),
 'states': OrderedDict([('Si-structure optimization--1', 'READY')]),
 'launch_dirs': OrderedDict([('Si-structure optimization--1', [])])}

Now that we a workflow in our LaunchPad, we are ready to run it. Normally we run fireworks through the command-line interface on supercomputers because external codes, such as VASP, require more compute resources. However, for today's demonstration, we will run our workflows locally in this notebook to illustrate how it works.

Fireworks has a command called rlaunch for "launching" or running a firework in a workflow from our LaunchPad. Let's see how to use it and use "rapidfire" mode.

!rlaunch --help
FW Echo Test: MP Workshop
usage: rlaunch [-h] [-l LAUNCHPAD_FILE] [-w FWORKER_FILE] [-c CONFIG_DIR]
               [--loglvl LOGLVL] [-s]
               {singleshot,rapidfire,multi} ...

This program launches one or more Rockets. A Rocket retrieves a job from the
central database and runs it. The "single-shot" option launches a single
Rocket, whereas the "rapidfire" option loops until all FireWorks are
completed.

positional arguments:
  {singleshot,rapidfire,multi}
                        command
    singleshot          launch a single Rocket
    rapidfire           launch multiple Rockets (loop until all FireWorks
                        complete)
    multi               launches multiple Rockets simultaneously

optional arguments:
  -h, --help            show this help message and exit
  -l LAUNCHPAD_FILE, --launchpad_file LAUNCHPAD_FILE
                        path to launchpad file
  -w FWORKER_FILE, --fworker_file FWORKER_FILE
                        path to fworker file
  -c CONFIG_DIR, --config_dir CONFIG_DIR
                        path to a directory containing the config file (used
                        if -l, -w unspecified)
  --loglvl LOGLVL       level to print log messages
  -s, --silencer        shortcut to mute log messages

!rlaunch rapidfire
FW Echo Test: MP Workshop
2021-08-10 02:26:35,535 INFO Hostname/IP lookup (this will take a few seconds)
2021-08-10 02:26:36,872 INFO Created new dir /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593
2021-08-10 02:26:36,872 INFO Launching Rocket
2021-08-10 02:26:36,893 INFO RUNNING fw_id: 1 in directory: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593
2021-08-10 02:26:36,900 INFO Task started: FileWriteTask.
2021-08-10 02:26:36,900 INFO Task completed: FileWriteTask 
2021-08-10 02:26:36,902 INFO Task started: {{atomate.vasp.firetasks.write_inputs.WriteVaspFromIOSet}}.
2021-08-10 02:26:37,023 INFO Task completed: {{atomate.vasp.firetasks.write_inputs.WriteVaspFromIOSet}} 
2021-08-10 02:26:37,026 INFO Task started: {{atomate.vasp.firetasks.run_calc.RunVaspFake}}.
2021-08-10 02:26:37,027 INFO atomate.vasp.firetasks.run_calc RunVaspFake: verified inputs successfully
2021-08-10 02:26:37,032 INFO atomate.vasp.firetasks.run_calc RunVaspFake: ran fake VASP, generated outputs
2021-08-10 02:26:37,032 INFO Task completed: {{atomate.vasp.firetasks.run_calc.RunVaspFake}} 
2021-08-10 02:26:37,034 INFO Task started: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}}.
2021-08-10 02:26:37,034 INFO Task completed: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}} 
2021-08-10 02:26:37,036 INFO Task started: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}}.
2021-08-10 02:26:37,036 INFO atomate.vasp.firetasks.parse_outputs PARSING DIRECTORY: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593
2021-08-10 02:26:37,036 INFO atomate.vasp.drones Getting task doc for base dir :/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/pymatgen/io/vasp/inputs.py:1792: UnknownPotcarWarning: POTCAR with symbol Si has metadata that does not match                          any VASP POTCAR known to pymatgen. The data in this                          POTCAR is known to match the following functionals:                          ['PBE']
  warnings.warn(
2021-08-10 02:26:37,584 INFO atomate.vasp.drones Post-processing dir:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593
2021-08-10 02:26:37,584 WARNING atomate.vasp.drones Transformations file does not exist.
2021-08-10 02:26:37,585 INFO atomate.vasp.drones Post-processed /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593
2021-08-10 02:26:37,630 INFO atomate.utils.database Inserting fv-az154-255.kzav01uq0i3u1f1hch3ggm0mbb.bx.internal.cloudapp.net:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593 with taskid = 1
2021-08-10 02:26:37,637 INFO atomate.vasp.firetasks.parse_outputs Finished parsing with task_id: 1
2021-08-10 02:26:37,637 INFO Task completed: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}} 
2021-08-10 02:26:37,652 INFO Rocket finished

Let's check on our workflow in our LaunchPad to see how it has changed after launching one firework.

lp.get_wf_summary_dict(fw_id=1)
{'state': 'COMPLETED',
 'name': 'Si',
 'created_on': datetime.datetime(2021, 8, 10, 2, 26, 34, 316000),
 'updated_on': datetime.datetime(2021, 8, 10, 2, 26, 37, 646000),
 'states': OrderedDict([('Si-structure optimization--1', 'COMPLETED')]),
 'launch_dirs': OrderedDict([('Si-structure optimization--1',
               ['/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-36-872593'])])}

Great! We can see the state of the one firework in our workflow has changed to COMPLETED and now the workflow is done.

Now let's try running the more complicated bandstructure workflow which has four fireworks. First let's add the workflow to our LaunchPad and look at its summary dictionary.

lp.add_wf(bs_wf)
2021-08-10 02:26:38,601 INFO Added a workflow. id_map: {-5: 2, -4: 3, -3: 4, -2: 5}

{-5: 2, -4: 3, -3: 4, -2: 5}
lp.get_wf_summary_dict(fw_id=2)
{'state': 'READY',
 'name': 'Si',
 'created_on': datetime.datetime(2021, 8, 10, 2, 26, 34, 328000),
 'updated_on': datetime.datetime(2021, 8, 10, 2, 26, 34, 328000),
 'states': OrderedDict([('Si-nscf line--2', 'WAITING'),
              ('Si-nscf uniform--3', 'WAITING'),
              ('Si-static--4', 'WAITING'),
              ('Si-structure optimization--5', 'READY')]),
 'launch_dirs': OrderedDict([('Si-nscf line--2', []),
              ('Si-nscf uniform--3', []),
              ('Si-static--4', []),
              ('Si-structure optimization--5', [])])}

Now let's move forward with running the workflow. Note that if the --nlaunches flag is not used, rlaunch rapidfire will continue to launch more fireworks from the LaunchPad until no "READY" fireworks remain. This is convenient for our case because we have 4 fireworks in our workflow that need to run.

!rlaunch rapidfire 
FW Echo Test: MP Workshop
2021-08-10 02:26:39,031 INFO Hostname/IP lookup (this will take a few seconds)
2021-08-10 02:26:40,362 INFO Created new dir /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793
2021-08-10 02:26:40,363 INFO Launching Rocket
2021-08-10 02:26:40,383 INFO RUNNING fw_id: 5 in directory: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793
2021-08-10 02:26:40,390 INFO Task started: FileWriteTask.
2021-08-10 02:26:40,390 INFO Task completed: FileWriteTask 
2021-08-10 02:26:40,392 INFO Task started: {{atomate.vasp.firetasks.write_inputs.WriteVaspFromIOSet}}.
2021-08-10 02:26:40,515 INFO Task completed: {{atomate.vasp.firetasks.write_inputs.WriteVaspFromIOSet}} 
2021-08-10 02:26:40,517 INFO Task started: {{atomate.vasp.firetasks.run_calc.RunVaspFake}}.
2021-08-10 02:26:40,518 INFO atomate.vasp.firetasks.run_calc RunVaspFake: verified inputs successfully
2021-08-10 02:26:40,523 INFO atomate.vasp.firetasks.run_calc RunVaspFake: ran fake VASP, generated outputs
2021-08-10 02:26:40,523 INFO Task completed: {{atomate.vasp.firetasks.run_calc.RunVaspFake}} 
2021-08-10 02:26:40,526 INFO Task started: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}}.
2021-08-10 02:26:40,526 INFO Task completed: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}} 
2021-08-10 02:26:40,528 INFO Task started: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}}.
2021-08-10 02:26:40,528 INFO atomate.vasp.firetasks.parse_outputs PARSING DIRECTORY: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793
2021-08-10 02:26:40,528 INFO atomate.vasp.drones Getting task doc for base dir :/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/pymatgen/io/vasp/inputs.py:1792: UnknownPotcarWarning: POTCAR with symbol Si has metadata that does not match                          any VASP POTCAR known to pymatgen. The data in this                          POTCAR is known to match the following functionals:                          ['PBE']
  warnings.warn(
2021-08-10 02:26:41,083 INFO atomate.vasp.drones Post-processing dir:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793
2021-08-10 02:26:41,084 WARNING atomate.vasp.drones Transformations file does not exist.
2021-08-10 02:26:41,084 INFO atomate.vasp.drones Post-processed /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793
2021-08-10 02:26:41,091 INFO atomate.utils.database Inserting fv-az154-255.kzav01uq0i3u1f1hch3ggm0mbb.bx.internal.cloudapp.net:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793 with taskid = 2
2021-08-10 02:26:41,098 INFO atomate.vasp.firetasks.parse_outputs Finished parsing with task_id: 2
2021-08-10 02:26:41,099 INFO Task completed: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}} 
2021-08-10 02:26:41,115 INFO Rocket finished
2021-08-10 02:26:41,118 INFO Created new dir /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046
2021-08-10 02:26:41,118 INFO Launching Rocket
2021-08-10 02:26:41,129 INFO RUNNING fw_id: 4 in directory: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046
2021-08-10 02:26:41,132 INFO Task started: FileWriteTask.
2021-08-10 02:26:41,132 INFO Task completed: FileWriteTask 
2021-08-10 02:26:41,133 INFO Task started: {{atomate.vasp.firetasks.glue_tasks.CopyVaspOutputs}}.
2021-08-10 02:26:41,141 INFO Task completed: {{atomate.vasp.firetasks.glue_tasks.CopyVaspOutputs}} 
2021-08-10 02:26:41,142 INFO Task started: {{atomate.vasp.firetasks.write_inputs.WriteVaspStaticFromPrev}}.
2021-08-10 02:26:41,390 INFO Task completed: {{atomate.vasp.firetasks.write_inputs.WriteVaspStaticFromPrev}} 
2021-08-10 02:26:41,393 INFO Task started: {{atomate.vasp.firetasks.run_calc.RunVaspFake}}.
2021-08-10 02:26:41,393 INFO atomate.vasp.firetasks.run_calc RunVaspFake: verified inputs successfully
2021-08-10 02:26:41,405 INFO atomate.vasp.firetasks.run_calc RunVaspFake: ran fake VASP, generated outputs
2021-08-10 02:26:41,405 INFO Task completed: {{atomate.vasp.firetasks.run_calc.RunVaspFake}} 
2021-08-10 02:26:41,407 INFO Task started: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}}.
2021-08-10 02:26:41,407 INFO Task completed: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}} 
2021-08-10 02:26:41,409 INFO Task started: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}}.
2021-08-10 02:26:41,409 INFO atomate.vasp.firetasks.parse_outputs PARSING DIRECTORY: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046
2021-08-10 02:26:41,409 INFO atomate.vasp.drones Getting task doc for base dir :/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046
2021-08-10 02:26:41,964 INFO atomate.vasp.drones Post-processing dir:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046
2021-08-10 02:26:41,964 WARNING atomate.vasp.drones Transformations file does not exist.
2021-08-10 02:26:42,122 INFO atomate.vasp.drones Post-processed /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046
2021-08-10 02:26:42,127 INFO atomate.utils.database Inserting fv-az154-255.kzav01uq0i3u1f1hch3ggm0mbb.bx.internal.cloudapp.net:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046 with taskid = 3
2021-08-10 02:26:42,132 INFO atomate.vasp.firetasks.parse_outputs Finished parsing with task_id: 3
2021-08-10 02:26:42,132 INFO Task completed: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}} 
2021-08-10 02:26:42,146 INFO Rocket finished
2021-08-10 02:26:42,149 INFO Created new dir /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589
2021-08-10 02:26:42,149 INFO Launching Rocket
2021-08-10 02:26:42,160 INFO RUNNING fw_id: 2 in directory: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589
2021-08-10 02:26:42,163 INFO Task started: FileWriteTask.
2021-08-10 02:26:42,164 INFO Task completed: FileWriteTask 
2021-08-10 02:26:42,165 INFO Task started: {{atomate.vasp.firetasks.glue_tasks.CopyVaspOutputs}}.
2021-08-10 02:26:42,226 INFO Task completed: {{atomate.vasp.firetasks.glue_tasks.CopyVaspOutputs}} 
2021-08-10 02:26:42,228 INFO Task started: {{atomate.vasp.firetasks.write_inputs.WriteVaspNSCFFromPrev}}.
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/pymatgen/symmetry/kpath.py:163: UserWarning: 'magmom' entry found in site properties but will be ignored                   for the Setyawan and Curtarolo convention.
  warn(
/usr/share/miniconda/envs/workshop/lib/python3.9/site-packages/pymatgen/symmetry/kpath.py:179: UserWarning: The input structure does not match the expected standard primitive! The path can be incorrect. Use at your own risk.
  warn(
2021-08-10 02:26:42,606 INFO Task completed: {{atomate.vasp.firetasks.write_inputs.WriteVaspNSCFFromPrev}} 
2021-08-10 02:26:42,608 INFO Task started: {{atomate.vasp.firetasks.run_calc.RunVaspFake}}.
2021-08-10 02:26:42,609 INFO atomate.vasp.firetasks.run_calc RunVaspFake: verified inputs successfully
2021-08-10 02:26:42,614 INFO atomate.vasp.firetasks.run_calc RunVaspFake: ran fake VASP, generated outputs
2021-08-10 02:26:42,614 INFO Task completed: {{atomate.vasp.firetasks.run_calc.RunVaspFake}} 
2021-08-10 02:26:42,616 INFO Task started: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}}.
2021-08-10 02:26:42,616 INFO Task completed: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}} 
2021-08-10 02:26:42,617 INFO Task started: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}}.
2021-08-10 02:26:42,618 INFO atomate.vasp.firetasks.parse_outputs PARSING DIRECTORY: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589
2021-08-10 02:26:42,618 INFO atomate.vasp.drones Getting task doc for base dir :/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589
2021-08-10 02:26:43,195 INFO atomate.vasp.drones Post-processing dir:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589
2021-08-10 02:26:43,195 WARNING atomate.vasp.drones Transformations file does not exist.
2021-08-10 02:26:43,264 INFO atomate.vasp.drones Post-processed /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589
2021-08-10 02:26:43,269 INFO atomate.utils.database Inserting fv-az154-255.kzav01uq0i3u1f1hch3ggm0mbb.bx.internal.cloudapp.net:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589 with taskid = 4
2021-08-10 02:26:43,323 INFO atomate.vasp.firetasks.parse_outputs Finished parsing with task_id: 4
2021-08-10 02:26:43,323 INFO Task completed: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}} 
2021-08-10 02:26:43,334 INFO Rocket finished
2021-08-10 02:26:43,337 INFO Created new dir /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588
2021-08-10 02:26:43,337 INFO Launching Rocket
2021-08-10 02:26:43,348 INFO RUNNING fw_id: 3 in directory: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588
2021-08-10 02:26:43,351 INFO Task started: FileWriteTask.
2021-08-10 02:26:43,352 INFO Task completed: FileWriteTask 
2021-08-10 02:26:43,353 INFO Task started: {{atomate.vasp.firetasks.glue_tasks.CopyVaspOutputs}}.
2021-08-10 02:26:43,414 INFO Task completed: {{atomate.vasp.firetasks.glue_tasks.CopyVaspOutputs}} 
2021-08-10 02:26:43,417 INFO Task started: {{atomate.vasp.firetasks.write_inputs.WriteVaspNSCFFromPrev}}.
2021-08-10 02:26:43,728 INFO Task completed: {{atomate.vasp.firetasks.write_inputs.WriteVaspNSCFFromPrev}} 
2021-08-10 02:26:43,731 INFO Task started: {{atomate.vasp.firetasks.run_calc.RunVaspFake}}.
2021-08-10 02:26:43,731 INFO atomate.vasp.firetasks.run_calc RunVaspFake: verified inputs successfully
2021-08-10 02:26:43,738 INFO atomate.vasp.firetasks.run_calc RunVaspFake: ran fake VASP, generated outputs
2021-08-10 02:26:43,738 INFO Task completed: {{atomate.vasp.firetasks.run_calc.RunVaspFake}} 
2021-08-10 02:26:43,740 INFO Task started: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}}.
2021-08-10 02:26:43,740 INFO Task completed: {{atomate.common.firetasks.glue_tasks.PassCalcLocs}} 
2021-08-10 02:26:43,742 INFO Task started: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}}.
2021-08-10 02:26:43,742 INFO atomate.vasp.firetasks.parse_outputs PARSING DIRECTORY: /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588
2021-08-10 02:26:43,742 INFO atomate.vasp.drones Getting task doc for base dir :/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588
2021-08-10 02:26:44,086 INFO atomate.vasp.drones Post-processing dir:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588
2021-08-10 02:26:44,086 WARNING atomate.vasp.drones Transformations file does not exist.
2021-08-10 02:26:44,250 INFO atomate.vasp.drones Post-processed /home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588
2021-08-10 02:26:44,256 INFO atomate.utils.database Inserting fv-az154-255.kzav01uq0i3u1f1hch3ggm0mbb.bx.internal.cloudapp.net:/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588 with taskid = 5
2021-08-10 02:26:44,307 INFO atomate.vasp.firetasks.parse_outputs Finished parsing with task_id: 5
2021-08-10 02:26:44,308 INFO Task completed: {{atomate.vasp.firetasks.parse_outputs.VaspToDb}} 
2021-08-10 02:26:44,319 INFO Rocket finished

Once rlaunch rapidfire has finished running, now we can check to see if this workflow completed successfully.

lp.get_wf_summary_dict(fw_id=2)
{'state': 'COMPLETED',
 'name': 'Si',
 'created_on': datetime.datetime(2021, 8, 10, 2, 26, 34, 328000),
 'updated_on': datetime.datetime(2021, 8, 10, 2, 26, 44, 315000),
 'states': OrderedDict([('Si-nscf line--2', 'COMPLETED'),
              ('Si-nscf uniform--3', 'COMPLETED'),
              ('Si-static--4', 'COMPLETED'),
              ('Si-structure optimization--5', 'COMPLETED')]),
 'launch_dirs': OrderedDict([('Si-nscf line--2',
               ['/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-42-149589']),
              ('Si-nscf uniform--3',
               ['/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-43-337588']),
              ('Si-static--4',
               ['/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-41-118046']),
              ('Si-structure optimization--5',
               ['/home/runner/work/workshop/workshop/workshop/lessons/05_automated_dft/launcher_2021-08-10-02-26-40-362793'])])}

Fireworks also has a command called qlaunch to automatically submit jobs to the supercomputer to run. Upon the job starting on the supercomputer, rlaunch from fireworks will be called thus running fireworks with supercomputer resources. qlaunch is the primary command used by users in the command-line interface on supercomputers.