Source code for lvlspy.transition

"""Module for handling transitions."""
import numpy as np
from gslconsts.consts import (
    GSL_CONST_CGSM_ELECTRON_VOLT,
    GSL_CONST_CGS_PLANCKS_CONSTANT_H,
    GSL_CONST_CGS_SPEED_OF_LIGHT,
    GSL_CONST_CGSM_BOLTZMANN,
)
import lvlspy.properties as lp


[docs] class Transition(lp.Properties): """A class for storing and retrieving data about a transition. Args: ``upper_level`` (:obj:`lvlspy.level.Level`) The level from which there is a spontaneous decay. ``lower_level`` (:obj:`lvlspy.level.Level`) The level to which there is a spontaneous decay. ``einstein_A`` (:obj:`float`): The Einstein A coefficient (the spontaneous decay rate per second from `upper_level` to `lower_level`). """ def __init__(self, upper_level, lower_level, einstein_a): super().__init__() self.properties = {} self.upper_level = upper_level self.lower_level = lower_level self.einstein_a = einstein_a def __eq__(self, other): if not isinstance(other, Transition): return NotImplemented return ( self.upper_level == other.upper_level and self.lower_level == other.lower_level )
[docs] def get_upper_level(self): """Method to retrieve the `upper_level` for the transition. Returns: :obj:`lvlspy.level.Level`: The `upper_level` for the transition. """ return self.upper_level
[docs] def get_lower_level(self): """Method to retrieve the `lower_level` for the transition. Returns: :obj:`lvlspy.level.Level`: The `lower_level` for the transition. """ return self.lower_level
[docs] def get_einstein_a(self): """Method to retrieve the Einstein A coefficient for the transition. Returns: :obj:`float`: The spontaneous rate (per second) for the transition. """ return self.einstein_a
[docs] def update_einstein_a(self, einstein_a): """Method that updates the Einstein A coefficient of a transition. Args: ``transition`` (:obj:`lvlspy.transition.Transition`) The transition to be modified. ``einstein_A`` (:obj:`float`) The new value for the Einstein A coefficient. Returns: On successful return, the transition Einstein A coefficient has been updated. """ self.einstein_a = einstein_a
[docs] def get_einstein_b_upper_to_lower(self): """Method to get the Einstein B coefficient for the upper level to lower level transition (induced emission). Returns: :obj:`float`: The Einstein coefficient in cm :sup:`2` steradian per erg per s. """ result = self.einstein_a / self._fnu() return result
[docs] def get_einstein_b_lower_to_upper(self): """Method to get the Einstein B coefficient for the lower level to upper level transition (induced absorption). Returns: :obj:`float`: The Einstein coefficient in cm :sup:`2` steradian per erg per s. """ return self.get_einstein_b_upper_to_lower() * ( self.upper_level.get_multiplicity() / self.lower_level.get_multiplicity() )
[docs] def compute_lower_to_upper_rate(self, temperature, user_func=None): """Method to compute the total rate for transition from the lower level to upper level. Args: ``temperature`` (:obj:`float`) The temperature in K at which to compute the rate. ``user_func`` (optional): A `function <https://docs.python.org/3/library/stdtypes.html#functions>`_ that computes the lower level to upper level transition rate. If supplied, the routine will use this function in place of the default one, which computes the rate from the appropriate Einstein coefficient and the blackbody spectrum. The function must take one :obj:`float` argument giving the temperature. Other data can be bound to the function. Returns: :obj:`float`: The rate (per second). """ if user_func: return user_func(temperature) return self.get_einstein_b_lower_to_upper() * self._bb(temperature)
[docs] def compute_upper_to_lower_rate(self, temperature, user_func=None): """Method to compute the total rate for transition from the upper level to to lower level. Args: ``temperature`` (:obj:`float`) The temperature in K at which to compute the rate. ``user_func`` (optional): A `function <https://docs.python.org/3/library/stdtypes.html#functions>`_ that computes the upper level to lower level transition rate. If supplied, the routine will use this function in place of the default one, which computes the rate from the appropriate Einstein coefficients and the blackbody spectrum. The function must take one :obj:`float` argument giving the temperature. Other data can be bound to the function. Returns: :obj:`float`: The rate (per second). """ if user_func: return user_func(temperature) return ( self.get_einstein_a() + self.get_einstein_b_upper_to_lower() * self._bb(temperature) )
[docs] def get_frequency(self): """Method to compute the frequency of the transition. Returns: :obj:`float`: The frequency (in Hz) of the transition. """ delta_e = self.upper_level.get_energy() - self.lower_level.get_energy() delta_e_erg = (1e3) * delta_e * GSL_CONST_CGSM_ELECTRON_VOLT return delta_e_erg / GSL_CONST_CGS_PLANCKS_CONSTANT_H
def _fnu(self): return ( 2.0 * GSL_CONST_CGS_PLANCKS_CONSTANT_H * np.power(self.get_frequency(), 3) / np.power(GSL_CONST_CGS_SPEED_OF_LIGHT, 2) ) def _bb(self, temperature): k_bt = GSL_CONST_CGSM_BOLTZMANN * temperature delta_e = self.upper_level.get_energy() - self.lower_level.get_energy() x_p = delta_e * 1.0e3 * GSL_CONST_CGSM_ELECTRON_VOLT / k_bt if x_p < 500: return self._fnu() / np.expm1(x_p) return self._fnu() * np.exp(-x_p)