1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
""" Core definition of a VASP Task Document """
from __future__ import annotations
from typing import Any, Dict, List
from pydantic import Field
from pymatgen.analysis.xas.spectrum import XAS
from pymatgen.core import Structure
from pymatgen.core.periodic_table import Element, Species
from emmet.core.structure import StructureMetadata
from emmet.core.utils import ValueEnum
from emmet.core.vasp.task_valid import TaskDocument as BaseTaskDocument
class CalcType(ValueEnum):
"""
The type of FEFF Calculation
XANES - Just the near-edge region
EXAFS - Just the extended region
XAFS - Fully stitchted XANES + EXAFS
"""
XANES = "XANES"
EXAFS = "EXAFS"
XAFS = "XAFS"
class TaskDocument(BaseTaskDocument, StructureMetadata):
"""Task Document for a FEFF XAS Calculation. Doesn't support EELS for now"""
calc_code: str = "FEFF"
structure: Structure
input_parameters: Dict[str, Any] = Field(
{}, description="Input parameters for the FEFF calculation"
)
spectrum: List[List[float]] = Field(
[[]], description="Raw spectrum data from FEFF xmu.dat or eels.dat"
)
absorbing_atom: int = Field(
..., description="Index in the cluster or structure for the absorbing atom"
)
spectrum_type: CalcType = Field(..., title="XAS Spectrum Type")
edge: str = Field(
..., title="Absorption Edge", description="The interaction edge for XAS"
)
# TEMP Stub properties for compatibility with atomate drone
@property
def absorbing_element(self) -> Element | Species:
if isinstance(self.structure[self.absorbing_atom].specie, Element):
return self.structure[self.absorbing_atom].specie
return self.structure[self.absorbing_atom].specie.element
@property
def xas_spectrum(self) -> XAS:
if not hasattr(self, "_xas_spectrum"):
if not all([len(p) == 6 for p in self.spectrum]):
raise ValueError(
"Spectrum data doesn't appear to be from xmu.dat which holds XAS data"
)
energy = [point[0] for point in self.spectrum] # (eV)
intensity = [point[3] for point in self.spectrum] # (mu)
structure = self.structure
absorbing_index = self.absorbing_atom
absorbing_element = self.absorbing_element
if isinstance(absorbing_element, Species):
absorbing_element = absorbing_element.element
edge = self.edge
spectrum_type = str(self.spectrum_type)
self._xas_spectrum = XAS(
x=energy,
y=intensity,
structure=structure,
absorbing_element=absorbing_element,
absorbing_index=absorbing_index,
edge=edge,
spectrum_type=spectrum_type,
)
return self._xas_spectrum
|