solrat.atom_model.multi_term_atom_model.statistical_equilibrium_equations module¶
- class solrat.atom_model.multi_term_atom_model.statistical_equilibrium_equations.MultiTermAtomSEE(level_registry: LevelRegistry, transition_registry: TransitionRegistry, disable_r_s: bool = False)[source]¶
Bases:
BaseSEEStatistical Equilibrium Equations within Multi-Term atom model
- Parameters:
level_registry – LevelRegistry instance for the multi-term atom under study.
transition_registry – TransitionRegistry instance for the multi-term atom under study.
disable_r_s – Whether to disable stimulated emission \(R_S\) (7.46c).
Reference: (LL04 7.38)
Note on precomputing: All frames are built lazily on first use and cached as instance attributes. Atom-specific frames (no radiation tensor) are built once and reused across calls. Frames that depend on the radiation tensor are partially precomputed; the radiation-tensor factor is applied per
fill_all_equations()call. Precomputed frames can be extracted after the firstfill_all_equations()call and injected into a new instance viaPrecomputedDatato skip the build step.- classmethod from_model_config(config: MultiTermAtomConfig) Self[source]¶
Constructor from the model config.
- fill_all_equations(atmosphere_parameters: AtmosphereParameters, radiation_tensor_in_magnetic_frame: RadiationTensor)[source]¶
Loop through all equations to construct the complete system of equations for rho.
- Parameters:
atmosphere_parameters – AtmosphereParameters instance carrying the magnetic field and other variables.
radiation_tensor_in_magnetic_frame – RadiationTensor instance
Reference: (LL04 7.38)
Note: Calling this function multiple times with different atmosphere_parameters of \(J\) tensors is safe, it will build the system of equations from scratch each time.
- add_coherence_decay(atmosphere_parameters: AtmosphereParameters)[source]¶
Add the coherence decay \(N = n_0 + n_1 \nu_L\)
Reference: (LL04 7.38, 7.41)
- add_absorption(radiation_tensor: RadiationTensor)[source]¶
Add absorption \(T_a = t_{a1} \cdot J^{K_r}_{Q_r}\).
Reference: (LL04 7.38, 7.45a)
- add_emission_s(radiation_tensor: RadiationTensor)[source]¶
Add stimulated emission \(T_s = t_{s1} \cdot J^{K_r}_{Q_r}\).
Reference: (LL04 7.38, 7.45c)
- add_relaxation_e()[source]¶
Add spontaneous emission relaxation \(R_E = -r_{e0}\).
Reference: (LL04 7.38, 7.46b)
- add_relaxation_a(radiation_tensor: RadiationTensor)[source]¶
Add absorption relaxation \(R_A = -r_{a1} \cdot J^{K_r}_{Q_r}\).
Reference: (LL04 7.38, 7.46a)
- add_relaxation_s(radiation_tensor: RadiationTensor)[source]¶
Add stimulated emission relaxation \(R_S = -r_{s1} \cdot J^{K_r}_{Q_r}\).
Reference: (LL04 7.38, 7.46c)
- get_solution() Rho[source]¶
Get the solution of the Statistical Equilibrium Equations.
- Returns:
Rho instance
The solution is constructed by manual linalg solving, which proved to be a bit more reliable than available homogeneous solvers. The idea is simple:
The matrix equation is \(A x = 0\).
Let \(x[0] = 1\) (it is always \(\rho_0^0\) of some kind, so it is least likely to be exactly zero). Then we have a non-homogeneous system of equations:
\[ \begin{align}\begin{aligned}A[1:] x &= 0\\A[1:, 1:] x[1:] &= -A[1:, 0]\end{aligned}\end{align} \]This system generally behaves well enough for linalg.solve to succeed, but pinv is more robust.