API

Configuration Enums

Enumerators to constrain options for functions.

class ProfileForm(value)[source]

Bases: Enum

Methods to calculate nT profiles.

analytic = 1
prf = 2
class RadiationMethod(value)[source]

Bases: Enum

Methods to calculate radiation losses.

Inherent = 'Bremsstrahlung and synchrotron radiation only'
PostJensen = 'Impurity radiation, using a coronal equilibrium model from Post & Jensen 1977'
MavrinCoronal = 'Impurity radiation, using a coronal equilibrium model from Mavrin 2018'
MavrinNoncoronal = 'Impurity radiation, using a non-coronal model from Mavrin 2017'
Radas = 'Impurity line and bremsstrahlung radiation, using coronal Lz curves from Radas'
class AtomicSpecies(value)[source]

Bases: Enum

Enum of possible atomic species.

Hydrogen = 1
Deuterium = 2
Tritium = 3
Helium = 4
Lithium = 5
Beryllium = 6
Boron = 7
Carbon = 8
Nitrogen = 9
Oxygen = 10
Neon = 11
Argon = 12
Krypton = 13
Xenon = 14
Tungsten = 15
class MomentumLossFunction(value)[source]

Bases: Enum

Select which SOL momentum loss function to use.

KotovReiter = 1
Sang = 2
Jarvinen = 3
Moulton = 4
PerezH = 5
PerezL = 6
class LambdaQScaling(value)[source]

Bases: Enum

Options for heat flux decay length scaling.

Brunner = 1
EichRegression9 = 2
EichRegression14 = 3
EichRegression15 = 4
class ConfinementPowerScaling(value)[source]

Bases: Enum

Options for which confinement threshold power scaling to use.

I_mode_AUG = 1
I_mode_HubbardNF17 = 2
I_mode_HubbardNF12 = 3
H_mode_Martin = 4
class VertMagneticFieldEq(value)[source]

Bases: Enum

Vertical magnetic field equation from various papers.

NOTE: the choice of Barr vs. Mitarai also affects invmu_0_dLedR and the vertical_magnetic_field_mutual_inductance.

Mit_and_Taka_Eq13 = 1
Barr = 2
Jean = 3
MagneticFusionEnergyFormulary = 4
class SurfaceInductanceCoeffs(value)[source]

Bases: Enum

Coefficients to calculate external inductance components.

Hirshman = 1
Barr = 2

Formulas

Auxiliary Power

Routines to calculate the auxiliary (non-Ohmic, non-fusion) power.

calc_auxiliary_power(
P_in: Quantity | DataArray,
P_alpha: Quantity | DataArray,
P_ohmic: Quantity | DataArray,
fraction_of_external_power_coupled: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the required auxiliary power.

Parameters:
Returns:

P_external [MW], P_auxiliary_absorbed [MW], P_auxiliary_launched [MW]

Energy Confinement

Interface to different energy confinement scalings and routines to calculate the plasma stored energy.

class ConfinementScaling(name: str, data: dict[str, Any])[source]

Bases: object

Class to handle different energy confinement scalings.

Initialises an energy confinement scaling from a block of the energy_confinement_scalings.yaml file.

instances: ClassVar[dict[str, ConfinementScaling]] = {}
calc_plasma_stored_energy(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_density: Quantity | DataArray,
summed_impurity_density: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
) Quantity | DataArray[source]

Calculates the plasma thermal stored energy.

Parameters:
Returns:

plasma_stored_energy

read_confinement_scalings() None[source]

Reads the energy confinement scalings from an energy_confinement_scalings.yaml file.

solve_energy_confinement_scaling_for_input_power(
confinement_time_scalar: Quantity | DataArray,
plasma_current: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
major_radius: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
separatrix_elongation: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
separatrix_triangularity: Quantity | DataArray,
plasma_stored_energy: Quantity | DataArray,
q_star: Quantity | DataArray,
energy_confinement_scaling: str,
) tuple[DataArray, DataArray][source]

Calculate energy confinement time and input power from a tau_E scaling.

The energy confinement time can generally be written as

\[\tau_e = H \cdot C \cdot P_{\tau}^{\alpha_P} \cdot I_{MA}^{\alpha_I} \cdot B_0^{\alpha_B} \cdot \bar{n_{e,19}}^{\alpha_n} \cdot R_0^{\alpha_R} \cdot \kappa_A^{\alpha_{ka}} \cdot \kappa_{sep}^{\alpha_{ks}} \cdot \epsilon^{\alpha_e} \cdot m_i^{\alpha_A} \cdot \delta^{\alpha_d}\]

We don’t know \(P_{\tau}\) in advance, so instead write

\[\tau_e = \gamma \cdot P_{\tau}^{\alpha_P}\]

with

\[\gamma = H \cdot C \cdot I_{MA}^{\alpha_I} \cdot B_0^{\alpha_B} \cdot \bar{n_{e,19}}^{\alpha_n} \cdot R_0^{\alpha_R} \cdot \kappa_A^{\alpha_{ka}} \cdot \kappa_{sep}^{\alpha_{ks}} \cdot \epsilon^{\alpha_e} \cdot m_i^{\alpha_A} \cdot \delta^{\alpha_d}\]

We have everything that we need to evaluate \(\gamma\). Then, we also know that

\[\tau_e = W_p / P_{loss}\]

Then, we crucially need to define what exactly we mean by the two powers that we’ve introduced (\(P_{\tau}\) and \(P_{loss}\)). We usually take \(P_{\tau} = P_{heating} = P_{ohmic} + P_{\alpha} + P_{aux}\) and \(P_{loss}=P_{SOL} + P_{rad,core}\) [Wesson definition]. From a simple power balance, \(P_{heating}=P_{loss}\) and so, setting the two \(\tau_e\) equations equal, we get that

\[W_p / P = \gamma \cdot P^{\alpha_P} P^{\alpha_P + 1} = W_p / \gamma P = \left(W_p / \gamma \right)^{\frac{1}{\alpha_P + 1}}\]

Once we have \(P = P_{ohmic} + P_{\alpha} + P_{aux} = P_{SOL} + P_{rad,core}\), we can calculate \(W_p/P\).

However, it is also possible that the core radiated power is subtracted when calculating \(\tau_e\) [Freidberg definition of \(W_p\)], giving

\[P_{\tau} = P_{ohmic} + P_{\alpha} + P_{aux} - P_{rad} = P_{loss} = P_{SOL}\]

Then, the returned value should be interpreted as \(P_{SOL}\). We currently don’t allow this case, since the general consensus is that the radiated power has not been consistently removed from scaling relationship. However, if you want to explore the effect of changing this assumption, you can implement a new feature.

N.b. there are two more possible cases, where different powers are used in the two \(\tau_e\) scalings. We don’t allow these cases, since 1) experiments generally pick a consistent definition for \(P\) and 2) this results in an equation for \(P\) which cannot be solved analytically.

Parameters:
Returns:

energy_confinement_time [s], P_in [MW]

solve_energy_confinement_scaling_for_input_power.unitless_func(
confinement_time_scalar: float,
plasma_current: float,
magnetic_field_on_axis: float,
average_electron_density: float,
major_radius: float,
areal_elongation: float,
separatrix_elongation: float,
inverse_aspect_ratio: float,
average_ion_mass: float,
triangularity_psi95: float,
separatrix_triangularity: float,
plasma_stored_energy: float,
q_star: float,
energy_confinement_scaling: str,
) tuple[float, float]

A scalar and not unit aware version of the above function.

