File: task.py

package info (click to toggle)
python-emmet-core 0.84.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 77,220 kB
  • sloc: python: 16,355; makefile: 30
file content (88 lines) | stat: -rw-r--r-- 2,920 bytes parent folder | download
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