Source code for atomate2.vasp.flows.matpes

"""
Module defining MatPES flows.

In case of questions, consult @janosh or @esoteric-ephemera. Makes PBE + r2SCAN
cheaper than running both separately.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from jobflow import Flow, Maker

from atomate2.vasp.jobs.matpes import MatPesGGAStaticMaker, MatPesMetaGGAStaticMaker
from atomate2.vasp.sets.matpes import MatPesGGAStaticSetGenerator

if TYPE_CHECKING:
    from pathlib import Path

    from pymatgen.core import Structure


[docs] @dataclass class MatPesStaticFlowMaker(Maker): """MatPES flow doing a GGA static followed by meta-GGA static. Uses the GGA WAVECAR to speed up electronic convergence on the meta-GGA static. Parameters ---------- name : str Name of the flows produced by this maker. static1 : .BaseVaspMaker Maker to generate the first VASP static. static2 : .BaseVaspMaker Maker to generate the second VASP static. static3 : .BaseVaspMaker or None Maker to generate the optional third VASP static. Defaults to GGA static with +U corrections if structure contains elements with +U corrections, else to None. """ name: str = "MatPES static flow" static1: Maker | None = field( default_factory=lambda: MatPesGGAStaticMaker( input_set_generator=MatPesGGAStaticSetGenerator( # write WAVECAR so we can use as pre-conditioned starting point for # static2/3 user_incar_settings={"LWAVE": True} ), ) ) static2: Maker = field( default_factory=lambda: MatPesMetaGGAStaticMaker( # start from pre-conditioned WAVECAR from static1 to speed up convergence # could copy CHGCAR too but is redundant since VASP can reconstruct it from # WAVECAR copy_vasp_kwargs={"additional_vasp_files": ("WAVECAR",)} ) ) # optional 3rd PBE+U static in case structure contains elements with +U corrections static3: Maker | None = field( default_factory=lambda: MatPesGGAStaticMaker( name="MatPES GGA+U static", input_set_generator=MatPesGGAStaticSetGenerator( user_incar_settings={"LDAU:": True}, # enable +U corrections ), copy_vasp_kwargs={"additional_vasp_files": ("WAVECAR",)}, ) )
[docs] def make(self, structure: Structure, prev_dir: str | Path | None = None) -> Flow: """ Create a flow with MatPES statics. By default, a PBE static is followed by an r2SCAN static and optionally a PBE+U static if the structure contains elements with +U corrections. The PBE static is run with LWAVE=True so its WAVECAR can be passed as a pre-conditioned starting point to both the r2SCAN static and the PBE+U static. Parameters ---------- structure : .Structure A pymatgen structure object. prev_dir : str or Path or None A previous VASP calculation directory to copy output files from. Returns ------- Flow A flow containing 2 or 3 statics. """ static1 = self.static1.make(structure, prev_dir=prev_dir) static2 = self.static2.make(structure, prev_dir=static1.output.dir_name) output = {"static1": static1.output, "static2": static2.output} jobs = [static1, static2] # only run 3rd static if set generator not None and structure contains at least # one element with Hubbard +U corrections if self.static3 is not None: static3_config = self.static3.input_set_generator.config_dict u_corrections = static3_config.get("INCAR", {}).get("LDAUU", {}) elems = set(map(str, structure.elements)) if self.static3 and any( anion in elems and elems & {*cations} for anion, cations in u_corrections.items() ): static3 = self.static3.make(structure, prev_dir=static1.output.dir_name) output["static3"] = static3.output jobs += [static3] return Flow(jobs=jobs, output=output, name=self.name)