Running EOS Workflows

Introduction

Equations of state are common and useful in many aspects of computational materials science. This tutorial will quickly guide you through customizing and running a preset EOS workflow.

Objectives

  • Run an atomate preset workflow for an EOS using Python
  • Query for the calculation result in your database
  • Visualize the results with matplotlib

Prerequisites

In order for you to complete this tutorial you need

  • A working installation of atomate
  • A text editor

Equation of State Workflows

An equation of state (EOS) relates state variables to each other. In first-principles calculations at 0K, it is often useful to understand the how the energy of a crystal changes when the crystal volume changes. Here there are instructions for running a workflow to calculate the EOS for fcc Al using both YAML format (text) files and Python programming. Both interfaces can produce equivalent results, so you can use either or both depending on the situation. To calculate the EOS, we need to (i) optimize our ground state structure, (ii) systematically change the crystal volume and calculate the resulting energies, and finally (iii) fit these energies and volumes to one of several EOS functional forms.

Elastic Tensor Workflow

Atomate elastic tensor workflow. This uses the same pattern as the EOS workflow, but the analysis step (final Firework) calculates the elastic tensor instead of an EOS.

Running an Equation of State Workflow

Setup

Make sure you have completed the installation tutorial. Next, create a folder on your HPC resource for this tutorial. It can be located anywhere. You’ll keep all of the files for this tutorial there.

If you do not already have important prior results in your atomate environment, start fresh by running:

``lpad reset``

Warning

This will reset all of your previous Fireworks and Workflows in your LaunchPad. Do not do this if you have actual results that you want to keep!

If you do not or want to reset your LaunchPad, you can set up a different database to use for tutorials or simply accept mixing your previous results and workflows with the contents of this tutorial in your database.

Use Python to generate and add the workflow

We’ll use fcc Al as a simple example and get the structure from the Materials Project. This requires that you set up an API key in your .pmgrc.yaml. In the installation tutorial, you set up your FW_config.yaml, you indicated the atomate Fireworks can be found at atomate.vasp.fireworks. Similarly, atomate preset workflows can be imported from atomate.vasp.workflows.presets.core, which thinly wraps the base workflows (atomate.vasp.workflows.base) allowing for common settings to be changed with configuration dictionaries. The bulk modulus preset workflow will provide a starting point for an EOS. And we can setup the workflow and add it to our LaunchPad ready to run in just a few lines of Python.

Create the workflow script

In the directory you created, make a Python script named eos.py with the following contents:

# Create an EOS from the workflow from the atomate presets
import numpy as np
from pymatgen import MPRester
from fireworks import LaunchPad
from atomate.vasp.workflows.presets.core import wf_bulk_modulus
from atomate.vasp.powerups import add_modify_incar

# get the structure from the Materials Projection
with MPRester() as mpr:
    struct = mpr.get_structure_by_material_id('mp-134')

# set up configuration dictionary
c = {}
# 7 deformations +/- 10% of the equilibrium volume
# note that the 1/3 power is so that we scale each direction by (x+1)^(1/3) and the total volume by (x+1)
c["deformations"] =  [(np.identity(3)*(1+x)**(1.0/3.0)).tolist() for x in np.linspace(-0.1, 0.1, 5)]

# create the Workflow
wf = wf_bulk_modulus(struct, c)

# now we need to set the correct smearing for the optimization, using the add_modify_incar powerup
wf = add_modify_incar(wf, {'incar_update': {'SIGMA': 0.2, 'ISMEAR': 1}}, fw_name_constraint='optimization')

# finally, instatiate the LaunchPad and add the workflow to it
lpad = LaunchPad.auto_load() # loads this based on the FireWorks configuration
lpad.add_wf(wf)

Add workflow to LaunchPad

If you want to add the workflow to your LaunchPad (e.g., you didn’t already go through Option 2 for adding a workflow): from the folder with your POSCAR and eos.py, run the Python script:

python eos.py

Running the workflow

Option 1

Running the workflow the following command will submit a single job to the batch queue configured in my_qadapter.yaml. The job will launch Fireworks from your LaunchPad until all of them have completed or you run out of walltime. This workflow will only take few minutes.

qlaunch singleshot

You can go to the output files from the batch job (*.out and *.error) at the launch directories to make sure everything went well.

Option 2

Since Al is a very easy calculation, we can run this entire workflow in a few minutes on a single core on the login node. This can be valuable for getting quick feedback in this tutorial. You should not be running workflows like this normally and running software like VASP on login nodes is forbidden on some resources.

The easiest way to set this up is to either explicitly set the vasp_cmd parameter in the configuration dictionary to just vasp_std (or whichever your system uses). The default is >>vasp_cmd<<, which looks up the vasp_cmd parameter in your my_fworker.yaml file. That means you could also temporarily make this change in your my_fworker.yaml file. In this case, make sure to set the vasp_cmd without ibrun, mpirun, srun, etc., which would use all of the cores on the login node (many hosts prevent you from running these commands on the login nodes altogether). To run the workflow on the login node, run the following command. Note the use of rlaunch rather than qlaunch.

rlaunch rapidfire

You should see logging text on the progress of each Firetask in your workflow. The Fireworks have successfully finished launching and running, the results should be added to your database and you can move on.

