Source code for hyperfine.bnmr.two_site

import numpy as np
from scipy import constants
import jax
from typing import Annotated

# use double-precision numbers
jax.config.update("jax_enable_x64", True)


[docs] def korringa_rate( temperature: float, slope: Annotated[float, 0:None], ) -> float: r"""Spin-lattice relaxation rate from a Korringa mechanism. Args: temperature: Absolute temperature (K). slope: Korringa slope (s\ :sup:`-1` K\ :sup:`-1`). Returns: The Korringa SLR rate (s\ :sup:`-1`). """ return temperature * slope
[docs] def arrhenius_rate( temperature: float, attempt_frequency__s: Annotated[float, 0:None], activation_energy_eV: Annotated[float, 0:None], ) -> float: r"""Thermally activated rate following an Arrhenius law. Args: temperature: Absolute temperature (K). attempt_freqency__s: Attempt frequency or pre-exponential factor (s\ :sup:`-1`). activation_energy_eV: Activation energy or energy barrier (eV). Returns: The Arrhenius rate (s\ :sup:`-1`). """ return attempt_frequency__s * jax.numpy.exp( -1.0 * activation_energy_eV / (constants.value("Boltzmann constant in eV/K") * temperature) )
[docs] def amplitude_1( fraction_1: float, hop_rate_12: float, slr_rate_1: float, slr_rate_2: float, ) -> float: r"""Amplitude of site 1. Args: fraction_1: Fraction occupying site 1. hop_rate_12: Rate of site change from 1 -> 2 (s\ :sup:`-1`). slr_rate_1: SLR rate at site 1 (s\ :sup:`-1`). slr_rate_2: SLR rate at site 2 (s\ :sup:`-1`). Returns: The amplitude at site 1. """ numerator = ( hop_rate_12 - slr_rate_2 + slr_rate_1 ) * fraction_1 - hop_rate_12 * fraction_1 denominator = hop_rate_12 - slr_rate_2 + slr_rate_1 return numerator / denominator
[docs] def amplitude_2( fraction_1: float, hop_rate_12: float, slr_rate_1: float, slr_rate_2: float, ) -> float: r"""Amplitude of site 2. Args: fraction_1: Fraction occupying site 1. hop_rate_12: Rate of site change from 1 -> 2 (s\ :sup:`-1`). slr_rate_1: SLR rate at site 1 (s\ :sup:`-1`). slr_rate_2: SLR rate at site 2 (s\ :sup:`-1`). Returns: The amplitude at site 2. """ fraction_2 = 1.0 - fraction_1 numerator = hop_rate_12 - slr_rate_2 * fraction_2 + slr_rate_1 * fraction_1 denominator = hop_rate_12 - slr_rate_2 + slr_rate_1 return numerator / denominator
[docs] def M( fraction_1: float, hop_rate_12: float, slr_rate_1: float, slr_rate_2: float, ) -> float: r"""Convenience term. Args: fraction_1: Fraction occupying site 1. hop_rate_12: Rate of site change from 1 -> 2 (s\ :sup:`-1`). slr_rate_1: SLR rate at site 1 (s\ :sup:`-1`). slr_rate_2: SLR rate at site 2 (s\ :sup:`-1`). Returns: The convenience term. """ denominator = hop_rate_12 - slr_rate_2 + slr_rate_1 return fraction_1 * (1.0 - hop_rate_12 / denominator)
[docs] def average_slr_rate( temperature: float, initial_fraction_1: Annotated[float, 0:1], attempt_frequency__s: Annotated[float, 0:None], activation_energy_eV: Annotated[float, 0:None], korringa_slope_1__s_K: Annotated[float, 0:None], korringa_slope_2__s_K: Annotated[float, 0:None], ) -> float: r"""Average SLR rate within the two-site model. Args: temperature: Absolute temperature (K). initial_faction_1: Fraction of population initially in site 1. attempt_freqency__s: Attempt frequency or pre-exponential factor (s\ :sup:`-1`). activation_energy_eV: Activation energy or energy barrier (eV). korringa_slope_1__s_K: Korringa slope at site 1 (s\ :sup:`-1` K\ :sup:`-1`). korringa_slope_2__s_K: Korringa slope at site 2 (s\ :sup:`-1` K\ :sup:`-1`). Returns: The site-averaged SLR rate (s\ :sup:`-1`). """ hop_rate_12 = arrhenius_rate( temperature, attempt_frequency__s, activation_energy_eV ) slr_rate_1 = korringa_rate(temperature, korringa_slope_1__s_K) slr_rate_2 = korringa_rate(temperature, korringa_slope_2__s_K) fraction_1 = M(initial_fraction_1, hop_rate_12, slr_rate_1, slr_rate_2) fraction_2 = 1.0 - fraction_1 # weighted average return fraction_1 * slr_rate_1 + fraction_2 * slr_rate_2
[docs] def polarization_1( time: float, p_1_0: float, hop_rate_12: float, slr_rate_1: float, ) -> float: r"""Polarization at site 1. Args: time: Time after implantation (s). p_1_0: Initial polarization at site 1. hop_rate_12: Rate of site change from 1 -> 2 (s\ :sup:`-1`). slr_rate_1: SLR rate at site 1 (s\ :sup:`-1`). Returns: The polarization at site 1. """ return p_1_0 * np.exp(-(slr_rate_1 + hop_rate_12) * time)
[docs] def polarization_2( time: float, p_1_0: float, p_2_0: float, hop_rate_12: float, slr_rate_1: float, slr_rate_2: float, ) -> float: r"""Polarization at site 2. Args: time: Time after implantation (s). p_1_0: Initial polarization at site 1. p_2_0: Initial polarization at site 2. hop_rate_12: Rate of site change from 1 -> 2 (s\ :sup:`-1`). slr_rate_1: SLR rate at site 1 (s\ :sup:`-1`). slr_rate_2: SLR rate at site 2 (s\ :sup:`-1`). Returns: The polarization at site 2. """ numerator = ( (p_2_0 + p_1_0) * hop_rate_12 - p_2_0 * slr_rate_2 + p_2_0 * slr_rate_1 ) * np.exp(-slr_rate_2 * time) - p_1_0 * hop_rate_12 * np.exp( -(slr_rate_1 + hop_rate_12) * time ) denominator = hop_rate_12 - slr_rate_2 + slr_rate_1 return numerator / denominator
[docs] def polarization( time: float, p_1_0: float, p_2_0: float, hop_rate_12: float, slr_rate_1: float, slr_rate_2: float, ) -> float: r"""The total spin polarization within the two-site model. Args: time: Time after implantation (s). p_1_0: Initial polarization at site 1. p_2_0: Initial polarization at site 2. hop_rate_12: Rate of site change from 1 -> 2 (s\ :sup:`-1`). slr_rate_1: SLR rate at site 1 (s\ :sup:`-1`). slr_rate_2: SLR rate at site 2 (s\ :sup:`-1`). Returns: The total polarization. """ return polarization_1(time, p_1_0, hop_rate_12, slr_rate_1) + polarization_2( time, p_1_0, p_2_0, hop_rate_12, slr_rate_1, slr_rate_2 )