cherab.imas.ids.common.solve_coronal_equilibriumΒΆ

cherab.imas.ids.common.solve_coronal_equilibrium(element: Element, density: ArrayLike, n_e: ArrayLike, t_e: ArrayLike, atomic_data: AtomicData | None = None, z_min: int | None = None, z_max: int | None = None) ndarray[tuple[Any, ...], dtype[float64]]SourceΒΆ

Solve the charge state distribution of an element in coronal equilibrium.

The coronal equilibrium assumption is valid when the plasma is optically thin and the timescales for ionisation and recombination are much shorter than the timescales for transport processes. Under these conditions, the charge state distribution can be determined solely by the balance between ionisation and recombination processes. The charge state density of species \(Z\), denoted \(n_Z\), can be calculated from the following relation:

\[n_{Z+1} = \frac{S_Z(n_\mathrm{e}, T_\mathrm{e})}{\alpha_{Z+1}(n_\mathrm{e}, T_\mathrm{e})}\cdot n_{Z},\]

where \(S_Z(n_\mathrm{e}, T_\mathrm{e})\) and \(\alpha_{Z+1}(n_\mathrm{e}, T_\mathrm{e})\) are the ionisation and recombination rates coefficients for the charge state \(Z\) as functions of the electron density \(n_\mathrm{e}\) and temperature \(T_\mathrm{e}\), respectively.

Using the total density of the element in the range of charge states considered i.e.,

\[\begin{split}n_\mathrm{total} &= \sum_{Z=Z_\mathrm{min}}^{Z_\mathrm{max}} n_Z\\ &= n_{Z_\mathrm{min}} + n_{Z_\mathrm{min}+1} + n_{Z_\mathrm{min}+2} + \dots\\ &= n_{Z_\mathrm{min}} + \frac{S_{Z_\mathrm{min}}} {\alpha_{Z_\mathrm{min}+1}} \cdot n_{Z_\mathrm{min}} + \frac{S_{Z_\mathrm{min}+1}} {\alpha_{Z_\mathrm{min}+2}} \cdot \frac{S_{Z_\mathrm{min}}} {\alpha_{Z_\mathrm{min}+1}} \cdot n_{Z_\mathrm{min}} + \dots\\ &= n_{Z_\mathrm{min}} \cdot \left[ 1 + \sum_{i=0}^{Z_\mathrm{max} - Z_\mathrm{min} - 1} \left( \prod_{j=0}^{i} \frac{S_{Z_\mathrm{min}+j}} {\alpha_{Z_\mathrm{min}+j+1}} \right) \right]\end{split}\]

allows us to express the first charge state density \(n_{Z_\mathrm{min}}\) as

\[n_{Z_\mathrm{min}} = n_\mathrm{total} \cdot \left[ 1 + \sum_{i=0}^{Z_\mathrm{max} - Z_\mathrm{min} - 1} \left( \prod_{j=0}^{i}\frac{S_{Z_\mathrm{min}+j}}{\alpha_{Z_\mathrm{min}+j+1}} \right) \right]^{-1}.\]

Substituting this back into the first equation \(n_{Z+1} = \frac{S_Z}{\alpha_{Z+1}} n_Z\) allows us to compute the density of each charge state as follows:

\[\begin{split}\begin{bmatrix} n_{Z_\mathrm{min}}\\ n_{Z_\mathrm{min}+1}\\ n_{Z_\mathrm{min}+2}\\ \vdots\\ n_{Z_\mathrm{max}} \end{bmatrix} = \frac{ n_\mathrm{total} }{ 1 + \displaystyle\sum_{i=0}^{Z_\mathrm{max} - Z_\mathrm{min} - 1} \left( \prod_{j=0}^{i}\frac{S_{Z_\mathrm{min}+j}}{\alpha_{Z_\mathrm{min}+j+1}} \right) } \begin{bmatrix} 1\\ \frac{S_{Z_\mathrm{min}}}{\alpha_{Z_\mathrm{min}+1}}\\ \frac{S_{Z_\mathrm{min}+1}} {\alpha_{Z_\mathrm{min}+2}} \cdot \frac{S_{Z_\mathrm{min}}}{\alpha_{Z_\mathrm{min}+1}}\\ \vdots\\ \displaystyle\prod_{j=0}^{Z_\mathrm{max} - Z_\mathrm{min} - 1} \frac{S_{Z_\mathrm{min}+j}}{\alpha_{Z_\mathrm{min}+j+1}} \end{bmatrix}.\end{split}\]
Parameters:
element: ElementΒΆ

Element for which to solve the charge state distribution.

density: ArrayLikeΒΆ

Total density of the element, \(n_\mathrm{total}\) (in m^-3). Should be the 1-D array of the same shape as n_e and t_e, or a scalar.

n_e: ArrayLikeΒΆ

Electron density, \(n_\mathrm{e}\) (in m^-3). Should be the 1-D array of the same shape as density and t_e, or a scalar.

t_e: ArrayLikeΒΆ

Electron temperature, \(T_\mathrm{e}\) (in eV). Should be the 1-D array of the same shape as density and n_e, or a scalar.

atomic_data: AtomicData | None = NoneΒΆ

Atomic data provider to use for ionisation and recombination rates. If None, OpenADAS will be used by default.

z_min: int | None = NoneΒΆ

Minimum charge state to consider (inclusive), \(Z_\mathrm{min}\). If None, defaults to 0.

z_max: int | None = NoneΒΆ

Maximum charge state to consider (inclusive), \(Z_\mathrm{max}\). If None, defaults to the atomic number of the element.

Returns:

numpy.ndarray – Density of the element in each charge state (in m^-3), with shape (z_max - z_min + 1, *density.shape).

Raises:
  • ValueError – If z_min or z_max are out of valid range, or if density, n_e, and t_e do not have the same shape.

  • TypeError – If atomic_data is not an instance of AtomicData.

Examples

>>> from cherab.core.atomic.elements import neon as element
>>> density = 1.0  # if the density is 1, the output will be the relative abundance of each charge state
>>> n_e = 1e20
>>> t_e = 10
>>> result = solve_coronal_equilibrium(element, density, n_e, t_e)
>>> print([f"{x:.1%}" for x in result.ravel()])
['0.0%', '0.0%', '13.1%', '80.4%', '6.4%', '0.0%', '0.0%', '0.0%', '0.0%', '0.0%', '0.0%']