Source code for assyst.calculators
"""
Convenience shorts to create ASE calculators to be used inside ASSYST.
Exists mostly to avoid passing around potentially large and unpickle-able calculator objects.
"""
from abc import ABC, abstractmethod
from dataclasses import dataclass, asdict
from functools import lru_cache
import os
from ase.calculators.calculator import Calculator
from ase.calculators.morse import MorsePotential
[docs]
class AseCalculatorConfig(ABC):
"""Base class to keep calculator configurations."""
[docs]
@abstractmethod
def get_calculator(self) -> Calculator:
"""Return the actual calculator object.
Returns:
:class:`ase.calculators.calculator.Calculator`: the actually usable calculator
"""
pass
[docs]
@dataclass(frozen=True, eq=True)
class Grace(AseCalculatorConfig):
"""Universal Graph Atomic Cluster Expansion models.
.. attention::
This class needs additional dependencies!
Install `tensorpotential` from `PyPI <https://pypi.org/project/tensorpotential/>`__.
"""
model: str = "GRACE-FS-OAM"
[docs]
@lru_cache(maxsize=1)
def get_calculator(self) -> Calculator:
try:
from tensorpotential.calculator import grace_fm
except ImportError:
raise ImportError(
"grace-tensorpotential required; install with "
"'conda install -c conda-forge grace-tensorpotential' or 'pip install tensorpotential'"
)
# disable tensorflow warnings noise
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
return grace_fm(self.model)
[docs]
@dataclass(frozen=True, eq=True)
class Morse(AseCalculatorConfig):
"""Morse potential for testing. Parameters as in ASE."""
epsilon: float = 1.0
r0: float = 1.0
rho0: float = 1.0
[docs]
def get_calculator(self) -> Calculator:
return MorsePotential(**asdict(self))
__all__ = [
"AseCalculatorConfig",
"Grace",
"Morse",
]