Source code for atomate2.vasp.flows.electrode
"""Flow for electrode analysis with specific VASP implementations."""
from __future__ import annotations
import logging
from pathlib import Path
from typing import TYPE_CHECKING
from pymatgen.io.vasp.outputs import Chgcar
from atomate2.common.flows import electrode as electrode_flows
from atomate2.utils.path import strip_hostname
if TYPE_CHECKING:
from pymatgen.io.vasp.outputs import VolumetricData
logger = logging.getLogger(__name__)
[docs]
class ElectrodeInsertionMaker(electrode_flows.ElectrodeInsertionMaker):
"""Attempt ion insertion into a structure.
The basic unit for cation insertion is:
[get_stable_inserted_structure]:
(static) -> (chgcar analysis) ->
N x (relax) -> (return best structure)
The workflow is:
[relax structure]
[get_stable_inserted_structure]
[get_stable_inserted_structure]
[get_stable_inserted_structure]
... until the insertion is no longer topotactic.
If you use this workflow please cite the following paper:
Shen, J.-X., Horton, M., & Persson, K. A. (2020).
A charge-density-based general cation insertion algorithm for
generating new Li-ion cathode materials.
npj Computational Materials, 6(161), 1—7.
doi: 10.1038/s41524-020-00422-3
Attributes
----------
name: str
The name of the flow created by this maker.
relax_maker: RelaxMaker
A maker to perform relaxation calculations.
bulk_relax_maker: Maker
A separate maker to perform the first bulk relaxation calculation.
If None, the relax_maker will be used.
static_maker: Maker
A maker to perform static calculations.
structure_matcher: StructureMatcher
The structure matcher to use to determine if additional insertion is needed.
"""
[docs]
def get_charge_density(self, prev_dir: Path | str) -> VolumetricData:
"""Get the charge density of a structure.
Parameters
----------
prev_dir:
The previous directory where the static calculation was performed.
Returns
-------
The charge density.
"""
prev_dir = Path(strip_hostname(prev_dir))
aeccar0 = Chgcar.from_file(prev_dir / "AECCAR0.gz")
aeccar2 = Chgcar.from_file(prev_dir / "AECCAR2.gz")
return aeccar0 + aeccar2
[docs]
def update_static_maker(self) -> None:
"""Ensure that the static maker will store the desired data."""
store_volumetric_data = list(
self.static_maker.task_document_kwargs.get("store_volumetric_data", [])
)
store_volumetric_data.extend(["aeccar0", "aeccar2"])
self.static_maker.task_document_kwargs["store_volumetric_data"] = (
store_volumetric_data
)