Source code for mchammer.observers.constituent_strain_observer

from mchammer.observers.base_observer import BaseObserver
from icet.tools import ConstituentStrain
from ase import Atoms


[docs] class ConstituentStrainObserver(BaseObserver): """ This class represents a constituent strain observer. It records the constituent strain energy of the configuration separately from the energy the cluster expansion describes, which is useful in a simulation with a :class:`ConstituentStrainCalculator <mchammer.calculators.ConstituentStrainCalculator>`, where the potential stored in the data container is the sum of the two. The value is stored in the data container under the key ``constituent_strain_energy`` and refers to the whole supercell. The section on :ref:`constituent strain <constituent_strain_example>` shows the observer in use. The observer reads the structure factors the :class:`ConstituentStrain <icet.tools.ConstituentStrain>` object holds but does not move them. It can therefore share the object with the calculator that samples the same configuration. Parameters ---------- constituent_strain Object that defines the strain energy of the system. Its supercell has to be the one the simulation samples. interval Observation interval in trial steps. By default the ensemble the observer is attached to sets the interval to the number of sites in the structure. """ def __init__(self, constituent_strain: ConstituentStrain, interval: int | None = None) -> None: super().__init__(interval=interval, return_type=dict, tag='ConstituentStrainObserver') self.constituent_strain = constituent_strain
[docs] def get_observable(self, structure: Atoms) -> dict: """ Returns the constituent strain energy of a configuration. Parameters ---------- structure Atomic configuration to observe. Returns ------- dict The constituent strain energy of the whole supercell under the key ``constituent_strain_energy``. """ # Observing must not move the structure factors, which a calculator # sampling the same ConstituentStrain object reads as the value # before the next change. cs = self.constituent_strain.get_constituent_strain( structure.get_atomic_numbers(), update_structure_factors=False) cs = {'constituent_strain_energy': cs * len(structure)} return cs