This first part is only needed as we have to mock VASP here as we cannot run it directly in a jupyter notebook:

import warnings

from mock_vasp import TEST_DIR, mock_vasp

ref_paths = {
    "phonon static 1/1": "Si_phonons_3/phonon_static_1_1",
    "static": "Si_phonons_3/static",
    "tight relax 1": "Si_phonons_3/tight_relax_1",
    "tight relax 2": "Si_phonons_3/tight_relax_2",
    "dielectric": "Si_phonons_3/dielectric",
}

Phonon Workflow Tutorial with VASP

This tutorial has been written based on a previous version from Aakash Naik.

Background

The Phonon workflow is based on the finite displacement approach as implemented in Phonopy.

If you want to read more about Phonopy, please read Togo’s paper: https://doi.org/10.7566/JPSJ.92.012001

Let’s run the workflow

Now, we load a structure and other important functions and classes for running the phonon workflow.

from jobflow import JobStore, run_locally
from maggma.stores import MemoryStore
from pymatgen.core import Structure

from atomate2.vasp.flows.phonons import PhononMaker

warnings.filterwarnings("ignore")

job_store = JobStore(MemoryStore(), additional_stores={"data": MemoryStore()})
si_structure = Structure.from_file(TEST_DIR / "structures" / "Si.cif")

Then one can use the PhononMaker to generate a Flow. For testing here, we are choosing a very small supercell length (min_length). Ideally, a larger cell should be chosen. For non-metallic systems with more than one element, one might need to add the non-analytical term correction considering very long-ranging forces by computing the BORN charges with the born_maker. Of course, the structure should also be relaxed in advance with the bulk_relax_maker. Please make sure this is done very accurately.

flow = PhononMaker(
    min_length=3.0,
    use_symmetrized_structure=None,
    generate_frequencies_eigenvectors_kwargs={"tstep": 100},
    create_thermal_displacements=True,
    store_force_constants=True,
    born_maker=None,
).make(si_structure)

The phonon run will first perform a bulk relaxation, then the displacements are generated and run. As we currently don’t have a way to compute BORN charges with such potentials, a non-analytical term correction is not performed here. We can visualize the flow first.

flow.draw_graph().show()

We now run the flow with run_locally. We mock the run here. Normally, you would simply use run_locally without the with mock_vasp

with mock_vasp(ref_paths=ref_paths) as mf:
    run_locally(
        flow,
        create_folders=True,
        ensure_success=True,
        raise_immediately=True,
        store=job_store,
    )
from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine
from pymatgen.phonon.dos import PhononDos
from pymatgen.phonon.plotter import PhononBSPlotter, PhononDosPlotter

job_store.connect()

result = job_store.query_one(
    {"name": "generate_frequencies_eigenvectors"},
    properties=[
        "output.phonon_dos",
        "output.phonon_bandstructure",
    ],
    load=True,
    sort={"completed_at": -1},  # to get the latest computation
)
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()

One can run the same workflow with a forcefield as well. Here, we cannot consider BORN charges yet as there is no forcefield equivalent. You can find this tutorial in the force field tutorials.