Grüneisen Workflow (VASP)

This part is mocking the VASP calculation to facilitate the execution in the notebook.

import warnings

from mock_vasp import TEST_DIR, mock_vasp

ref_paths = {
    "tight relax 1": "Si_gruneisen_tutorial/tight_relax_1_0",
    "tight relax 2": "Si_gruneisen_tutorial/tight_relax_2_1",
    "tight relax 1 plus": "Si_gruneisen_tutorial/tight_relax_1_plus_3",
    "tight relax 2 plus": "Si_gruneisen_tutorial/tight_relax_2_plus_5",
    "tight relax 1 minus": "Si_gruneisen_tutorial/tight_relax_1_minus_4",
    "tight relax 2 minus": "Si_gruneisen_tutorial/tight_relax_2_minus_6",
    "dft phonon static 1/1 ground": "Si_gruneisen_tutorial/dft_phonon_static_1_1_ground_24",
    "dft phonon static 1/1 plus": "Si_gruneisen_tutorial/dft_phonon_static_1_1_plus_26",
    "dft phonon static 1/1 minus": "Si_gruneisen_tutorial/dft_phonon_static_1_1_minus_28",
}

Let’s load all required Makers to set up the calculation settings for VASP.

from atomate2.vasp.flows.core import DoubleRelaxMaker
from atomate2.vasp.jobs.core import TightRelaxMaker
from atomate2.vasp.jobs.phonons import PhononDisplacementMaker
from atomate2.vasp.sets.core import StaticSetGenerator, TightRelaxSetGenerator
from jobflow import JobStore, run_locally
from maggma.stores import MemoryStore
from pymatgen.core import Structure

from atomate2.vasp.flows.gruneisen import GruneisenMaker, PhononMaker

warnings.filterwarnings("ignore")

job_store = JobStore(
    MemoryStore(),
    additional_stores={"data": MemoryStore()},
)
si_structure = Structure.from_file(TEST_DIR / "structures" / "Si_diamond.cif")
phonon_displacement_maker = PhononDisplacementMaker(
    name="dft phonon static",
    run_vasp_kwargs={"handlers": ()},
    input_set_generator=StaticSetGenerator(
        user_incar_settings={
            "GGA": "PE",
            "IBRION": -1,
            "ISPIN": 1,
            "ISMEAR": 0,
            "ISIF": 3,
            "ENCUT": 700,
            "EDIFF": 1e-7,
            "LAECHG": False,
            "LREAL": False,
            "ALGO": "Normal",
            "NSW": 0,
            "LCHARG": False,
            "LWAVE": False,
            "LVTOT": False,
            "LORBIT": None,
            "LOPTICS": False,
            "SIGMA": 0.05,
            "ISYM": 0,
            "KSPACING": 0.1,
            "NPAR": 4,
        },
        auto_ispin=False,
    ),
)
phonon_bulk_relax_maker_isif3 = DoubleRelaxMaker.from_relax_maker(
    TightRelaxMaker(
        run_vasp_kwargs={"handlers": ()},
        input_set_generator=TightRelaxSetGenerator(
            user_incar_settings={
                "GGA": "PE",
                "ISPIN": 1,
                "KSPACING": 0.1,
                # "EDIFFG": 1e-5,
                "ALGO": "Normal",
                "LAECHG": False,
                "ISMEAR": 0,
                "ENCUT": 700,
                "IBRION": 1,
                "ISYM": 0,
                "SIGMA": 0.05,
                "LCHARG": False,
                "LWAVE": False,
                "LVTOT": False,
                "LORBIT": None,
                "LOPTICS": False,
                "LREAL": False,
                "ISIF": 3,
                "NPAR": 4,
            }
        ),
    )
)
phonon_bulk_relax_maker_isif4 = DoubleRelaxMaker.from_relax_maker(
    TightRelaxMaker(
        run_vasp_kwargs={"handlers": ()},
        input_set_generator=TightRelaxSetGenerator(
            user_incar_settings={
                "GGA": "PE",
                "ISPIN": 1,
                "KSPACING": 0.1,
                # "EDIFFG": 1e-5,
                "ALGO": "Normal",
                "LAECHG": False,
                "ISMEAR": 0,
                "ENCUT": 700,
                "IBRION": 1,
                "ISYM": 0,
                "SIGMA": 0.05,
                "LCHARG": False,
                "LWAVE": False,
                "LVTOT": False,
                "LORBIT": None,
                "LOPTICS": False,
                "LREAL": False,
                "ISIF": 4,
                "NPAR": 4,
            }
        ),
    )
)

Then one can use the GruneisenMaker to generate a Flow.

flow = GruneisenMaker(
    symprec=1e-4,
    bulk_relax_maker=phonon_bulk_relax_maker_isif3,
    const_vol_relax_maker=phonon_bulk_relax_maker_isif4,
    phonon_maker=PhononMaker(
        generate_frequencies_eigenvectors_kwargs={
            "tmin": 0,
            "tmax": 1000,
            "tstep": 10,
        },
        min_length=10,
        bulk_relax_maker=None,
        born_maker=None,
        static_energy_maker=None,
        phonon_displacement_maker=phonon_displacement_maker,
    ),
).make(structure=si_structure)
flow.draw_graph().show()

We can then run the code 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,
    )

Let’s then analyze outputs from the workflow.

job_store.connect()

result = job_store.query_one(
    {"name": "compute_gruneisen_param"},
    properties=[
        "output.gruneisen_band_structure",
        "output.gruneisen_parameter",
    ],
    load=True,
    sort={"completed_at": -1},  # to get the latest computation
)
from pymatgen.phonon.gruneisen import GruneisenPhononBandStructureSymmLine
from pymatgen.phonon.plotter import GruneisenPhononBSPlotter

bs = GruneisenPhononBandStructureSymmLine.from_dict(
    result["output"]["gruneisen_band_structure"]
)
plt = GruneisenPhononBSPlotter(bs=bs)
plt.get_plot_gs(plot_ph_bs_with_gruneisen=True)