Analyzing an Equation of State Workflow

Querying the results

In the Python preset, we get the nice EOS analysis Firework for free. This is not supported in atwf, so we will extract the data for a simple energy vs. volume curve ourselves. With the PMGDB_DB_FILE varible set in your $HOME/.pmgrc.yaml file as in the installation instructions, we will be querying the database that the db.json file you created describes.

mgdb query --props task_id formula_pretty output.energy_per_atom output.structure.lattice.volume task_label

which will give you an overview of the each Firework you ran. It should look something like

  task_id  formula_pretty      output.energy_per_atom    output.structure.lattice.volume  task_label
---------  ----------------  ------------------------  ---------------------------------  -----------------------------------------------------
        1  Al                                -3.74617                            65.8868  2015-12-30-18-00-00-163825 structure optimization
        2  Al                                -3.69701                            59.2981  2015-12-30-18-00-00-163825 bulk_modulus deformation 0
        3  Al                                -3.73492                            62.5925  2015-12-30-18-00-00-163825 bulk_modulus deformation 1
        4  Al                                -3.74617                            65.8868  2015-12-30-18-00-00-163825 bulk_modulus deformation 2
        5  Al                                -3.73752                            69.1812  2015-12-30-18-00-00-163825 bulk_modulus deformation 3
        6  Al                                -3.71384                            72.4755  2015-12-30-18-00-00-163825 bulk_modulus deformation 4

Now we want to get the results for just our deformations. We add the --crit option to enable searching based on JSON-formatted criteria. Specifically we just want the deformation. By using the --dump option and redirection the results to a JSON file, we can load the results in Python for our analysis. We can also simplify the properties are getting, since we are already aware of the other things.

mgdb query --crit '{"task_label": {"$regex": "deformation"}}' --props output.energy_per_atom output.structure.lattice.volume --dump > eos-results.json

Note

It is important to format your criteria as single quotes on the outside and double quotes on the inside. Double quotes are required for JSON and the single quotes prevent any shell magic that curly braces (‘{‘) usually invoke.

If everything worked, you should have gotten no output, but you should be able to find an eos-results.json with the following content

{"output.structure.lattice.volume": 59.29814953343786, "output.energy_per_atom": -3.69701308}
{"output.structure.lattice.volume": 62.59247826860741, "output.energy_per_atom": -3.7349166475}
{"output.structure.lattice.volume": 65.88683660010845, "output.energy_per_atom": -3.74616541}
{"output.structure.lattice.volume": 69.1811925337604, "output.energy_per_atom": -3.73751932}
{"output.structure.lattice.volume": 72.47551533513209, "output.energy_per_atom": -3.7138362225}

We need to format this file to actual JSON to more easily load the results in Python. Add a “data” property name, extra curly braces and brackets around all of the data and a comma on each line, making the results a list. The file eos-results.json should look like

{"data":
[
{"output.structure.lattice.volume": 59.29814953343786, "output.energy_per_atom": -3.69701308},
{"output.structure.lattice.volume": 62.59247826860741, "output.energy_per_atom": -3.7349166475},
{"output.structure.lattice.volume": 65.88683660010845, "output.energy_per_atom": -3.74616541},
{"output.structure.lattice.volume": 69.1811925337604, "output.energy_per_atom": -3.73751932},
{"output.structure.lattice.volume": 72.47551533513209, "output.energy_per_atom": -3.7138362225}
]
}

Analyzing the results

Finally, we’ll plot the EOS results that we saved in the last section. Simply add the following Python script (eos-analysis.py) to your folder and run it

# eos-analysis.py
import json
import matplotlib
matplotlib.use('Agg') # a little magic for matplotlib to work without a $DISPLAY set
from matplotlib import pyplot as plt

# load the results as JSON
with open('eos-results.json') as f:
    eos_results = json.load(f)

# get the results into lists of volumes and energies
volumes = []
energies = []
for entry in eos_results['data']:
    volumes.append(entry['output.structure.lattice.volume'])
    energies.append(entry['output.energy_per_atom'])

# set up the plot, plot the results, and save them to a file
fig = plt.figure()
ax = fig.gca()
ax.plot(volumes, energies, marker='o', linestyle='')
ax.set_title('Energy vs. Volume for Al')
ax.set_ylabel('Energy per atom (eV)')
ax.set_xlabel('Volume (A^3)')
fig.savefig('eos-energy-volume.png')

If you open the saved figure, eos-energy-volume.png, on your computer you should see the datapoints for your first automated E-V curve plotted!

Alumninum energy vs. volume

Energy vs. volume curve for Al created from the EOS volume deformations.

Conclusion

In this tutorial you learned how run a workflow from in a YAML file without writing any code and to do the same in Python.

We have tried to provide common functionality as preset workflows in Python. Due to some current limitation in the atwf utility, some analysis tasks like the EOS Firework cannot currently be expressed in the YAML, so complete access to full preset workflows can only be achieved in Python.

To see what preset workflows can be run, see the documentation that includes them at atomate.vasp.workflows.presets. They can be set up the same way as in this tutorial.

Eventually you may want to create your own workflows that you can use and distribute. The Creating Workflows article is a guide for writing custom workflows in Python.