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