Source code for MDMC.trajectory_analysis.observables.fqt_coh

"""
Module for coherent FQt class.
"""

import numpy as np
import periodictable

from MDMC.common.mathematics import faster_correlation
from MDMC.trajectory_analysis.observables.fqt import AbstractFQt
from MDMC.trajectory_analysis.observables.obs_factory import ObservableFactory


[docs] @ObservableFactory.register(('CoherentIntermediateScatteringFunction', 'FQtCoherent', 'FQtCoh', 'FQt_coh')) class FQtCoherent(AbstractFQt): """ Class for processing the intermediate scattering function for coherent dynamic structure factor. """ def _set_weights(self) -> None: """Calculate the neutron weighting for coherent scattering.""" elem_getter = periodictable.elements.symbol self.weights = {element: elem_getter(element).neutron.b_c if elem_getter(element).neutron.b_c is not None else 0 for element in self._trajectory.element_set} def _calculate_FQt_single_Q(self, single_Q_vectors: list) -> np.ndarray: # Inherit docstring of abstract method n_t = len(self.t) elements = self._trajectory.element_set FQt_single_Q = np.zeros(n_t) rho_element = {} n_atoms = 0 for element in elements: # Get the positions of all atoms (the configuration) of each # element over time such that ``element_configs`` has time as its # first dimension and each atom of ``element`` as its second indexes = np.where(np.array(self._trajectory.element_list) == element) element_configs = self._trajectory.position[:, indexes[0], :] rho_element[element] = self.calculate_rho_config(element_configs, single_Q_vectors) n_atoms += np.shape(indexes)[1] for element1 in elements: for element2 in elements: # A sum over the Q vectors is performed within ``correlation``. FQt_single_Q += (self.weights[element1] * self.weights[element2] * faster_correlation(rho_element[element1], rho_element[element2])[:n_t]) # Normalise to the number of orthogonal vectors try: norm = np.shape(single_Q_vectors)[0] except IndexError: norm = 1 return FQt_single_Q / (n_atoms * norm)