Source code for solrat.atom_model.multi_term_atom_model.object.transition_registry

from typing import Dict, List, Union

from solrat.atom_model.multi_term_atom_model.object.level_registry import Term
from solrat.atom_model.multi_term_atom_model.utility.einstein_coefficients import (
    b_lu_from_b_ul_multi_term_atom,
    b_ul_from_a_ul_multi_term_atom,
)
from solrat.atom_model.shared.utility.functions import energy_cmm1_to_frequency_sm1
from solrat.engine.functions.decorators import log_method


[docs] class TransitionRegistry: r""" This class serves as a registry for all transitions. The transitions are defined as ones occurring between terms, not levels, so the Einstein coefficients need to be adjusted accordingly. Only pure E1 :math:`LS` transitions are fully supported. """ def __init__(self): self.transitions: Dict[str, "Transition"] = {}
[docs] def einstein_b_lu(self, transition_id: str) -> float: return self.transitions[transition_id].einstein_b_lu
[docs] def einstein_b_ul(self, transition_id: str) -> float: return self.transitions[transition_id].einstein_b_ul
[docs] def einstein_a_ul(self, transition_id: str) -> float: return self.transitions[transition_id].einstein_a_ul
[docs] @log_method def register_transition( self, term_upper: Term, term_lower: Term, einstein_a_ul_sm1: float, lower_J_constraint: Union[List[float], None] = None, upper_J_constraint: Union[List[float], None] = None, ): r""" Einstein coefficients are on :math:`\beta LS \to \beta LS` level, so need to sum over :math:`J` in advance. :param term_upper: upper Term instance :param term_lower: lower Term instance :param einstein_a_ul_sm1: spontaneous emission in [1/s] :param lower_J_constraint: constrain lower term :math:`J` values in RTE to these values :param upper_J_constraint: constrain upper term :math:`J` values in RTE to these values """ assert term_lower.S == term_upper.S, "Spin of upper and lower terms must be the same" transition_id = term_upper.term_id + "->" + term_lower.term_id assert transition_id not in self.transitions.keys() nu_ul = energy_cmm1_to_frequency_sm1(term_upper.get_mean_energy_cmm1() - term_lower.get_mean_energy_cmm1()) b_ul = b_ul_from_a_ul_multi_term_atom(a_ul_sm1=einstein_a_ul_sm1, nu_ul=nu_ul) b_lu = b_lu_from_b_ul_multi_term_atom(b_ul=b_ul, Lu=term_upper.L, Ll=term_lower.L) transition = Transition( transition_id=transition_id, term_upper=term_upper, term_lower=term_lower, einstein_a_ul=einstein_a_ul_sm1, einstein_b_ul=b_ul, einstein_b_lu=b_lu, lower_J_constraint=lower_J_constraint, upper_J_constraint=upper_J_constraint, ) self.transitions[transition_id] = transition
[docs] def is_transition_registered( self, term_upper: Term, term_lower: Term, ): """ Checks if the transition between the terms is registered. """ transition_id = term_upper.term_id + "->" + term_lower.term_id return transition_id in self.transitions.keys()
[docs] def get_transition( self, term_upper: Term, term_lower: Term, ): """ Get the transition between the two terms - assume it is registered. """ transition_id = term_upper.term_id + "->" + term_lower.term_id return self.transitions[transition_id]
[docs] class Transition: r""" Transition coefficients are registered between terms, not levels. :param transition_id: Unique transition ID :param term_upper: upper Term instance :param term_lower: lower Term instance :param einstein_a_ul: Einstein coefficient :math:`A_{ul}` :param einstein_b_ul: Einstein coefficient :math:`B_{ul}` :param einstein_b_lu: Einstein coefficient :math:`B_{lu}` :param lower_J_constraint: constrain lower term :math:`J` values in RTE to these values :param upper_J_constraint: constrain lower term :math:`J` values in RTE to these values """ def __init__( self, transition_id: str, term_upper: Term, term_lower: Term, einstein_a_ul: float, einstein_b_ul: float, einstein_b_lu: float, lower_J_constraint: Union[List[float], None] = None, upper_J_constraint: Union[List[float], None] = None, ): assert term_lower.S == term_upper.S self.transition_id = transition_id self.term_upper: Term = term_upper self.term_lower: Term = term_lower self.einstein_a_ul: float = einstein_a_ul self.einstein_b_ul: float = einstein_b_ul self.einstein_b_lu: float = einstein_b_lu if lower_J_constraint is not None: for J in lower_J_constraint: assert J in [level.J for level in term_lower.levels] if upper_J_constraint is not None: for J in upper_J_constraint: assert J in [level.J for level in term_upper.levels] self.lower_J_for_RTE = lower_J_constraint self.upper_J_for_RTE = upper_J_constraint
[docs] def get_mean_transition_frequency_sm1(self): r""" A crude approximation for the 'central' frequency of the transition. Should be used only in non-frequency-sensitive expressions like filling out Planck's function in LTE. """ return energy_cmm1_to_frequency_sm1( self.term_upper.get_mean_energy_cmm1() - self.term_lower.get_mean_energy_cmm1() )