The tutorial has been written by A. Naik and J. George. Suggestions and corrections by J.Bustamante have been included. (Federal Institute for Materials Research and Testing in Germany in Berlin, Friedrich Schiller University).
Hello! 👋 Welcome to the atomate2 phonon workflow
tutorial. This tutorial will introduce you to how to use the phonon workflow
implemented in the atomate2 python package and to access results from the database. After completing this tutorial, you should be able to use the phonon workflow
for your own computations.
Before starting, you will want the following softwares available and ready to use:
A conda environment with python (3.9 or higher) and following packages needs to be installed:
pip install atomate2[phonons,forcefields]
pip install fireworks
Additionally, you should
some knowledge of phonons (this reference can help you to get familiarize with the topic https://onlinelibrary.wiley.com/doi/10.1002/anie.200906780)
familiar with CHGNet a universal neural network potential (Check this reference : https://doi.org/10.48550/arXiv.2302.14231)
🎺 Let's get started. 🎺
We perform the phonon calculation (Vibrational Properties of Crystals) using the Finite Displacement method
. In this approximation, we generate a supercell of the structure, then displace an atom from the symmetrically allowed position, and calculate the forces on all other atoms. Before performing the phonon calculations, we need to ensure the lattice structure is well optimized.
Workflow only needs structure as input. The following steps are performed sequentially in this workflow:
from mp_api.client import MPRester
from fireworks import LaunchPad
from jobflow import SETTINGS
from jobflow import run_locally
from jobflow.managers.fireworks import flow_to_workflow
from atomate2.vasp.powerups import update_user_incar_settings, update_user_kpoints_settings
from atomate2.vasp.jobs.base import BaseVaspMaker
from atomate2.vasp.sets.core import StaticSetGenerator
from pymatgen.core.structure import Structure
from atomate2.vasp.flows.phonons import PhononMaker
Before we proceed, let's quickly look at the parameters you can alter when instantiating a phonon calculation workfolow using PhononMaker
:
name: str # Name of the flows produced by this maker
sym_reduce: bool = True # Whether to reduce the number of deformations using symmetry
symprec : float = 1e-4 # Symmetry precision to use in the reduction of symmetry to find the primitive/conventional cell use_primitive_standard_structure, use_conventional_standard_structure and to handle all symmetry-related tasks in phonopy
displacement: float = 0.01 # displacement distance for phonons
min_length: float = 20 # min length in Å of the supercell that will be built
prefer_90_degrees: bool = True #if set to True, supercell algorithm will first try to find a supercell with 3 90 degree angles
use_symmetrized_structure: str | None = None # allowed strings: "primitive", "conventional", None
# - "primitive" will enforce to start the phonon computation from the primitive standard structure according to Setyawan, W., & Curtarolo, S. (2010). High-throughput electronic band structure calculations: Challenges and tools. Computational Materials Science, 49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010. This makes it possible to use certain k-path definitions with this workflow. Otherwise, we must rely on seekpath
# - "conventional" will enforce to start the phonon computation from the conventional standard structure according to Setyawan, W., & Curtarolo, S. (2010). High-throughput electronic band structure calculations: Challenges and tools. Computational Materials Science, 49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010. We will however use seekpath and primitive structures as determined by from phonopy to compute the phonon band structure
bulk_relax_maker: BaseVaspMaker | None = field(
default_factory=lambda: DoubleRelaxMaker.from_relax_maker(TightRelaxMaker())
) # Maker used to perform a tight relaxation on the bulk. Set to ``None`` to skip the bulk relaxation
static_energy_maker: BaseVaspMaker | None = field(
default_factory=lambda: StaticMaker(input_set_generator=StaticSetGenerator(auto_ispin=True))
) # Maker used to perform the computation of the DFT energy on the bulk. Set to ``None`` to skip the static energy computation
born_maker: BaseVaspMaker | None = field(default_factory=DielectricMaker) # Maker used to compute the BORN charges
phonon_displacement_maker : BaseVaspMaker | None = field(
default_factory=PhononDisplacementMaker
)# Maker used to compute the forces for a supercell
create_thermal_displacements: bool = True # Determines whether to compute thermal_displacement_matrices
kpath_scheme:str = "seekpath"
# Scheme to generate kpoints. Please be aware that you can only use seekpath with any kind of cell. Otherwise, please use the standard primitive structure. Available schemes are: "seekpath", "hinuma", "setyawan_curtarolo", "latimer_munro". "seekpath" and "hinuma" are the same definition but seekpath can be used with any kind of unit cell as it relies on phonopy to handle the relationship to the primitive cell and not pymatgen
store_force_constants:bool = True # if True, force constants will be stored
As you can see, most of the parameters have already set defaults, one can now simply load the structure you have locally into Structure
object of pymatgen or retrieve a structure from materials project database. (You need to have your unique api key from your account)
Here we will get structure from materials project database:
mpid="mp-7000"
mr = MPRester(api_key='my_api_key')
struct = mr.get_structure_by_material_id(mpid)
Here we will be skipping born effective charge computations and will instantiate a phonon workflow:
phonon_flow = PhononMaker(born_maker=None).make(structure=struct)
One can also use power ups for setting up some VASP calculations global parameters (Optional).
Note:
One can modify basically all the global VASP settings, except NPAR
if born charge corrections are being performed during phonon runs. In such case, its better to change VASP maker configurations of specific jobs using name_filter
argrument of update_user_incar_settings
.
# phonon_flow = update_user_incar_settings(phonon_flow, {"NPAR": 4})
# phonon_flow = update_user_kpoints_settings(phonon_flow,{"grid_density": 1})
You can also specify workers for different jobs based on job names in the flow (For eg.:- Structural optimzation job could need difference resources, than static supercell, or phonopy run jobs).
Check out this useful resource if not familiar how to do this Running Jobflow with FireWorks.
#for job, _ in phonon_flow.iterflow():
# config = {"manager_config": {"_fworker": "worker"}}
# if "run_phonon" in job.name:
# job.update_config(config)
The code block below will convert the jobflow object to fireworks workflow via flow_to_workflow
utility provided by jobflow
:
wf = flow_to_workflow(phonon_flow)
lpad = LaunchPad.auto_load() #loads existing mongoDB database
lpad.add_wf(wf) # adds jobs to the workflow
Use the following command in your shell to start workflow using fireworks:
qlaunch -r rapidfire -m 3
Altertnatively, you can start the workflow locally that does not require mongoDB by using following command:
# run the job
run_locally(phonon_flow, create_folders=True, store=SETTINGS.JOB_STORE)
Once the calculations are finished we can access the results from the jobstore. Below is a snippet to access phonon dos and bandstructure and get plots of the same. Check the Phonon workflow schema PhononBSDOSDoc to see what all data can be accessed from the database.
from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine
from pymatgen.phonon.dos import PhononDos
from pymatgen.phonon.plotter import PhononBSPlotter, PhononDosPlotter
store = SETTINGS.JOB_STORE
store.connect()
result = store.query_one(
{"name": "generate_frequencies_eigenvectors"},
properties=[
"output.phonon_dos",
"output.phonon_bandstructure",
],
load=True,
)
ph_bs = PhononBandStructureSymmLine.from_dict(result['output']['phonon_bandstructure']) # get pymatgen bandstructure object
ph_dos = PhononDos.from_dict(result['output']['phonon_dos']) # get pymatgen phonon dos object
# initialize dos plotter and visualize dos plot
dos_plot = PhononDosPlotter()
dos_plot.add_dos(label='a', dos=ph_dos)
dos_plot.get_plot();
# initialize Phonon bandstructure plotter and visualize band structure plot
bs_plot = PhononBSPlotter(bs=ph_bs)
bs_plot.get_plot();
## import the phonon flow maker that uses CHGNet ML potential to perform static computations
from atomate2.forcefields.flows.phonons import PhononMaker as FFPhononMaker
The the parameters you can alter when instantiating a Phonon calculation workfolow using forcefield PhononMaker
are similar to the VASP based PhononMaker, please refer the following link for more details PhononMaker.
# we use the same structure ( mp-7000) here and instantiate the workflow
phonon_flow = FFPhononMaker().make(structure=struct)
# you can run this flow directly in the notebook itself
run_locally(phonon_flow, create_folders=True, store=SETTINGS.JOB_STORE)