switch_to_L_mode_confinement_below_threshold(
plasma_stored_energy: Quantity | DataArray,
energy_confinement_time: Quantity | DataArray,
P_in: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
confinement_time_scalar: Quantity | DataArray,
plasma_current: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
major_radius: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
separatrix_elongation: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
separatrix_triangularity: Quantity | DataArray,
q_star: Quantity | DataArray,
ratio_of_P_SOL_to_P_LH: Quantity | DataArray,
energy_confinement_scaling_for_L_mode: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Switch to the L-mode scaling if Psol < PLH.

Parameters:
Returns:

energy_confinement_time, P_in

switch_to_linearised_ohmic_confinement_below_threshold(
plasma_stored_energy: Quantity | DataArray,
energy_confinement_time: Quantity | DataArray,
P_in: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
confinement_time_scalar: Quantity | DataArray,
plasma_current: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
major_radius: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
separatrix_elongation: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
separatrix_triangularity: Quantity | DataArray,
q_star: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Switch to the LOC scaling if it predicts a worse energy confinement than our selected tau_e scaling.

Parameters:
Returns:

energy_confinement_time, P_in, SOC_LOC_ratio

Fusion Power

Routines to calculate the fusion power and gain.

class DDFusionBoschHale[source]

Bases: FusionReaction

Deuterium-Deuterium reaction using Bosch-Hale cross-section.

Sets the reaction energies for the Deuterium-Deuterium reaction.

static calc_rate_coefficient(ion_temp: float) tuple[float, float, float][source]

Calculate \(\\langle \\sigma v \rangle\) for a given ion temperature.

Cross-section from [12]

Parameters:

ion_temp – [keV]

Returns:

\(\\langle \\sigma v \rangle\) [cm^3/s]

calc_average_ion_mass() Quantity | DataArray[source]

Returns the average mass of the fuel ions.

Returns:

average_ion_mass [amu]

calc_energy_per_reaction(
ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the total energy per reaction.

calc_energy_to_neutrals_per_reaction(
ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the energy going to uncharged species per reaction.

calc_energy_to_charged_per_reaction(
ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the energy going to charged species per reaction.

calc_power_density(
ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the total power density.

calc_power_density_to_neutrals(
ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the power density going to uncharged species.

calc_power_density_to_charged(
ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the power density going to charged species.

class DDFusionHively[source]

Bases: DDFusionBoschHale

Deuterium-Deuterium reaction using Hively cross-section.

Sets the reaction energies for the Deuterium-Deuterium reaction.

static calc_rate_coefficient(ion_temp: float) tuple[float, float, float][source]

Calculate \(\\langle \\sigma v \rangle\) for a given ion temperature.

Cross-section from [13]

Parameters:

ion_temp – [keV]

Returns:

\(\\langle \\sigma v \rangle\) [cm^3/s]

class DHe3Fusion[source]

Bases: FusionReaction

Deuterium-Helium-3 reaction (Bosch-Hale cross-section).

Sets the reaction energies for the Deuterium-Tritium reaction.

static calc_rate_coefficient(ion_temp: float) float[source]

Deuterium-Helium-3 reaction.

Calculate \(\langle \sigma v \rangle\) for a given characteristic ion energy.

Function tested on available data at [1, 2, 5, 10, 20, 50, 100] keV. Maximum error = 8.4% within range 2-100 keV and should not be used outside range [2, 100] keV.

Uses DD cross section formulation [12].

Parameters:

ion_temp – [keV]

Returns:

\(\langle \sigma v \rangle\) in cm^3/s.

calc_average_ion_mass(
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average mass of the fuel ions.

Parameters:

heavier_fuel_species_fraction – n_heavier / (n_heavier + n_lighter) number fraction.

Returns:

average_ion_mass [amu]

calc_energy_per_reaction() Quantity | DataArray[source]

Returns the total energy per reaction.

calc_energy_to_neutrals_per_reaction() Quantity | DataArray[source]

Returns the energy going to uncharged species per reaction.

calc_energy_to_charged_per_reaction() Quantity | DataArray[source]

Returns the energy going to charged species per reaction.

calc_power_density(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the total power density.

calc_power_density_to_neutrals() Quantity | DataArray[source]

Returns the power density going to uncharged species.

calc_power_density_to_charged(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the power density going to charged species.

class DTFusionBoschHale[source]

Bases: FusionReaction

Deuterium-Tritium reaction using Bosch-Hale cross-section.

Sets the reaction energies for the Deuterium-Tritium reaction.

static calc_rate_coefficient(ion_temp: float) float[source]

Calculate \(\\langle \\sigma v \rangle\) for a given ion temperature.

Cross-section from [12], equation 12, using coefficients from table VII, page 625 (first column is DT reaction)

Parameters:

ion_temp – [keV]

Returns:

\(\\langle \\sigma v \rangle\) [cm^3/s]

calc_average_ion_mass(
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average mass of the fuel ions.

Parameters:

heavier_fuel_species_fraction – n_heavier / (n_heavier + n_lighter) number fraction.

Returns:

average_ion_mass [amu]

calc_energy_per_reaction() Quantity | DataArray[source]

Returns the total energy per reaction.

calc_energy_to_neutrals_per_reaction() Quantity | DataArray[source]

Returns the energy going to uncharged species per reaction.

calc_energy_to_charged_per_reaction() Quantity | DataArray[source]

Returns the energy going to charged species per reaction.

calc_power_density(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the total power density.

calc_power_density_to_neutrals(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the power density going to uncharged species.

calc_power_density_to_charged(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the power density going to charged species.

class DTFusionHively[source]

Bases: DTFusionBoschHale

Deuterium-Tritium reaction using Hively cross-section.

Sets the reaction energies for the Deuterium-Tritium reaction.

static calc_rate_coefficient(ion_temp: float) float[source]

Calculate \(\\langle \\sigma v \rangle\) for a given ion temperature.

Cross-section from [13]

Parameters:

ion_temp – [keV]

Returns:

\(\\langle \\sigma v \rangle\) [cm^3/s]

class FusionReaction[source]

Bases: object

A base class for different fusion reactions.

Records children classes in instances.

instances: ClassVar[dict[str, FusionReaction]] = {'DDFusionBoschHale': <cfspopcon.formulas.fusion_power.fusion_data.DDFusionBoschHale object>, 'DDFusionHively': <cfspopcon.formulas.fusion_power.fusion_data.DDFusionHively object>, 'DHe3Fusion': <cfspopcon.formulas.fusion_power.fusion_data.DHe3Fusion object>, 'DTFusionBoschHale': <cfspopcon.formulas.fusion_power.fusion_data.DTFusionBoschHale object>, 'DTFusionHively': <cfspopcon.formulas.fusion_power.fusion_data.DTFusionHively object>, 'pB11Fusion': <cfspopcon.formulas.fusion_power.fusion_data.pB11Fusion object>}
calc_average_ion_mass(
fusion_reaction: str,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average mass of the fuel ions, based on reaction type and fuel mixture ratio.

Parameters:
  • fusion_reaction – reaction type.

  • heavier_fuel_species_fraction – n_heavier / (n_heavier + n_lighter) number fraction.

Returns:

average_ion_mass [amu]

calc_fusion_gain(
P_fusion: Quantity | DataArray,
P_ohmic: Quantity | DataArray,
P_auxiliary_launched: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the fusion gain, using the launched power in the denominator.

This is the thermal gain using the launched power. A slightly more optimistic Q can be obtained by using the absorbed power (P_external) in the denominator, but for scientific breakeven the launched power will be used.

The denominator is forced to be at least 1W, to prevent a division-by-zero error.

Parameters:
Returns:

Q [~]

calc_fusion_power(
fusion_reaction: str,
ion_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
heavier_fuel_species_fraction: float,
fuel_ion_density_profile: ndarray[tuple[int, ...], dtype[float64]],
rho: ndarray[tuple[int, ...], dtype[float64]],
plasma_volume: float,
) tuple[Quantity | DataArray, Quantity | DataArray, Quantity | DataArray][source]

Calculate the fusion power.

Parameters:
Returns:

P_fusion [MW], P_neutron [MW], P_alpha [MW]

calc_neutron_flux_to_walls(
P_neutron: float,
surface_area: float,
fusion_reaction: str,
ion_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
heavier_fuel_species_fraction: float,
) tuple[float, float][source]

Calculate the neutron loading on the wall.

Parameters:
  • P_neutron – [MW] glossary link

  • surface_area – [m^2] glossary link

  • fusion_reaction – which nuclear reaction is being considered

  • ion_temp_profile – [keV] glossary link

  • heavier_fuel_species_fraction – fraction of fuel mixture which is the heavier nuclide

Returns:

neutron_power_flux_to_walls [MW / m^2], neutron_rate [s^-1]

calc_triple_product(
peak_fuel_ion_density: Quantity | DataArray,
peak_ion_temp: Quantity | DataArray,
energy_confinement_time: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the fusion triple product.

Parameters:
Returns:

fusion_triple_product [10e20 m**-3 keV s]

class pB11Fusion[source]

Bases: FusionReaction

Proton-Boron-11 reaction (Nevins-Swain cross-section).

Sets the reaction energies for the Deuterium-Tritium reaction.

static calc_rate_coefficient(ion_temp: float) float[source]

Proton (hydrogen)-Boron11 reaction.

Calculate \(\langle \sigma v \rangle\) for a given characteristic ion energy.

Uses cross section from Nevins and Swain [14]. Updated cross sections in [15], and [16] are not in analytic form.

Parameters:

ion_temp – [keV]

Returns:

\(\langle \sigma v \rangle\) in cm^3/s.

calc_average_ion_mass(
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average mass of the fuel ions.

Parameters:

heavier_fuel_species_fraction – n_heavier / (n_heavier + n_lighter) number fraction.

Returns:

average_ion_mass [amu]

calc_energy_per_reaction() Quantity | DataArray[source]

Returns the total energy per reaction.

calc_energy_to_neutrals_per_reaction() Quantity | DataArray[source]

Returns the energy going to uncharged species per reaction.

calc_energy_to_charged_per_reaction() Quantity | DataArray[source]

Returns the energy going to charged species per reaction.

calc_power_density(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the total power density.

calc_power_density_to_neutrals() Quantity | DataArray[source]

Returns the power density going to uncharged species.

calc_power_density_to_charged(
ion_temp: Quantity | DataArray,
heavier_fuel_species_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Returns the power density going to charged species.

Geometry

Routines to calculate terms related to the plasma geometry, such as the volume inside the last-closed-flux-surface.

calc_areal_elongation_from_elongation_at_psi95
calc_areal_elongation_from_elongation_at_psi95.return_keys = ['areal_elongation']
calc_areal_elongation_from_elongation_at_psi95.run(elongation_ratio_areal_to_psi95)
calc_areal_elongation_from_elongation_at_psi95.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_elongation_at_psi95_from_areal_elongation
calc_elongation_at_psi95_from_areal_elongation.return_keys = ['elongation_psi95']
calc_elongation_at_psi95_from_areal_elongation.run(elongation_ratio_areal_to_psi95)
calc_elongation_at_psi95_from_areal_elongation.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_inverse_aspect_ratio
calc_inverse_aspect_ratio.return_keys = ['inverse_aspect_ratio']
calc_inverse_aspect_ratio.run(minor_radius)
calc_inverse_aspect_ratio.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_minor_radius_from_inverse_aspect_ratio
calc_minor_radius_from_inverse_aspect_ratio.return_keys = ['minor_radius']
calc_minor_radius_from_inverse_aspect_ratio.run(inverse_aspect_ratio)
calc_minor_radius_from_inverse_aspect_ratio.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_plasma_poloidal_circumference(
minor_radius: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the plasma poloidal circumference at the last-closed-flux-surface.

Geometric formulas for system codes including the effect of negative triangularity :cite: sauter

Parameters:
Returns:

poloidal_circumference [m]

calc_plasma_surface_area(
major_radius: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the plasma surface area inside the last-closed-flux-surface.

Parameters:
Returns:

surface_area [m^2]

calc_plasma_volume(
major_radius: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the plasma volume inside an up-down symmetrical last-closed-flux-surface.

Geometric formulas for system codes including the effect of negative triangularity :cite: sauter NOTE: delta=1.0 is assumed since this was found to give a closer match to 2D equilibria from FreeGS.

Parameters:
Returns:

plasma_volume [m^3]

calc_separatrix_elongation_from_areal_elongation
calc_separatrix_elongation_from_areal_elongation.return_keys = ['separatrix_elongation']
calc_separatrix_elongation_from_areal_elongation.run(elongation_ratio_sep_to_areal)
calc_separatrix_elongation_from_areal_elongation.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_separatrix_triangularity_from_triangularity95
calc_separatrix_triangularity_from_triangularity95.return_keys = ['separatrix_triangularity']
calc_separatrix_triangularity_from_triangularity95.run(triangularity_ratio_sep_to_psi95)
calc_separatrix_triangularity_from_triangularity95.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_vertical_minor_radius_from_elongation_and_minor_radius
calc_vertical_minor_radius_from_elongation_and_minor_radius.return_keys = ['vertical_minor_radius']
calc_vertical_minor_radius_from_elongation_and_minor_radius.run(separatrix_elongation)
calc_vertical_minor_radius_from_elongation_and_minor_radius.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

integrate_profile_over_volume(
array_per_m3: Quantity | DataArray,
rho: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
) DataArray[source]

Approximate the volume integral of a profile given as a function of rho.

Parameters:
Returns:

volume_integrated_value [units]

integrate_profile_over_volume.unitless_func(
array_per_m3: ndarray[tuple[int, ...], dtype[float64]],
rho: ndarray[tuple[int, ...], dtype[float64]],
plasma_volume: float,
) float

A scalar and not unit aware version of the above function.

Metrics

Various metrics for operating points, generally used when we can’t fit something into another logical grouping.

calc_PB_over_R(
power_crossing_separatrix: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
major_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate P_sep*B0/R0, which scales roughly the same as the parallel heat flux density entering the scrape-off-layer.

calc_PBpRnSq(
power_crossing_separatrix: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
q_star: Quantity | DataArray,
major_radius: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate P_sep * B_pol / (R * n^2), which scales roughly the same as the impurity fraction required for detachment.

calc_alpha_t(
separatrix_electron_density: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
cylindrical_safety_factor: Quantity | DataArray,
major_radius: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
z_effective: Quantity | DataArray,
mean_ion_charge_state: Quantity | DataArray,
ion_to_electron_temp_ratio: float = 1.0,
) Quantity | DataArray[source]

Calculate the turbulence parameter alpha_t.

Equation 9 from [17]. Compared to this equation, the factor of the ion_to_electron_temp_ratio is added following a discussion with T. Eich.

Parameters:
Returns:

alpha_t

calc_average_electron_density_from_greenwald_fraction(
greenwald_fraction: Quantity | DataArray,
greenwald_density_limit: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average electron density corresponding to a given Greenwald fraction.

Parameters:
Returns:

average_electron_density in same units as greenwald_density_limit

calc_coulomb_logarithm(
electron_density: Quantity | DataArray,
electron_temp: Quantity | DataArray,
) DataArray[source]

Calculate the Coulomb logarithm, for electron-electron or electron-ion collisions.

From text on page 6 of [18]

calc_coulomb_logarithm.unitless_func(
electron_density: float,
electron_temp: float,
) float

A scalar and not unit aware version of the above function.

calc_edge_collisionality(
separatrix_electron_density: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
cylindrical_safety_factor: Quantity | DataArray,
major_radius: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
z_effective: Quantity | DataArray,
mean_ion_charge_state: Quantity | DataArray,
ion_to_electron_temp_ratio: float = 1.0,
) Quantity | DataArray[source]

Calculate the edge collisionality.

Equation 7 from [19].

Parameters:
Returns:

edge_collisionality

calc_greenwald_density_limit(
plasma_current: Quantity | DataArray,
minor_radius: Quantity | DataArray,
) DataArray[source]

Calculate the Greenwald density limit.

Parameters:
Returns:

greenwald_density_limit [1e20 m^-3]

calc_greenwald_density_limit.unitless_func(
plasma_current: float,
minor_radius: float,
) float

A scalar and not unit aware version of the above function.

calc_greenwald_fraction(
average_electron_density: Quantity | DataArray,
greenwald_density_limit: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the fraction of the Greenwald density limit.

Parameters:
Returns:

greenwald_fraction [~]

calc_larmor_radius(
species_temperature: Quantity | DataArray,
magnetic_field_strength: Quantity | DataArray,
species_mass: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the Larmor radius.

Equation 1 from [17]

calc_normalised_collisionality(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
q_star: Quantity | DataArray,
major_radius: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
z_effective: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate normalized collisionality.

Equation 1c from [18]

Extra factor of ureg.e**2, presumably related to electron_temp**-2 for electron_temp in eV

Parameters:
Returns:

nu_star [~]

calc_rho_star(
average_ion_mass: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
minor_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate rho* (normalized gyroradius).

Equation 1a from [18]

Parameters:
Returns:

rho_star [~]

Plasma Current

Routines to calculate the plasma current, safety factor and ohmic heating.

calc_Spitzer_loop_resistivity(
average_electron_temp: Quantity | DataArray,
) DataArray[source]

Calculate the parallel Spitzer loop resistivity assuming the Coulomb logarithm = 17 and Z=1.

Resistivity from Wesson 2.16.2 [20]

Parameters:

average_electron_temp – [keV] glossary link

Returns:

spitzer_resistivity [Ohm-m]

calc_Spitzer_loop_resistivity.unitless_func(average_electron_temp: float) float

A scalar and not unit aware version of the above function.

calc_bootstrap_fraction(
ion_density_peaking: Quantity | DataArray,
electron_density_peaking: Quantity | DataArray,
temperature_peaking: Quantity | DataArray,
z_effective: Quantity | DataArray,
q_star: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
beta_poloidal: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate bootstrap current fraction.

K. Gi et al, Bootstrap current fraction scaling [21] Equation assumes q0 = 1

Parameters:
Returns:

bootstrap_fraction [~]

calc_breakdown_flux_consumption(
major_radius: Quantity | DataArray,
) DataArray[source]

Calculate the resistive flux required for breakdown.

Plasma Design Considerations of Near Term Tokamak Fusion Experimental Reactor [2] NOTE: given the way the ejima_coefficient is empirically derived in [22] (i.e., with an implicit assumption that the ramp is defined from Ip=0) there is reason to believe a separate calculation for flux consumed over breakdown is not necessary, but it is included here anyways.

Parameters:

major_radius – [m] glossary link

Returns:

[weber] breakdown_flux_consumption

calc_breakdown_flux_consumption.unitless_func(major_radius: float) float

A scalar and not unit aware version of the above function.

calc_current_relaxation_time(
major_radius: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
z_effective: Quantity | DataArray,
) DataArray[source]

Calculate the current relaxation time.

from [23]

Parameters:
Returns:

current_relaxation_time [s]

calc_current_relaxation_time.unitless_func(
major_radius: float,
inverse_aspect_ratio: float,
areal_elongation: float,
average_electron_temp: float,
z_effective: float,
) float

A scalar and not unit aware version of the above function.

calc_cylindrical_edge_safety_factor(
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
elongation_psi95: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
plasma_current: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the edge safety factor, following the formula used in the SepOS paper.

Equation K.6 from [24]

Should use kappa_95 and delta_95 values.

Gives a slightly different result to our standard q_star calculation.

calc_external_flux(
plasma_current: Quantity | DataArray,
external_inductance: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the surface flux generated by the plasma current.

From: A power-balance model for local helicity injection startup in a spherical tokamak [3]

Parameters:
Returns:

[weber] external_flux

calc_external_inductance(
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
beta_poloidal: Quantity | DataArray,
major_radius: Quantity | DataArray,
internal_inductivity: Quantity | DataArray,
surface_inductance_coefficients: SurfaceInductanceCoeffs,
) Quantity | DataArray[source]

Calculate the external self-inductance of the plasma for which the current-induced surface flux of the plasma is generated from eq. 13 in [3].

A power-balance model for local helicity injection startup in a spherical tokamak [3]

Parameters:
Returns:

[henry] external_inductance

calc_f_shaping_for_qstar(
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the shaping function.

Equation A11 from ITER Physics Basis Ch. 1. Eqn. A-11 [25] See following discussion for how this function is used. q_95 = 5 * minor_radius^2 * magnetic_field_on_axis / (R * plasma_current) f_shaping

Parameters:
Returns:

f_shaping [~]

calc_flux_needed_from_solenoid_over_rampup(
internal_flux: Quantity | DataArray,
external_flux: Quantity | DataArray,
resistive_flux: Quantity | DataArray,
poloidal_field_flux: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the total flux needed from the central solenoid over rampup.

Sums together the required fluxes, subtracting the contribution from the poloidal field coils.

Parameters:
Returns:

[weber] flux_needed_from_CS_over_rampup

calc_inductive_plasma_current
calc_inductive_plasma_current.return_keys = ['inductive_plasma_current']
calc_inductive_plasma_current.run(bootstrap_fraction)
calc_inductive_plasma_current.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_internal_flux(
plasma_current: Quantity | DataArray,
internal_inductance: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the flux due to the plasma current and internal inductance of the plasma (assuming a circular cross-section).

From: A power-balance model for local helicity injection startup in a spherical tokamak [3] NOTE: This is (plasma current times) equation 25 from Barr but applied to a plasma with a circular cross-section and a non-cirular cross-section.

Parameters:
Returns:

[weber] internal_flux

calc_internal_inductance_for_cylindrical(
major_radius: Quantity | DataArray,
internal_inductivity: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the internal inductance of the plasma (assuming a circular cross-section).

TODO: what is the difference between inductivity and inductance?

A power-balance model for local helicity injection startup in a spherical tokamak [3]

Returns:

[henry] internal_inductance

calc_internal_inductance_for_noncylindrical(
plasma_volume: Quantity | DataArray,
poloidal_circumference: Quantity | DataArray,
internal_inductivity: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the internal inductance of the plasma.

TODO: what is the difference between inductivity and inductance?

A power-balance model for local helicity injection startup in a spherical tokamak [3]

Returns:

[henry] internal_inductance

calc_internal_inductivity(
cylindrical_safety_factor: Quantity | DataArray,
safety_factor_on_axis: Quantity | DataArray = 1.0,
) Quantity | DataArray[source]

Calculate the normalized internal inductance for an assumed circular plasma cross-section.

Tokamaks (pg.120): Physics [20]

TODO: Isaac please check if the implementation for cylindrical safety factor is consistent TODO: previous: cylindrical_safety_factor = 2 * np.pi * minor_radius**2 * magnetic_field_on_axis / (constants.mu_0 * major_radius * plasma_current)

Parameters:
Returns:

[~] internal_inductivity

calc_invmu_0_dLedR(
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
beta_poloidal: Quantity | DataArray,
internal_inductivity: Quantity | DataArray,
external_inductance: Quantity | DataArray,
major_radius: Quantity | DataArray,
surface_inductance_coefficients: SurfaceInductanceCoeffs,
) Quantity | DataArray[source]

Calculate eq. 21 on page 6 in [3].

A power-balance model for local helicity injection startup in a spherical tokamak [3]

Parameters:
Returns:

[~] invmu_0_dLedR

calc_loop_voltage(
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
inductive_plasma_current: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
neoclassical_loop_resistivity: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate plasma toroidal loop voltage at flattop.

Plasma loop voltage from Alex Creely’s original work.

Parameters:
Returns:

loop_voltage [V]

calc_max_flattop_duration(
total_flux_available_from_CS: Quantity | DataArray,
flux_needed_from_CS_over_rampup: Quantity | DataArray,
loop_voltage: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the maximum-duration flattop time that can be driven by the central solenoid.

Parameters:
Returns:

[seconds] max_flattop_duration

calc_neoclassical_loop_resistivity(
spitzer_resistivity: Quantity | DataArray,
z_effective: Quantity | DataArray,
trapped_particle_fraction: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the neoclassical loop resistivity including impurity ions.

Wesson Section 14.10. Impact of ion charge. Impact of dilution ~ 0.9.

Parameters:
Returns:

neoclassical_loop_resistivity [Ohm-m]

calc_ohmic_power(
inductive_plasma_current: Quantity | DataArray,
loop_voltage: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the Ohmic heating power.

Parameters:
Returns:

P_ohmic [MW]

calc_plasma_current_from_qstar(
magnetic_field_on_axis: Quantity | DataArray,
major_radius: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
q_star: Quantity | DataArray,
f_shaping: Quantity | DataArray,
) DataArray[source]

Calculate the plasma current in mega-amperes.

Updated formula from ITER Physics Basis Ch. 1. [25]

Parameters:
Returns:

plasma_current [MA]

calc_plasma_current_from_qstar.unitless_func(
magnetic_field_on_axis: float,
major_radius: float,
inverse_aspect_ratio: float,
q_star: float,
f_shaping: float,
) float

A scalar and not unit aware version of the above function.

calc_poloidal_field_flux(
vertical_field_mutual_inductance: Quantity | DataArray,
vertical_magnetic_field: Quantity | DataArray,
major_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the surface flux contribution from the vertical magnetic field required for radial force balance (which arises from the poloidal field coils).

From: A power-balance model for local helicity injection startup in a spherical tokamak [3]

Parameters:
Returns:

[weber] poloidal_field_flux

calc_q_star_from_plasma_current(
magnetic_field_on_axis: Quantity | DataArray,
major_radius: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
plasma_current: Quantity | DataArray,
f_shaping: Quantity | DataArray,
) DataArray[source]

Calculate an analytical estimate for the edge safety factor q_star.

Updated formula from ITER Physics Basis Ch. 1. [25]

Parameters:
Returns:

q_star [~]

calc_q_star_from_plasma_current.unitless_func(
magnetic_field_on_axis: float,
major_radius: float,
inverse_aspect_ratio: float,
plasma_current: float,
f_shaping: float,
) float

A scalar and not unit aware version of the above function.

calc_resistive_flux(
plasma_current: Quantity | DataArray,
major_radius: Quantity | DataArray,
ejima_coefficient: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the resistive flux.

Chapter 8: Plasma operation and control: Physics cite:Gribov_2007 NOTE: CE, the Ejima coefficient, is chosen by default to be 0.4, See for example… Chapter 8: Plasma operation and control: cite:Gribov_2007 Ohmic flux consumption during initial operation of the NSTX spherical torus [26]

Parameters:
Returns:

[weber] resistive_flux

calc_resistivity_trapped_enhancement(
inverse_aspect_ratio: Quantity | DataArray,
resistivity_trapped_enhancement_method: int = 3,
) Quantity | DataArray[source]

Calculate the enhancement of the plasma resistivity due to trapped particles.

Definition 1 is the denominator of eta_n (neoclassical resistivity) on p801 of Wesson [20]

Parameters:
Returns:

trapped_particle_fraction [~]

Raises:

NotImplementedError – if resistivity_trapped_enhancement_method doesn’t match an implementation

calc_vertical_field_mutual_inductance(
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
surface_inductance_coefficients: SurfaceInductanceCoeffs,
) Quantity | DataArray[source]

Calculate the mutual inductance linking the surface to the vertical field from eq. 15 in [3].

A power-balance model for local helicity injection startup in a spherical tokamak [3]

Parameters:
Returns:

[~] vertical_field_mutual_inductance

calc_vertical_magnetic_field(
inverse_aspect_ratio: Quantity | DataArray,
areal_elongation: Quantity | DataArray,
beta_poloidal: Quantity | DataArray,
internal_inductivity: Quantity | DataArray,
external_inductance: Quantity | DataArray,
major_radius: Quantity | DataArray,
plasma_current: Quantity | DataArray,
invmu_0_dLedR: Quantity | DataArray = 0,
vertical_magnetic_field_equation: VertMagneticFieldEq = VertMagneticFieldEq.Barr,
surface_inductance_coefficients: SurfaceInductanceCoeffs = SurfaceInductanceCoeffs.Hirshman,
) Quantity | DataArray[source]

Calculate the mutual inductance linking the surface to the vertical field from eq. 16 in [3].

A power-balance model for local helicity injection startup in a spherical tokamak [3]

Parameters:
Returns:

[T] vertical_magnetic_field

Plasma Pressure

Routines to calculate the plasma pressure, beta and related quantities.

calc_average_ion_temp_from_temperature_ratio
calc_average_ion_temp_from_temperature_ratio.return_keys = ['average_ion_temp']
calc_average_ion_temp_from_temperature_ratio.run(ion_to_electron_temp_ratio)
calc_average_ion_temp_from_temperature_ratio.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_average_total_pressure(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average total pressure.

calc_beta_normalized(
beta_total: Quantity | DataArray,
minor_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
plasma_current: Quantity | DataArray,
) Quantity | DataArray[source]

Normalize beta to stability (Troyon) parameters.

See section 6.18 in Wesson [20].

Parameters:
Returns:

normalized_beta

calc_beta_poloidal(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
plasma_current: Quantity | DataArray,
minor_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average ratio of the plasma pressure to the magnetic pressure due to the plasma current.

Calculates the poloidal magnetic field at radius a from the plasma current using equation 11.55 from Freidberg, “Plasma Physics and Fusion Energy” [27] and then evaluates beta_poloidal using equation 11.58 from Freidberg, “Plasma Physics and Fusion Energy” [27]

The unit_conversion_factor cancels the units, and can be calculated using the following

>>> from pint import Quantity
>>> from numpy import pi
>>> mu_0 = Quantity(1, "mu_0")
>>> I = Quantity(1, "MA")
>>> minor_radius = Quantity(1, "m")
>>> (mu_0 * I / (2 * pi * minor_radius)).to("T").units
<Unit('tesla')>
Parameters:
Returns:

beta_poloidal [~]

calc_beta_toroidal(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the average ratio of the plasma pressure to the magnetic pressure due to the toroidal field.

Also called beta_external, since the toroidal field is generated by external toroidal field coils. Using equation 11.58 from Freidberg, “Plasma Physics and Fusion Energy” [27]

Parameters:
Returns:

beta_toroidal [~]

calc_beta_total(
beta_toroidal: Quantity | DataArray,
beta_poloidal: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the total beta from the toroidal and poloidal betas.

Using equation 11.59 from Freidberg, “Plasma Physics and Fusion Energy” [27]

Parameters:
Returns:

beta_total [~]

calc_peak_pressure(
peak_electron_temp: Quantity | DataArray,
peak_ion_temp: Quantity | DataArray,
peak_electron_density: Quantity | DataArray,
peak_fuel_ion_density: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the peak pressure (needed for solving for the magnetic equilibrium).

Parameters:
Returns:

peak_pressure [Pa]

calc_troyon_limit(
minor_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
plasma_current: Quantity | DataArray,
) DataArray[source]

Calculate the maximum value for beta, according to the Troyon limit.

Parameters:
Returns:

troyon_max_beta [~]

calc_troyon_limit.unitless_func(
minor_radius: float,
magnetic_field_on_axis: float,
plasma_current: float,
) float

A scalar and not unit aware version of the above function.

Plasma Profiles

Routines to calculate estimate 1D profiles for the confined region.

calc_1D_plasma_profiles(
density_profile_form: ProfileForm,
temp_profile_form: ProfileForm,
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
electron_density_peaking: Quantity | DataArray,
ion_density_peaking: Quantity | DataArray,
temperature_peaking: Quantity | DataArray,
dilution: Quantity | DataArray,
normalized_inverse_temp_scale_length: Quantity | DataArray,
n_points_for_confined_region_profiles: int = 50,
) tuple[DataArray, DataArray, DataArray, DataArray, DataArray][source]

Estimate density and temperature profiles.

Parameters:
Returns:

rho [~], electron_density_profile [1e19 m^-3], fuel_ion_density_profile [1e19 m^-3], electron_temp_profile [keV], ion_temp_profile [keV]

calc_1D_plasma_profiles.unitless_func(
density_profile_form: ProfileForm,
temp_profile_form: ProfileForm,
average_electron_density: float,
average_electron_temp: float,
average_ion_temp: float,
electron_density_peaking: float,
ion_density_peaking: float,
temperature_peaking: float,
dilution: float,
normalized_inverse_temp_scale_length: float,
n_points_for_confined_region_profiles: int = 50,
) tuple[ndarray, ndarray, ndarray, ndarray, ndarray]

A scalar and not unit aware version of the above function.

calc_density_peaking(
effective_collisionality: Quantity | DataArray,
beta_toroidal: Quantity | DataArray,
nu_noffset: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the density peaking (peak over volume average).

Equation 3 from p1334 of Angioni et al, “Scaling of density peaking in H-mode plasmas based on a combined database of AUG and JET observations” [28]

Parameters:
  • effective_collisionality – [~] glossary link

  • beta_toroidalglossary link [~]

  • nu_noffset – scalar offset added to peaking factor [~]

Returns:

nu_n [~]

calc_effective_collisionality(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
major_radius: Quantity | DataArray,
z_effective: Quantity | DataArray,
) DataArray[source]

Calculate the effective collisionality.

From p1327 of Angioni et al, “Scaling of density peaking in H-mode plasmas based on a combined database of AUG and JET observations” [28]

Parameters:
Returns:

effective_collisionality [~]

calc_effective_collisionality.unitless_func(
average_electron_density: float,
average_electron_temp: float,
major_radius: float,
z_effective: float,
) float

A scalar and not unit aware version of the above function.

calc_electron_density_peaking(
effective_collisionality: Quantity | DataArray,
beta_toroidal: Quantity | DataArray,
electron_density_peaking_offset: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Calculate the electron density peaking.

Parameters:
Returns:

electron_density_peaking, peak_electron_density

calc_ion_density_peaking(
effective_collisionality: Quantity | DataArray,
beta_toroidal: Quantity | DataArray,
ion_density_peaking_offset: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
dilution: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Calculate the ion density peaking.

Parameters:
Returns:

ion_density_peaking, peak_fuel_ion_density

calc_peaked_profiles(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
ion_density_peaking_offset: Quantity | DataArray,
electron_density_peaking_offset: Quantity | DataArray,
temperature_peaking: Quantity | DataArray,
major_radius: Quantity | DataArray,
z_effective: Quantity | DataArray,
dilution: Quantity | DataArray,
beta_toroidal: Quantity | DataArray,
normalized_inverse_temp_scale_length: Quantity | DataArray,
density_profile_form: ProfileForm,
temp_profile_form: ProfileForm,
) tuple[Quantity | DataArray, ...][source]

Calculate density peaking and the corresponding density and temperature profiles.

Parameters:

Returns: effective_collisionality, ion_density_peaking, electron_density_peaking, peak_electron_density, peak_electron_temp, peak_ion_temp, rho, electron_density_profile, fuel_ion_density_profile, electron_temp_profile, ion_temp_profile

calc_temperature_peaking(
average_electron_temp: Quantity | DataArray,
average_ion_temp: Quantity | DataArray,
temperature_peaking: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Apply the temperature peaking.

Parameters:
Returns:

peak_electron_temp, peak_ion_temp

Separatrix Conditions

Calculate the power crossing the separatrix and the threshold values for confinement-regime transitions.

calc_LH_transition_threshold_power(
plasma_current: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
minor_radius: Quantity | DataArray,
major_radius: Quantity | DataArray,
surface_area: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
confinement_power_scaling: ConfinementPowerScaling = ConfinementPowerScaling.H_mode_Martin,
confinement_threshold_scalar: Quantity | DataArray = 1.0,
) DataArray[source]

Calculate the threshold power (crossing the separatrix) to transition into H-mode.

From Martin NF 2008 Scaling, with mass correction [29] Added in low density branch from Ryter 2014 [30]

Parameters:
Returns:

P_LH_thresh [MW]

calc_LH_transition_threshold_power.unitless_func(
plasma_current: float,
magnetic_field_on_axis: float,
minor_radius: float,
major_radius: float,
surface_area: float,
average_ion_mass: float,
average_electron_density: float,
confinement_power_scaling: ConfinementPowerScaling = ConfinementPowerScaling.H_mode_Martin,
confinement_threshold_scalar: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_LI_transition_threshold_power(
plasma_current: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
surface_area: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
confinement_power_scaling: ConfinementPowerScaling = ConfinementPowerScaling.I_mode_HubbardNF17,
confinement_threshold_scalar: Quantity | DataArray = 1.0,
) DataArray[source]

Calculate the threshold power (crossing the separatrix) to transition into I-mode.

Note

“AUG” option is inspired from [31] and [32] “HubbardNF17” uses scaling described in Fig 6 of [33] “HubbardNF12” uses scaling described in Fig 5 of ref [34]

Parameters:
Returns:

P_LI_thresh [MW]

calc_LI_transition_threshold_power.unitless_func(
plasma_current: float,
magnetic_field_on_axis: float,
surface_area: float,
average_electron_density: float,
confinement_power_scaling: ConfinementPowerScaling = ConfinementPowerScaling.I_mode_HubbardNF17,
confinement_threshold_scalar: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_SepOS_LH_transition(
separatrix_electron_density: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
major_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
critical_alpha_MHD: Quantity | DataArray,
alpha_t: Quantity | DataArray,
poloidal_sound_larmor_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate a condition function which gives the LH transition at SepOS_LH_transition=1.

If SepOS_LH_transition < 1, the operating point will be in L-mode If SepOS_LH_transition > 1, the operating point will be in H-mode

Equation 8 from [24]

Parameters:
Returns:

SepOS_LH_transition

calc_SepOS_L_mode_density_limit(
separatrix_electron_density: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
major_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
critical_alpha_MHD: Quantity | DataArray,
alpha_t: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate a condition function which gives the L-mode density limit when SepOS_density_limit=1.

If SepOS_density_limit < 1, the operating point is stable If SepOS_density_limit > 1, the operating point will disrupt if not above the LH transition

Equation 3 from [24]

Parameters:
Returns:

SepOS_density_limit

calc_SepOS_ideal_MHD_limit(
separatrix_electron_density: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
major_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
cylindrical_safety_factor: Quantity | DataArray,
critical_alpha_MHD: Quantity | DataArray,
alpha_t: Quantity | DataArray,
poloidal_sound_larmor_radius: Quantity | DataArray,
ion_to_electron_temp_ratio: float = 1.0,
) Quantity | DataArray[source]

Calculate a condition function which gives the ideal MHD limit at SepOS_MHD_limit=1.

If SepOS_MHD_limit < 1, the operating point is stable If SepOS_MHD_limit > 1, the transport will increase until SepOS_MHD_limit < 1 (soft limit)

Equation 12 from [24]

Parameters:
Returns:

SepOS_MHD_limit

calc_critical_alpha_MHD(
elongation_psi95: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the critical value of alpha_MHD.

Equation K.5 from [24]

calc_poloidal_sound_larmor_radius(
minor_radius: Quantity | DataArray,
elongation_psi95: Quantity | DataArray,
triangularity_psi95: Quantity | DataArray,
plasma_current: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the poloidally-averaged sound Larmor radius (rho_s_pol).

Equation K.4 from [24], using B_pol from equations K.6 and K.7.

Parameters:
Returns:

poloidal_sound_larmor_radius

calc_power_crossing_separatrix(
P_in: Quantity | DataArray,
P_radiation: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the power crossing the separatrix.

calc_power_crossing_separatrix_in_electron_channel(
separatrix_electron_temp: Quantity | DataArray,
target_electron_temp: Quantity | DataArray,
cylindrical_safety_factor: Quantity | DataArray,
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
B_pol_out_mid: Quantity | DataArray,
B_t_out_mid: Quantity | DataArray,
fraction_of_P_SOL_to_divertor: Quantity | DataArray,
z_effective: Quantity | DataArray,
alpha_t: Quantity | DataArray,
poloidal_sound_larmor_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the power crossing the separatrix for a given separatrix temperature.

Equation 11 from [24], inverting the Spitzer-Harm power balance.

Parameters:
Returns:

sustainment_power_in_electron_channel

calc_power_crossing_separatrix_in_ion_channel(
surface_area: Quantity | DataArray,
separatrix_electron_density: Quantity | DataArray,
separatrix_electron_temp: Quantity | DataArray,
alpha_t: Quantity | DataArray,
poloidal_sound_larmor_radius: Quantity | DataArray,
ion_heat_diffusivity: Quantity | DataArray,
temp_scale_length_ratio: float = 1.0,
) Quantity | DataArray[source]

Calculate the power crossing the separatrix in the ion channel.

This algorithm computes the power required to sustain a particular ion temperature gradient, given a ion heat diffusivity, using the method from section 4.1 in [24].

temp_scale_length_ratio = Ti / Te * lambda_Te / lambda_Ti = L_Te / L_Ti

Parameters:
Returns:

sustainment_power_in_ion_channel

calc_ratio_P_LH
calc_ratio_P_LH.return_keys = ['ratio_of_P_SOL_to_P_LH']
calc_ratio_P_LH.run(P_LH_thresh)
calc_ratio_P_LH.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_ratio_P_LI
calc_ratio_P_LI.return_keys = ['ratio_of_P_SOL_to_P_LI']
calc_ratio_P_LI.run(P_LI_thresh)
calc_ratio_P_LI.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

Radiated Power

Routines to calculate the radiated power due to Bremsstrahlung, synchrotron and impurity-line radiation.

calc_P_rad_hydrogen_bremsstrahlung
calc_P_rad_hydrogen_bremsstrahlung.return_keys = ['P_rad_hydrogen_bremsstrahlung']
calc_P_rad_hydrogen_bremsstrahlung.run(
electron_density_profile,
electron_temp_profile,
plasma_volume,
)
calc_P_rad_hydrogen_bremsstrahlung.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_bremsstrahlung_radiation(
rho: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
z_effective: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
) DataArray[source]

Calculate the Bremsstrahlung radiated power due to the main plasma.

Formula 13 in [35]

Parameters:
Returns:

Radiated bremsstrahlung power per cubic meter [MW / m^3]

calc_bremsstrahlung_radiation.unitless_func(
rho: ndarray[tuple[int, ...], dtype[float64]],
electron_density_profile: ndarray[tuple[int, ...], dtype[float64]],
electron_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
z_effective: float,
plasma_volume: float,
) float

A scalar and not unit aware version of the above function.

calc_f_rad_core
calc_f_rad_core.return_keys = ['core_radiated_power_fraction']
calc_f_rad_core.run(P_in)
calc_f_rad_core.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

calc_impurity_radiated_power(
radiated_power_method: RadiationMethod,
rho: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
impurity_concentration: DataArray,
plasma_volume: Quantity | DataArray,
atomic_data: AtomicData,
) DataArray[source]

Compute the total radiated power due to fuel and impurity species.

Parameters:
Returns:

[MW] Estimated radiation power due to this impurity

calc_impurity_radiated_power_mavrin_coronal(
rho: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
impurity_concentration: Quantity | DataArray,
impurity_species: AtomicSpecies,
plasma_volume: Quantity | DataArray,
) DataArray[source]

Calculation of radiated power, using fits from A.A. Mavrin’s 2018 paper.

“Improved fits of coronal radiative cooling rates for high-temperature plasmas.”

[36]

Parameters:
Returns:

k [MW] Estimated radiation power due to this impurity

calc_impurity_radiated_power_mavrin_coronal.unitless_func(
rho: ndarray[tuple[int, ...], dtype[float64]],
electron_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
electron_density_profile: ndarray[tuple[int, ...], dtype[float64]],
impurity_concentration: float,
impurity_species: AtomicSpecies,
plasma_volume: float,
) float

A scalar and not unit aware version of the above function.

calc_impurity_radiated_power_mavrin_noncoronal(
rho: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
impurity_residence_time: Quantity | DataArray,
impurity_concentration: Quantity | DataArray,
impurity_species: AtomicSpecies,
plasma_volume: Quantity | DataArray,
) DataArray[source]

Calculation of radiated power, using fits from A.A. Mavrin’s 2017 paper.

“Radiative Cooling Rates for Low-Z Impurities in Non-coronal Equilibrium State.”

[37]

Parameters:
Returns:

[MW] Estimated radiation power due to this impurity

calc_impurity_radiated_power_mavrin_noncoronal.unitless_func(
rho: ndarray[tuple[int, ...], dtype[float64]],
electron_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
electron_density_profile: ndarray[tuple[int, ...], dtype[float64]],
impurity_residence_time: Quantity,
impurity_concentration: float,
impurity_species: AtomicSpecies,
plasma_volume: float,
) float

A scalar and not unit aware version of the above function.

calc_impurity_radiated_power_post_and_jensen(
rho: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
impurity_concentration: Quantity | DataArray,
impurity_species: AtomicSpecies,
plasma_volume: Quantity | DataArray,
) DataArray[source]

Calculation of radiated power using Post & Jensen 1977.

Radiation fits to the Post & Jensen cooling curves, which use the coronal equilibrium model with data in [38].

Parameters:
Returns:

[MW] Estimated radiation power due to this impurity

calc_impurity_radiated_power_post_and_jensen.unitless_func(
rho: ndarray[tuple[int, ...], dtype[float64]],
electron_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
electron_density_profile: ndarray[tuple[int, ...], dtype[float64]],
impurity_concentration: float,
impurity_species: AtomicSpecies,
plasma_volume: float,
) float

A scalar and not unit aware version of the above function.

calc_impurity_radiated_power_radas(
rho: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
impurity_concentration: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
atomic_data: AtomicData,
) Quantity | DataArray[source]

Calculation of radiated power using radas atomic_data datasets.

Parameters:
Returns:

[MW] Estimated radiation power due to this impurity

calc_intrinsic_radiated_power_from_core(
rho: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
z_effective: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
separatrix_elongation: Quantity | DataArray,
radiated_power_method: RadiationMethod,
radiated_power_scalar: Quantity | DataArray,
impurity_concentration: DataArray,
atomic_data: DataArray,
) Quantity | DataArray[source]

Calculate the power radiated from the confined region due to the fuel and impurity species.

Parameters:
Returns:

P_radiation

calc_synchrotron_radiation(
rho: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
separatrix_elongation: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
) DataArray[source]

Calculate the Synchrotron radiated power due to the main plasma.

This can be an important loss mechanism in high temperature plasmas.

Formula 15 in [35]

For now this calculation assumes 90% wall reflectivity, consistent with stott_feasibility_2005.

This calculation also assumes profiles of the form n(r) = n[1 - (r/a)**2]**alpha_n and T(r) = Tedge + (T - Tedge)[1 - (r/a)**gamma_T]**alpha_T. For now, these are assumed as gamma_T = 2, alpha_n = 0.5 and alpha_T = 1, consistent with stott_feasibility_2005.

An alternative approach could be developed using formula 6 in [39], which assumes 80% wall reflectivity.

Parameters:
Returns:

Radiated bremsstrahlung power per cubic meter [MW / m^3]

calc_synchrotron_radiation.unitless_func(
rho: ndarray[tuple[int, ...], dtype[float64]],
electron_density_profile: ndarray[tuple[int, ...], dtype[float64]],
electron_temp_profile: ndarray[tuple[int, ...], dtype[float64]],
major_radius: float,
minor_radius: float,
magnetic_field_on_axis: float,
separatrix_elongation: float,
plasma_volume: float,
) float

A scalar and not unit aware version of the above function.

require_P_rad_less_than_P_in
require_P_rad_less_than_P_in.return_keys = ['P_radiation']
require_P_rad_less_than_P_in.run(P_radiation)
require_P_rad_less_than_P_in.update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

Scrape Off Layer

Routines to calculate the scrape-off-layer conditions and check divertor survivability.

calc_B_pol_omp(
plasma_current: Quantity | DataArray,
minor_radius: Quantity | DataArray,
) DataArray[source]

Calculate the poloidal magnetic field at the outboard midplane.

Parameters:
Returns:

B_pol_out_mid [T]

calc_B_pol_omp.unitless_func(plasma_current: float, minor_radius: float) float

A scalar and not unit aware version of the above function.

calc_B_tor_omp(
magnetic_field_on_axis: Quantity | DataArray,
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the toroidal magnetic field at the outboard midplane.

Parameters:
Returns:

B_t_out_mid [T]

calc_fieldline_pitch_at_omp(
B_t_out_mid: Quantity | DataArray,
B_pol_out_mid: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the pitch of the magnetic field at the outboard midplane.

Parameters:
Returns:

fieldline_pitch_at_omp [~]

calc_ionization_volume_from_AUG(
plasma_volume: Quantity | DataArray,
) Quantity | DataArray[source]

Calculates ionization volume using major radius and AUG ionization volume.

AUG ionization volume per [40] page 8 RH column

Parameters:

plasma_volume – [m**3] glossary link

Returns:

ionization_volume [m**3]

calc_lambda_q(
lambda_q_scaling: LambdaQScaling,
average_total_pressure: Quantity | DataArray,
power_crossing_separatrix: Quantity | DataArray,
major_radius: Quantity | DataArray,
B_pol_out_mid: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
magnetic_field_on_axis: Quantity | DataArray,
q_star: Quantity | DataArray,
lambda_q_factor: Quantity | DataArray = 1.0,
) DataArray[source]

Calculate SOL heat flux decay length (lambda_q) from a scaling.

Parameters:
Returns:

lambda_q [mm]

calc_lambda_q.unitless_func(
lambda_q_scaling: LambdaQScaling,
average_total_pressure: float,
power_crossing_separatrix: float,
major_radius: float,
B_pol_out_mid: float,
inverse_aspect_ratio: float,
magnetic_field_on_axis: float,
q_star: float,
lambda_q_factor: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_lambda_q_with_brunner(
average_total_pressure: Quantity | DataArray,
lambda_q_factor: Quantity | DataArray = 1.0,
) DataArray[source]

Return lambda_q according to the Brunner scaling.

Equation 4 in [41]

calc_lambda_q_with_brunner.unitless_func(
average_total_pressure: float,
lambda_q_factor: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_lambda_q_with_eich_regression_9(
magnetic_field_on_axis: Quantity | DataArray,
q_star: Quantity | DataArray,
power_crossing_separatrix: Quantity | DataArray,
lambda_q_factor: Quantity | DataArray = 1.0,
) DataArray[source]

Return lambda_q according to Eich regression 9.

#9 in Table 2 in [42]

calc_lambda_q_with_eich_regression_9.unitless_func(
magnetic_field_on_axis: float,
q_star: float,
power_crossing_separatrix: float,
lambda_q_factor: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_lambda_q_with_eich_regression_14(
B_pol_out_mid: Quantity | DataArray,
lambda_q_factor: Quantity | DataArray = 1.0,
) DataArray[source]

Return lambda_q according to Eich regression 14.

#14 in Table 3 in [42]

calc_lambda_q_with_eich_regression_14.unitless_func(
B_pol_out_mid: float,
lambda_q_factor: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_lambda_q_with_eich_regression_15(
power_crossing_separatrix: Quantity | DataArray,
major_radius: Quantity | DataArray,
B_pol_out_mid: Quantity | DataArray,
inverse_aspect_ratio: Quantity | DataArray,
lambda_q_factor: Quantity | DataArray = 1.0,
) DataArray[source]

Return lambda_q according to Eich regression 15.

#15 in Table 3 in [42]

calc_lambda_q_with_eich_regression_15.unitless_func(
power_crossing_separatrix: float,
major_radius: float,
B_pol_out_mid: float,
inverse_aspect_ratio: float,
lambda_q_factor: float = 1.0,
) float

A scalar and not unit aware version of the above function.

calc_neutral_flux_density_factor(
average_ion_mass: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
ratio_of_molecular_to_ion_mass: ~pint.Quantity | ~xarray.core.dataarray.DataArray = 2.0,
wall_temperature: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(300.0,
'kelvin')>,
) Quantity | DataArray[source]

Calculate a factor to convert from a flux density to a pressure.

calc_neutral_pressure_kallenbach(
average_ion_mass: Quantity | DataArray,
kappa_e0: Quantity | DataArray,
kappa_ez: Quantity | DataArray,
parallel_connection_length: Quantity | DataArray,
target_angle_of_incidence: Quantity | DataArray,
lambda_q: Quantity | DataArray,
target_gaussian_spreading: Quantity | DataArray,
sheath_heat_transmission_factor: Quantity | DataArray,
neutral_flux_density_factor: Quantity | DataArray,
SOL_power_loss_fraction: Quantity | DataArray,
SOL_momentum_loss_function: Quantity | DataArray,
separatrix_electron_density: Quantity | DataArray,
target_electron_temp: Quantity | DataArray,
q_parallel: Quantity | DataArray,
ratio_of_divertor_to_duct_pressure: Quantity | DataArray,
) Quantity | DataArray[source]

Calculates target neutral pressure, p0, as a function of upstream separatrix density and some other variables.

Similar to equation 6 from [43] and equation 2 from [40], rearranged for p0. Note that Henderson uses frad and fmom as (1 - …) compared to Kallenbach and our definition of these terms.

Parameters:
Returns:

target_neutral_pressure [Pa]

calc_parallel_heat_flux_density(
power_crossing_separatrix: Quantity | DataArray,
fraction_of_P_SOL_to_divertor: Quantity | DataArray,
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
lambda_q: Quantity | DataArray,
fieldline_pitch_at_omp: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the parallel heat flux density entering a flux tube (q_par) at the outboard midplane.

This expression is power to target divided by the area perpendicular to the flux tube. 1. Power to target = power crossing separatrix * fraction of that power going to the target considered 2. The poloidal area of a ring at the outboard midplane is 2 * pi * (R + minor_radius) * width 3. For the width, we take the heat flux decay length lambda_q 4. P_SOL * f_share / (2 * pi * (R + minor_radius) lambda_q) gives the heat flux per poloidal area 5. We project this poloidal heat flux density into a parallel heat flux density by dividing by the field-line pitch

Parameters:
Returns:

q_parallel [GW/m^2]

calc_q_perp(
power_crossing_separatrix: Quantity | DataArray,
major_radius: Quantity | DataArray,
minor_radius: Quantity | DataArray,
lambda_q: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the perpendicular heat flux at the outboard midplane.

Parameters:
Returns:

q_perp [MW/m^2]

calc_reattachment_time_henderson(
target_neutral_pressure: Quantity | DataArray,
target_electron_density: Quantity | DataArray,
parallel_connection_length: Quantity | DataArray,
separatrix_power_transient: Quantity | DataArray,
ionization_volume_density_factor: Quantity | DataArray,
ionization_volume: Quantity | DataArray,
) Quantity | DataArray[source]

Calculates the reattachment time for a detachment front to move to e^-5 * original front location from the target.

Values are normalized to AUG. Equation 5 from [40]

Parameters:
Returns:

reattachment_time [s]

calc_separatrix_electron_density(
nesep_over_nebar: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
) Quantity | DataArray[source]

Calculate the separatrix electron density, assuming a constant ratio to the average electron density.

calc_separatrix_electron_temp(
target_electron_temp: Quantity | DataArray,
q_parallel: Quantity | DataArray,
parallel_connection_length: Quantity | DataArray,
kappa_e0: Quantity | DataArray,
SOL_conduction_fraction: float | DataArray = 1.0,
) Quantity | DataArray[source]

Calculate the upstream electron temperature assuming Spitzer-Harm heat conductivity.

Equation 38 from [44], keeping the dependence on target_electron_temp.

Parameters:
Returns:

separatrix_electron_temp [eV]

solve_target_first_two_point_model(
target_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
q_parallel: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
parallel_connection_length: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
separatrix_electron_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
toroidal_flux_expansion: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
average_ion_mass: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
kappa_e0: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
SOL_momentum_loss_function: ~cfspopcon.named_options.MomentumLossFunction | ~xarray.core.dataarray.DataArray,
sheath_heat_transmission_factor: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(7.5,
'dimensionless')>,
SOL_conduction_fraction: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
target_ratio_of_ion_to_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
target_ratio_of_electron_to_ion_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
target_mach_number: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
upstream_ratio_of_ion_to_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
upstream_ratio_of_electron_to_ion_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
upstream_mach_number: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(0.0,
'dimensionless')>,
) tuple[Quantity | DataArray, Quantity | DataArray, Quantity | DataArray, Quantity | DataArray][source]

Calculate the SOL_power_loss_fraction required to keep the target temperature at a given value.

Parameters:
  • target_electron_temp – [eV]

  • q_parallel – [GW/m^2]

  • parallel_connection_length – [m]

  • separatrix_electron_density – [m^-3]

  • toroidal_flux_expansion – [~]

  • average_ion_mass – [~]

  • kappa_e0 – electron heat conductivity constant [W / (eV^3.5 * m)]

  • SOL_momentum_loss_function – which momentum loss function to use

  • sheath_heat_transmission_factor – [~]

  • SOL_conduction_fraction – [~]

  • target_ratio_of_ion_to_electron_temp – [~]

  • target_ratio_of_electron_to_ion_density – [~]

  • target_mach_number – [~]

  • upstream_ratio_of_ion_to_electron_temp – [~]

  • upstream_ratio_of_electron_to_ion_density – [~]

  • upstream_mach_number – [~]

Returns:

SOL_power_loss_fraction [~], separatrix_electron_temp [eV], target_electron_density [m^-3], target_electron_flux [m^-2 s^-1]

solve_two_point_model(
SOL_power_loss_fraction: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
q_parallel: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
parallel_connection_length: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
separatrix_electron_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
toroidal_flux_expansion: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
average_ion_mass: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
kappa_e0: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
SOL_momentum_loss_function: ~cfspopcon.named_options.MomentumLossFunction | ~xarray.core.dataarray.DataArray,
initial_target_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(10.0,
'electron_volt')>,
sheath_heat_transmission_factor: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(7.5,
'dimensionless')>,
SOL_conduction_fraction: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
target_ratio_of_ion_to_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
target_ratio_of_electron_to_ion_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
target_mach_number: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
upstream_ratio_of_ion_to_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
upstream_ratio_of_electron_to_ion_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'dimensionless')>,
upstream_mach_number: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(0.0,
'dimensionless')>,
max_iterations: int = 100,
upstream_temp_relaxation: float = 0.5,
target_electron_density_relaxation: float = 0.5,
target_temp_relaxation: float = 0.5,
upstream_temp_max_residual: float = 0.01,
target_electron_density_max_residual: float = 0.01,
target_temp_max_residual: float = 0.01,
two_point_model_error_nonconverged_error: bool = True,
quiet: bool = True,
) tuple[Quantity | DataArray, Quantity | DataArray, Quantity | DataArray, Quantity | DataArray][source]

Calculate the upstream and target electron temperature and target electron density according to the extended two-point-model.

Parameters:
  • SOL_power_loss_fraction – [~]

  • q_parallel – [GW/m^2]

  • parallel_connection_length – [m]

  • separatrix_electron_density – [m^-3]

  • toroidal_flux_expansion – [~]

  • average_ion_mass – [~]

  • kappa_e0 – electron heat conductivity constant [W / (eV^3.5 * m)]

  • SOL_momentum_loss_function – which momentum loss function to use

  • initial_target_electron_temp – starting guess for target electron temp [eV]

  • sheath_heat_transmission_factor – [~]

  • SOL_conduction_fraction – [~]

  • target_ratio_of_ion_to_electron_temp – [~]

  • target_ratio_of_electron_to_ion_density – [~]

  • target_mach_number – [~]

  • upstream_ratio_of_ion_to_electron_temp – [~]

  • upstream_ratio_of_electron_to_ion_density – [~]

  • upstream_mach_number – [~]

  • max_iterations – how many iterations to try before returning NaN

  • upstream_temp_relaxation – step-size for upstream Te evolution

  • target_electron_density_relaxation – step-size for target ne evolution

  • target_temp_relaxation – step-size for target Te evolution

  • upstream_temp_max_residual – relative rate of change for convergence for upstream Te evolution

  • target_electron_density_max_residual – relative rate of change for convergence for target ne evolution

  • target_temp_max_residual – relative rate of change for convergence for target Te evolution

  • two_point_model_error_nonconverged_error – raise an error if not all point converge within max iterations (otherwise return NaN)

  • quiet – if not True, print additional information about the iterative solve to terminal

Returns:

separatrix_electron_temp [eV], target_electron_density [m^-3], target_electron_temp [eV], target_electron_flux [m^-2 s^-1]

two_point_model_fixed_fpow(
SOL_power_loss_fraction: Quantity | DataArray,
q_parallel: Quantity | DataArray,
parallel_connection_length: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
nesep_over_nebar: Quantity | DataArray,
toroidal_flux_expansion: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
kappa_e0: Quantity | DataArray,
SOL_momentum_loss_function: MomentumLossFunction | DataArray,
sheath_heat_transmission_factor: Quantity | DataArray,
two_point_model_error_nonconverged_error: bool = False,
) tuple[Quantity | DataArray, ...][source]

Run the two point model with a fixed power loss fraction in the SOL.

Parameters:
Returns:

separatrix_electron_temp, target_electron_density, target_electron_temp, target_electron_flux, target_q_parallel,

two_point_model_fixed_qpart(
target_q_parallel: Quantity | DataArray,
q_parallel: Quantity | DataArray,
parallel_connection_length: Quantity | DataArray,
average_electron_density: Quantity | DataArray,
nesep_over_nebar: Quantity | DataArray,
toroidal_flux_expansion: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
kappa_e0: Quantity | DataArray,
SOL_momentum_loss_function: MomentumLossFunction | DataArray,
sheath_heat_transmission_factor: Quantity | DataArray,
two_point_model_error_nonconverged_error: bool = False,
) tuple[Quantity | DataArray, ...][source]

Run the two point model with a fixed parallel heat flux density reaching the target.

Parameters:
Returns:

separatrix_electron_temp, target_electron_density, target_electron_temp, target_electron_flux, SOL_power_loss_fraction,

two_point_model_fixed_tet(
target_electron_temp: Quantity | DataArray,
q_parallel: Quantity | DataArray,
parallel_connection_length: Quantity | DataArray,
separatrix_electron_density: Quantity | DataArray,
toroidal_flux_expansion: Quantity | DataArray,
average_ion_mass: Quantity | DataArray,
kappa_e0: Quantity | DataArray,
SOL_momentum_loss_function: MomentumLossFunction | DataArray,
sheath_heat_transmission_factor: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Run the two point model with a fixed sheath entrance temperature.

Parameters:
Returns:

separatrix_electron_temp, target_electron_density, SOL_power_loss_fraction, target_electron_flux, target_q_parallel,

Impurity seeding, dilution and Z-effective

Routines to calculate seeded impurity concentrations and the change in effective charge and dilution due to seeded and intrinsic impurities.

calc_P_radiation_from_core_seeded_impurity(
P_radiation: Quantity | DataArray,
min_P_radiation: Quantity | DataArray,
) tuple[Quantity | DataArray, ...][source]

Increases P_radiation until it is at least min_P_radiation.

If P_radiation > min_P_radiation, this does nothing.

If P_radiation < min_P_radiation, it is assumed some core seed impurity will be injected to increased P_radiation until it reaches min_P_radiation. The additional radiated power is returned as P_radiation_from_core_seeded_impurity

Parameters:
Returns:

P_radiation, P_radiation_from_core_seeded_impurity

calc_core_seeded_impurity_concentration(
P_radiation_from_core_seeded_impurity: Quantity | DataArray,
impurity_concentration: Quantity | DataArray,
rho: Quantity | DataArray,
electron_density_profile: Quantity | DataArray,
electron_temp_profile: Quantity | DataArray,
plasma_volume: Quantity | DataArray,
radiated_power_method: RadiationMethod,
radiated_power_scalar: Quantity | DataArray,
core_impurity_species: AtomicSpecies,
atomic_data: DataArray | AtomicData,
) Quantity | DataArray[source]

Calculate the concentration of a core radiator required to increase the radiated power by a desired amount.

Parameters:
Returns:

impurity_concentration

calc_edge_impurity_concentration(
edge_impurity_species: ~cfspopcon.named_options.AtomicSpecies,
q_parallel: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
SOL_power_loss_fraction: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
target_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
separatrix_electron_temp: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
separatrix_electron_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
kappa_e0: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
lengyel_overestimation_factor: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
edge_impurity_enrichment: ~pint.Quantity | ~xarray.core.dataarray.DataArray,
impurity_concentration: ~xarray.core.dataarray.DataArray,
atomic_data: ~xarray.core.dataarray.DataArray | ~cfspopcon.formulas.atomic_data.atomic_data.AtomicData,
reference_electron_density: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'_1e20_per_cubic_metre')>,
reference_ne_tau: ~pint.Quantity | ~xarray.core.dataarray.DataArray = <Quantity(1.0,
'_1e20_per_cubic_metre * millisecond')>,
) tuple[Quantity | DataArray, ...][source]

Calculate the impurity concentration required to cool the scrape-off-layer using the Lengyel model.

Parameters:
Returns:

edge_impurity_concentration, edge_impurity_concentration_in_core, impurity_concentration

calc_impurity_charge_state(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
impurity_concentration: DataArray,
atomic_data: AtomicData | DataArray,
) Quantity | DataArray[source]

Calculate the impurity charge state for each species in impurity_concentration.

Parameters:
Returns:

impurity_charge_state

calc_min_P_radiation_from_LH_factor(
maximum_P_LH_factor_for_P_SOL: Quantity | DataArray,
P_LH_thresh: Quantity | DataArray,
P_in: Quantity | DataArray,
) Quantity | DataArray[source]

Set the minimum radiated power such that P_sol doesn’t go above some multiple of the LH threshold power.

Parameters:
Returns:

min_P_radiation

calc_min_P_radiation_from_fraction(
minimum_core_radiated_fraction: Quantity | DataArray,
P_in: Quantity | DataArray,
) Quantity | DataArray[source]

Set the minimum radiated power as a fraction of the total input power.

Parameters:
Returns:

min_P_radiation

calc_zeff_and_dilution_due_to_impurities(
average_electron_density: Quantity | DataArray,
average_electron_temp: Quantity | DataArray,
impurity_concentration: DataArray,
atomic_data: DataArray,
) tuple[Quantity | DataArray, ...][source]

Calculate the impact of core impurities on z_effective and dilution.

Parameters:
Returns:

impurity_charge_state, change_in_zeff, change_in_dilution, z_effective, dilution, summed_impurity_density, average_ion_density

set_up_impurity_concentration_array(
intrinsic_impurity_concentration: Quantity | DataArray,
) Quantity | DataArray[source]

Set up the impurity concentration array, starting with the intrinsic impurities.

Parameters:

intrinsic_impurity_concentrationglossary link

Returns:

impurity_concentration

Atomic Data

Interface to atomic data files.

class AtomicData(atomic_data_directory: Path = PosixPath('radas_dir'))[source]

Bases: object

A class to manage atomic data for various species, providing facilities for accessing datasets directly or by constructing interpolators for different datasets (i.e. radiated power curves).

Attributes: - atomic_data_directory (Path): Path to the directory containing atomic data files. - datasets (dict): A dictionary storing the atomic data for different species. - available_species (list): A list of species for which atomic data is available. - coronal_Lz_interpolators (dict): A dictionary of interpolators for coronal Lz values. - coronal_Z_interpolators (dict): A dictionary of interpolators for coronal Z values. - noncoronal_Lz_interpolators (dict): A dictionary of interpolators for non-coronal Lz values. - noncoronal_Z_interpolators (dict): A dictionary of interpolators for non-coronal Z values.

Initializes the AtomicData object by loading atomic data from the specified directory.

Parameters: - atomic_data_directory (Path): The path to the directory containing atomic data files.

static read_atomic_data(
atomic_data_directory: Path = PosixPath('radas_dir'),
) dict[AtomicSpecies, Dataset][source]

Reads atomic data from netCDF files located in the specified directory.

This function scans a directory for netCDF files (.nc), each representing atomic data for a different species. It expects these files to be in a subdirectory named ‘output’. The data is read into an xarray Dataset, quantified with pint for unit handling, and stored in a dictionary with keys corresponding to AtomicSpecies enums.

Parameters: - atomic_data_directory (Path): The path to the directory containing the ‘output’ folder with netCDF files.

Returns: - dict: A dictionary where keys are AtomicSpecies enums and values are xarray Datasets of the atomic data.

Raises: - FileNotFoundError: If the atomic_data_directory or its ‘output’ subdirectory does not exist.

static key_to_enum(
species: str | AtomicSpecies,
) AtomicSpecies[source]

Converts a species identifier to an AtomicSpecies enum.

This method allows for flexible specification of species, accepting either a string (which is then capitalized and matched to an AtomicSpecies enum) or an AtomicSpecies enum directly.

Parameters: - species (Union[str, AtomicSpecies]): The species identifier, either a string name or an AtomicSpecies enum.

Returns: - AtomicSpecies: The corresponding AtomicSpecies enum.

get_coronal_Lz_interpolator(
species: str | AtomicSpecies,
) CoeffInterpolator[source]

Returns a coronal_Lz_interpolator for the specified species and ne_tau value.

get_coronal_Z_interpolator(
species: str | AtomicSpecies,
) CoeffInterpolator[source]

Returns a coronal_Z_interpolator for the specified species and ne_tau value.

get_noncoronal_Lz_interpolator(
species: str | AtomicSpecies,
ne_tau: float | Quantity,
ne_tau_rel_tolerance: float | Quantity | None = None,
) CoeffInterpolator[source]

Returns a noncoronal_Lz_interpolator for the specified species and ne_tau value.

get_noncoronal_Z_interpolator(
species: str | AtomicSpecies,
ne_tau: float | Quantity,
ne_tau_rel_tolerance: float | Quantity | None = None,
) CoeffInterpolator[source]

Returns a noncoronal_Z_interpolator for the specified species and ne_tau value.

class CoeffInterpolator(
coeff: ~xarray.core.dataarray.DataArray,
reference_electron_density: ~pint.Quantity = <Quantity(1.0,
'1 / meter ** 3')>,
reference_electron_temp: ~pint.Quantity = <Quantity(1.0,
'electron_volt')>,
)[source]

Bases: RectBivariateSpline

An extension of a 2D spline interpolator which handles interpolations in log-space, for interpolating atomic data.

Builds a bivariate spline interpolator for the provided DataArray of coefficients.

The interpolator performs interpolations on the log of the provided coefficient, for the log of the provided temperature and density, since the atomic data arrays are provided with log-spaced values.

Parameters: - coeff (xr.DataArray): The xarray DataArray containing the data to interpolate, indexed by electron temperature and density. - reference_electron_density (Quantity): the normalization value for the electron density coordinates. - reference_electron_temp (Quantity): the normalization value for the electron temp coordinates.

Returns: - CoeffInterpolator: The bivariate spline interpolator object with eval, vector_eval and grid_eval methods.

tiny = np.float64(2.2250738585072014e-308)
log10_with_floor(
x: DataArray | ndarray | float,
) DataArray | ndarray | float[source]

Return the log of x if x > 0, and otherwise return the log of the smallest representable float.

read_atomic_data(
radas_dir: Path,
) tuple[AtomicData, str][source]

Construct an AtomicData interface using the atomic data in the specified directory.

Algorithms

Defines a class for different POPCON algorithms.

class Algorithm(
function: Callable[[...], dict[str, Any]],
return_keys: list[str],
name: str | None = None,
skip_registration: bool = False,
)[source]

Bases: object

A class which handles the input and output of POPCON algorithms.

Initialise an Algorithm.

Parameters:
  • function – a callable function

  • return_keys – the arguments which are returned from the function

  • name – Descriptive name for algorithm

  • skip_registration – flag to skip adding the Algorithm to ‘instances’ (useful for testing)

instances: ClassVar[dict[str, Algorithm | CompositeAlgorithm]] = {'calc_1D_plasma_profiles': Algorithm: calc_1D_plasma_profiles, 'calc_B_pol_omp': Algorithm: calc_B_pol_omp, 'calc_B_tor_omp': Algorithm: calc_B_tor_omp, 'calc_LH_transition_threshold_power': Algorithm: calc_LH_transition_threshold_power, 'calc_LI_transition_threshold_power': Algorithm: calc_LI_transition_threshold_power, 'calc_PB_over_R': Algorithm: calc_PB_over_R, 'calc_PBpRnSq': Algorithm: calc_PBpRnSq, 'calc_P_rad_hydrogen_bremsstrahlung': Algorithm: calc_P_rad_hydrogen_bremsstrahlung, 'calc_P_radiation_from_core_seeded_impurity': Algorithm: calc_P_radiation_from_core_seeded_impurity, 'calc_SepOS_LH_transition': Algorithm: calc_SepOS_LH_transition, 'calc_SepOS_L_mode_density_limit': Algorithm: calc_SepOS_L_mode_density_limit, 'calc_SepOS_ideal_MHD_limit': Algorithm: calc_SepOS_ideal_MHD_limit, 'calc_Spitzer_loop_resistivity': Algorithm: calc_Spitzer_loop_resistivity, 'calc_alpha_t': Algorithm: calc_alpha_t, 'calc_areal_elongation_from_elongation_at_psi95': Algorithm: calc_areal_elongation_from_elongation_at_psi95, 'calc_auxiliary_power': Algorithm: calc_auxiliary_power, 'calc_average_electron_density_from_greenwald_fraction': Algorithm: calc_average_electron_density_from_greenwald_fraction, 'calc_average_ion_mass': Algorithm: calc_average_ion_mass, 'calc_average_ion_temp_from_temperature_ratio': Algorithm: calc_average_ion_temp_from_temperature_ratio, 'calc_average_total_pressure': Algorithm: calc_average_total_pressure, 'calc_beta_normalized': Algorithm: calc_beta_normalized, 'calc_beta_poloidal': Algorithm: calc_beta_poloidal, 'calc_beta_toroidal': Algorithm: calc_beta_toroidal, 'calc_beta_total': Algorithm: calc_beta_total, 'calc_bootstrap_fraction': Algorithm: calc_bootstrap_fraction, 'calc_breakdown_flux_consumption': Algorithm: calc_breakdown_flux_consumption, 'calc_bremsstrahlung_radiation': Algorithm: calc_bremsstrahlung_radiation, 'calc_core_seeded_impurity_concentration': Algorithm: calc_core_seeded_impurity_concentration, 'calc_critical_alpha_MHD': Algorithm: calc_critical_alpha_MHD, 'calc_current_relaxation_time': Algorithm: calc_current_relaxation_time, 'calc_cylindrical_edge_safety_factor': Algorithm: calc_cylindrical_edge_safety_factor, 'calc_edge_collisionality': Algorithm: calc_edge_collisionality, 'calc_edge_impurity_concentration': Algorithm: calc_edge_impurity_concentration, 'calc_effective_collisionality': Algorithm: calc_effective_collisionality, 'calc_electron_density_peaking': Algorithm: calc_electron_density_peaking, 'calc_elongation_at_psi95_from_areal_elongation': Algorithm: calc_elongation_at_psi95_from_areal_elongation, 'calc_external_flux': Algorithm: calc_external_flux, 'calc_external_inductance': Algorithm: calc_external_inductance, 'calc_f_rad_core': Algorithm: calc_f_rad_core, 'calc_f_shaping_for_qstar': Algorithm: calc_f_shaping_for_qstar, 'calc_fieldline_pitch_at_omp': Algorithm: calc_fieldline_pitch_at_omp, 'calc_flux_needed_from_solenoid_over_rampup': Algorithm: calc_flux_needed_from_solenoid_over_rampup, 'calc_fusion_gain': Algorithm: calc_fusion_gain, 'calc_fusion_power': Algorithm: calc_fusion_power, 'calc_greenwald_density_limit': Algorithm: calc_greenwald_density_limit, 'calc_greenwald_fraction': Algorithm: calc_greenwald_fraction, 'calc_impurity_charge_state': Algorithm: calc_impurity_charge_state, 'calc_impurity_radiated_power': Algorithm: calc_impurity_radiated_power, 'calc_impurity_radiated_power_mavrin_coronal': Algorithm: calc_impurity_radiated_power_mavrin_coronal, 'calc_impurity_radiated_power_mavrin_noncoronal': Algorithm: calc_impurity_radiated_power_mavrin_noncoronal, 'calc_impurity_radiated_power_post_and_jensen': Algorithm: calc_impurity_radiated_power_post_and_jensen, 'calc_impurity_radiated_power_radas': Algorithm: calc_impurity_radiated_power_radas, 'calc_inductive_plasma_current': Algorithm: calc_inductive_plasma_current, 'calc_internal_flux': Algorithm: calc_internal_flux, 'calc_internal_inductance_for_cylindrical': Algorithm: calc_internal_inductance_for_cylindrical, 'calc_internal_inductance_for_noncylindrical': Algorithm: calc_internal_inductance_for_noncylindrical, 'calc_internal_inductivity': Algorithm: calc_internal_inductivity, 'calc_intrinsic_radiated_power_from_core': Algorithm: calc_intrinsic_radiated_power_from_core, 'calc_inverse_aspect_ratio': Algorithm: calc_inverse_aspect_ratio, 'calc_invmu_0_dLedR': Algorithm: calc_invmu_0_dLedR, 'calc_ion_density_peaking': Algorithm: calc_ion_density_peaking, 'calc_ionization_volume_from_AUG': Algorithm: calc_ionization_volume_from_AUG, 'calc_lambda_q': Algorithm: calc_lambda_q, 'calc_lambda_q_with_brunner': Algorithm: calc_lambda_q_with_brunner, 'calc_lambda_q_with_eich_regression_14': Algorithm: calc_lambda_q_with_eich_regression_14, 'calc_lambda_q_with_eich_regression_15': Algorithm: calc_lambda_q_with_eich_regression_15, 'calc_lambda_q_with_eich_regression_9': Algorithm: calc_lambda_q_with_eich_regression_9, 'calc_loop_voltage': Algorithm: calc_loop_voltage, 'calc_max_flattop_duration': Algorithm: calc_max_flattop_duration, 'calc_min_P_radiation_from_LH_factor': Algorithm: calc_min_P_radiation_from_LH_factor, 'calc_min_P_radiation_from_fraction': Algorithm: calc_min_P_radiation_from_fraction, 'calc_minor_radius_from_inverse_aspect_ratio': Algorithm: calc_minor_radius_from_inverse_aspect_ratio, 'calc_neoclassical_loop_resistivity': Algorithm: calc_neoclassical_loop_resistivity, 'calc_neutral_flux_density_factor': Algorithm: calc_neutral_flux_density_factor, 'calc_neutral_pressure_kallenbach': Algorithm: calc_neutral_pressure_kallenbach, 'calc_neutron_flux_to_walls': Algorithm: calc_neutron_flux_to_walls, 'calc_normalised_collisionality': Algorithm: calc_normalised_collisionality, 'calc_ohmic_power': Algorithm: calc_ohmic_power, 'calc_parallel_heat_flux_density': Algorithm: calc_parallel_heat_flux_density, 'calc_peak_pressure': Algorithm: calc_peak_pressure, 'calc_peaked_profiles': Algorithm: calc_peaked_profiles, 'calc_plasma_current_from_qstar': Algorithm: calc_plasma_current_from_qstar, 'calc_plasma_poloidal_circumference': Algorithm: calc_plasma_poloidal_circumference, 'calc_plasma_stored_energy': Algorithm: calc_plasma_stored_energy, 'calc_plasma_surface_area': Algorithm: calc_plasma_surface_area, 'calc_plasma_volume': Algorithm: calc_plasma_volume, 'calc_poloidal_field_flux': Algorithm: calc_poloidal_field_flux, 'calc_poloidal_sound_larmor_radius': Algorithm: calc_poloidal_sound_larmor_radius, 'calc_power_crossing_separatrix': Algorithm: calc_power_crossing_separatrix, 'calc_power_crossing_separatrix_in_electron_channel': Algorithm: calc_power_crossing_separatrix_in_electron_channel, 'calc_power_crossing_separatrix_in_ion_channel': Algorithm: calc_power_crossing_separatrix_in_ion_channel, 'calc_q_perp': Algorithm: calc_q_perp, 'calc_q_star_from_plasma_current': Algorithm: calc_q_star_from_plasma_current, 'calc_ratio_P_LH': Algorithm: calc_ratio_P_LH, 'calc_ratio_P_LI': Algorithm: calc_ratio_P_LI, 'calc_reattachment_time_henderson': Algorithm: calc_reattachment_time_henderson, 'calc_resistive_flux': Algorithm: calc_resistive_flux, 'calc_resistivity_trapped_enhancement': Algorithm: calc_resistivity_trapped_enhancement, 'calc_rho_star': Algorithm: calc_rho_star, 'calc_separatrix_electron_density': Algorithm: calc_separatrix_electron_density, 'calc_separatrix_electron_temp': Algorithm: calc_separatrix_electron_temp, 'calc_separatrix_elongation_from_areal_elongation': Algorithm: calc_separatrix_elongation_from_areal_elongation, 'calc_separatrix_triangularity_from_triangularity95': Algorithm: calc_separatrix_triangularity_from_triangularity95, 'calc_synchrotron_radiation': Algorithm: calc_synchrotron_radiation, 'calc_temperature_peaking': Algorithm: calc_temperature_peaking, 'calc_triple_product': Algorithm: calc_triple_product, 'calc_troyon_limit': Algorithm: calc_troyon_limit, 'calc_vertical_field_mutual_inductance': Algorithm: calc_vertical_field_mutual_inductance, 'calc_vertical_magnetic_field': Algorithm: calc_vertical_magnetic_field, 'calc_vertical_minor_radius_from_elongation_and_minor_radius': Algorithm: calc_vertical_minor_radius_from_elongation_and_minor_radius, 'calc_zeff_and_dilution_due_to_impurities': Algorithm: calc_zeff_and_dilution_due_to_impurities, 'read_atomic_data': Algorithm: read_atomic_data, 'read_confinement_scalings': Algorithm: read_confinement_scalings, 'require_P_rad_less_than_P_in': Algorithm: require_P_rad_less_than_P_in, 'set_up_impurity_concentration_array': Algorithm: set_up_impurity_concentration_array, 'solve_energy_confinement_scaling_for_input_power': Algorithm: solve_energy_confinement_scaling_for_input_power, 'switch_to_L_mode_confinement_below_threshold': Algorithm: switch_to_L_mode_confinement_below_threshold, 'switch_to_linearised_ohmic_confinement_below_threshold': Algorithm: switch_to_linearised_ohmic_confinement_below_threshold, 'two_point_model_fixed_fpow': Algorithm: two_point_model_fixed_fpow, 'two_point_model_fixed_qpart': Algorithm: two_point_model_fixed_qpart, 'two_point_model_fixed_tet': Algorithm: two_point_model_fixed_tet}
update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset[source]

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

classmethod from_single_function(
func: Callable,
return_keys: list[str],
name: str | None = None,
skip_unit_conversion: bool = False,
skip_registration: bool = False,
) Algorithm[source]

Build an Algorithm which wraps a single function.

classmethod register_algorithm(
return_keys: list[str],
name: str | None = None,
skip_unit_conversion: bool = False,
) Callable[[...], Any][source]

Decorate a function and turn it into an Algorithm. Usage: @Algorithm.register_algorithm(return_keys=[”…”]).

classmethod empty() Algorithm[source]

Makes a ‘do nothing’ algorithm, in case you don’t want to use the algorithm functionality.

validate_inputs(
configuration: dict | Dataset,
quiet: bool = False,
raise_error_on_missing_inputs: bool = False,
) bool[source]

Check that all required inputs are defined, and warn if inputs are unused.

classmethod write_yaml(filepath: Path) None[source]

Writes a file ‘algorithms.yaml’ documenting the available algorithms.

classmethod algorithms() list[str][source]

Make a list of the available algorithms.

classmethod get_algorithm(
key: str,
) Algorithm | CompositeAlgorithm[source]

Retrieves an algorithm by name.

class CompositeAlgorithm(
algorithms: Sequence[Algorithm | CompositeAlgorithm],
name: str | None = None,
register: bool = False,
)[source]

Bases: object

A class which combined multiple Algorithms into a single object which behaves like an Algorithm.

Initialise a CompositeAlgorithm, combining several other Algorithms.

Parameters:
  • algorithms – a list of Algorithms, in the order that they should be executed.

  • name – a name used to refer to the composite algorithm.

  • register – flag register a named CompositeAlgorithm to ‘Algorithm.instances’ (ignored if name = None)

classmethod from_list(
keys: list[str],
name: str | None = None,
register: bool = False,
) CompositeAlgorithm[source]

Build a CompositeAlgorithm from a list of Algorithm names.

update_dataset(
dataset: Dataset,
allow_overwrite: bool = True,
) Dataset[source]

Retrieve inputs from passed dataset and return a new dataset combining input and output quantities.

N.b. will not throw a warning if the dataset contains unused elements.

Parameters:
  • dataset – input dataset

  • allow_overwrite – if False, raise an error if trying to write a variable which is already defined in dataset

Returns: modified dataset

validate_inputs(
configuration: dict | Dataset,
quiet: bool = False,
raise_error_on_missing_inputs: bool = True,
warn_for_overridden_variables: bool = False,
) bool[source]

Check that all required inputs are defined, and warn if inputs are unused.

Internals

The functions and classes below are listed here for completeness. But these are internals, so it should usually not be required to interact with any of them directly.

Unitfull

alias of Quantity | DataArray

Constructors and helper functions.

convert_named_options(key: str, val: Any) Any[source]

Given a ‘key’ matching a named_option, return the corresponding Enum value.

get_item(value: Any) Any[source]

Check if an object is an xr.DataArray, and if so, return the “.item()” element.

get_values(array: Any) Any[source]

Check if an object is an xr.DataArray, and if so, return the “.values” element.