diff --git a/documentation/source/physics-models/plasma_fuelling.md b/documentation/source/physics-models/plasma_fuelling.md
new file mode 100644
index 0000000000..9b2423ea28
--- /dev/null
+++ b/documentation/source/physics-models/plasma_fuelling.md
@@ -0,0 +1,244 @@
+# Plasma Fuelling | `PlasmaFuelling()`
+
+## Particle balance
+
+The control of fuelling is governed by 4 key particle flux equations for each of the primary fuel species and the thermal helium $\alpha$ ash.
+
+$$
+\frac{dN_{\text{T}}}{dt} = f_{\text{fuelling,T}}\eta_{\text{fuelling}}\Gamma_{\text{fuel}}+\Gamma_{\text{T,beam}} + \Gamma_{\text{D+D} \rightarrow \text{T}} - \Gamma_{\text{D+T}} - \frac{N_{\text{T}}}{\tau_{\text{T}}^*}
+$$
+
+$$
+\frac{dN_{\text{D}}}{dt} = f_{\text{fuelling,D}}\eta_{\text{fuelling}}\Gamma_{\text{fuel}}+\Gamma_{\text{D,beam}} -2 \Gamma_{\text{D+D}}- \Gamma_{\text{D+3He}} - \Gamma_{\text{D+T}} - \frac{N_{\text{T}}}{\tau_{\text{D}}^*}
+$$
+
+$$
+\frac{dN_{\text{3He}}}{dt} = f_{\text{fuelling,3He}}\eta_{\text{fuelling}}\Gamma_{\text{fuel}} + \Gamma_{\text{D+D} \rightarrow \text{3He}} -\Gamma_{\text{D+3He}} - \frac{N_{\text{T}}}{\tau_{\text{3He}}^*}
+$$
+
+$$
+\frac{dN_{\alpha,\text{thermal}}}{dt} = \Gamma_{\text{D+3He}} + \Gamma_{\text{D+T}} - \frac{N_{\alpha,\text{thermal}}}{\tau_{\alpha}^*}
+$$
+
+In a steady state equilibrium all 4 of these equations should balance, therefore:
+
+$$
+\frac{dN_{\text{D}}}{dt} = \frac{dN_{\text{T}}}{dt} = \frac{dN_{\text{3He}}}{dt} = \frac{dN_{\alpha,\text{thermal}}}{dt} = 0
+$$
+
+Here, $\eta_{\text{fuelling}}$ is the fuelling efficiency, which quantifies how effectively fuel injected into the vacuum vessel reaches the plasma core. The value of $\eta_{\text{fuelling}}$ depends on the fuelling method. Typical values are around 0.01--0.1 for low-field-side gas puffing, 0.1--0.2 for supersonic gas injection, and 0.5--0.9 for pellet injection, which can approach unity under favourable conditions. $\Gamma_{\text{fuelling}}$ is the fuel injection rate into the vacuum vessel. The product $\eta_{\text{fuelling}} \Gamma_{\text{fuelling}}$ therefore represents the effective fuelling rate, i.e. the fraction of the injected fuel that successfully penetrates into the plasma and becomes available for fusion reactions. $\Gamma_{\text{T,beam}}$ and $\Gamma_{\text{D,beam}}$ respectively are the particle source rates from neutral beam systems (if present).
+
+
+The fuelling fractional compositions is given by $f$
+
+ - $N$ is the total amount of ions in the plasma.
+
+ - $\tau_{\text{fuel}}^*$ is the recycling corrected fuel particle confinement time given by:
+
+ $\tau_{\text{fuel}}^* = (\tau_p) / (1-R)$
+
+The (effective) exhaust efficiency is is given by , $\eta_{\text{eff}} = 1- R$
+
+The factor $\frac{R}{1-R}$ is the mean number of recycling events back into the burning region experieced by a particle before it is pumped away.
+
+The definition of the recycling coefficient $R = 1- \frac{\Gamma_{\text{pumps}}}{\Gamma_{\text{out}}}$, where $\Gamma_{\text{pumps}}$ is the number of particles exhausted by the pumps per second and $\Gamma_{\text{out}}$ is the number of particles per second transported radially outwards across the separatrix.
+
+
+
+Where $\tau_p$ is the particle confinement time which we can assume is approximately equal to the energy confinement time ($\tau_p = \tau_E$).
+
+!!! warning "Relation between $\tau_p$ and $\tau_E$"
+
+ In this model the "raw" particle confinement time ($\tau_p$) is set to always match the energy confinement time ($\tau_E$). The only variation of this in terms of the "effective" particle confinement time $\tau_{p}^*$ is via the recycling coefficient ($R$). If needed new coeffcients may be added to scale ($\tau_p$) before recyling corrections if needed.
+
+!!! note "Quantifying $R$"
+
+ The recycling coefficient $R$, defined as the fraction of particles crossing the LCFS that return to the plasma, can depend on numerous factors—including vessel pumping speed, neutral pressure in the private‑divertor region, impurity seeding levels, and the detailed properties of the SOL. Among these parameters, $R$ is the least certain and the most difficult to quantify. In next‑step devices, the SOL temperature is expected to be high, so particles reflected from the vessel walls are mostly ionized within the SOL and are removed by pumping before they can effectively refuel the burning plasma. As a result, the recycling coefficient is anticipated to be lower than in present‑day tokamaks, where $R$ can often approach unity. An additional uncertainty is the extent of neutral penetration at the plasma edge, which influences both the pedestal density and the density profile, and therefore also affects $R$[^1].
+
+
+--------------
+
+### Tritium Flow Rate | `calculate_plasma_tritium_flow_rate()`
+
+$$
+\frac{dN_{\text{T}}}{dt} = f_{\text{fuelling,T}}\eta_{\text{fuelling}}\Gamma_{\text{fuel}}+\Gamma_{\text{T,beam}} + \Gamma_{\text{D+D} \rightarrow \text{T}} - \Gamma_{\text{D+T}} - \frac{N_{\text{T}}}{\tau_{\text{T}}^*}
+$$
+
+---------------
+
+### Deuterium Flow Rate | `calculate_plasma_deuterium_flow_rate()`
+
+$$
+\frac{dN_{\text{D}}}{dt} = f_{\text{fuelling,D}}\eta_{\text{fuelling}}\Gamma_{\text{fuel}}+\Gamma_{\text{D,beam}} -2 \Gamma_{\text{D+D}}- \Gamma_{\text{D+3He}} - \Gamma_{\text{D+T}} - \frac{N_{\text{T}}}{\tau_{\text{D}}^*}
+$$
+
+---------------
+
+### Helium-3 Flow Rate | `calculate_plasma_helium3_flow_rate()`
+
+$$
+\frac{dN_{\text{3He}}}{dt} = f_{\text{fuelling,3He}}\eta_{\text{fuelling}}\Gamma_{\text{fuel}} + \Gamma_{\text{D+D} \rightarrow \text{3He}}-\Gamma_{\text{D+3He}} - \frac{N_{\text{T}}}{\tau_{\text{3He}}^*}
+$$
+
+---------------
+
+### Thermal Alpha Particle Flow Rate | `calculate_plasma_alphas_thermal_flow_rate()`
+
+$$
+\frac{dN_{\alpha,\text{thermal}}}{dt} = \Gamma_{\text{D+3He}} + \Gamma_{\text{D+T}} - \frac{N_{\alpha,\text{thermal}}}{\tau_{\alpha}^*}
+$$
+
+-----------------
+
+## Fuel Burnup Fration
+
+In a steady state tokamak, the burnup fraction ($f_b$) is explicitly defined by the following rate equation:
+
+$$
+f_b = \frac{\Gamma_{\text{fusion}}}{\sum\Gamma_{\text{fuel}}}
+$$
+
+where $\Gamma_{\text{fusion}}$ is the fusion reaction rate per second $[\text{s}^{-1}]$, and $\sum\Gamma_{\text{fuel}}$ is the sum of all fuel injection rates into the vacuum vessel by any means in particles per second $[\text{s}^{-1}]$.
+
+-----------------
+
+### Total Fuel Burnup Fraction | `calculate_fuel_burnup_fraction()`
+
+For the total burnup fraction we state:
+
+$$
+\overbrace{f_b}^{\texttt{f_plasma_fuel_burnup}} = \frac{2\left(\Gamma_{\text{D+D}}+\Gamma_{\text{D+T}}+\Gamma_{\text{D+3He}}\right)}{\Gamma_{\text{fuel}}+\Gamma_{\text{D,beam}}+\Gamma_{\text{T,beam}}}
+$$
+
+Here the factor of 2 is included as each fusion reaction removes 2 particles but our fuelling rate looks at indivudal particles injected.
+
+-------------------
+
+### Tritium Burnup Fraction | `calculate_tritium_burnup_fraction()`
+
+For just the tritium burnup fraction we state:
+
+$$
+\overbrace{f_b}^{\texttt{f_plasma_tritium_burnup}} = \frac{\left(\Gamma_{\text{D+T}}\right)}{\Gamma_{\text{fuel}}f_{\text{fuelling,T}}+\Gamma_{\text{T,beam}}}
+$$
+
+------------------
+
+### Deuterium Burnup Fraction | `calculate_deuterium_burnup_fraction()`
+
+For just the deuterium burnup fraction we state:
+
+$$
+\overbrace{f_b}^{\texttt{f_plasma_deuterium_burnup}} = \frac{2\left(\Gamma_{\text{D+D}}+\Gamma_{\text{D+3He}}\right)}{\Gamma_{\text{fuel}}f_{\text{fuelling,D}}+\Gamma_{\text{D,beam}}}
+$$
+
+------------------
+
+## Key Constraints
+
+The implementation of the equations above as equality constraints is required in order to achieve a plasma steady state equilibrium where there is not a net rate of change of species number. In any given run several of these constraints and iterations variables will almost always be on.Below is the generic input used for a D-T only plasma where we have allowed all of the key solution variables to be iteration variables:
+
+```python
+* Tritium particle balance
+icc = 93
+
+* Deuterium particle balance
+icc = 94
+
+* Alpha particle balance
+icc = 96
+
+* Fuelling composition consistency
+icc = 97
+
+
+* Particle recycling fraction
+ixc = 178
+f_plasma_particles_lcfs_recycled = 0.9
+
+* Plasma fuelling efficiecy
+ixc = 179
+eta_plasma_fuelling = 0.7
+
+* Injected VV fuelling rate
+ixc = 180
+molflow_plasma_fuelling_vv_injected = 5e21
+boundl(180) = 1e20
+
+* Deuterium fuelling fraction
+ixc = 181
+f_molflow_plasma_fuelling_deuterium = 0.5
+boundl(181) = 0.4
+
+* Tritium fuelling fraction
+ixc = 182
+f_molflow_plasma_fuelling_tritium = 0.5
+boundl(182) = 0.4
+```
+
+Note that the Helium-3 consistency equation (`icc= 95`) is not active as we are not actively fuelling and have no stated Helium-3 in the plasma composition.
+
+If solving this as an evaluation problem it would be typical to fix the values of the reycling fraction, $R$ (`f_plasma_particles_lcfs_recycled`) and the fuelling efficiency $\eta_{\text{fuelling}}$ (`eta_plasma_fuelling`) as these represent higher order assumptions already about the plant design that `PROCESS` cannot model. This realistically leaves the total fuelling rate $\Gamma_{\text{fuel}}$ (`molflow_plasma_fuelling_vv_injected`) and the fuelling fractions $f_{\text{fuelling,D}}$,$f_{\text{fuelling,T}}$ (`f_molflow_plasma_fuelling_deuterium,f_molflow_plasma_fuelling_tritium`) to solve this consistency equations. This is ideal as the fuelling rates and fractions are ideal optimisation paramters as they can be directly controlled from the machine control room.
+
+------------
+
+### Tritium Flow Consistency
+
+This constraint can be activated by stating `icc = 93` in the input file.
+
+This constraint ensures that the change in tritium particles as a function of time is zero. It ensures the output of `calculate_plasma_tritium_flow_rate()` is zero
+
+**It is recommended to have this constraint on as it is a plasma equilibrium solution model**
+
+-----------------
+
+### Deuterium Flow Consistency
+
+This constraint can be activated by stating `icc = 94` in the input file.
+
+This constraint ensures that the change in deuterium particles as a function of time is zero. It ensures the output of `calculate_plasma_deuterium_flow_rate()` is zero
+
+**It is recommended to have this constraint on as it is a plasma equilibrium solution model**
+
+----------------
+
+### Helium-3 Flow Consistency
+
+This constraint can be activated by stating `icc = 95` in the input file.
+
+This constraint ensures that the change in helium-3 particles as a function of time is zero. It ensures the output of `calculate_plasma_helium3_flow_rate()` is zero
+
+**It is recommended to have this constraint on as it is a plasma equilibrium solution model**
+
+----------------
+
+### Thermal Alpha Particle Flow Consistency
+
+This constraint can be activated by stating `icc = 96` in the input file.
+
+This constraint ensures that the change in thermal alpha particles as a function of time is zero. It ensures the output of `calculate_plasma_alphas_thermal_flow_rate()` is zero
+
+**It is recommended to have this constraint on as it is a plasma equilibrium solution model**
+
+------------------
+
+### Fuelling Proportion Consistency
+
+This constraint can be activated by stating `icc = 97` in the input file.
+
+This ensures that all 3 injected fuelling fractions sum up to 1:
+
+$$
+f_{\text{fuelling,D}} + f_{\text{fuelling,T}} + f_{\text{fuelling,3He}} = 1.0
+$$
+
+**It is recommended to have this constraint on as it is a plasma consistency model**
+
+-----------------
+
+
+[^1]: G. L. Jackson, V. S. Chan, and R. D. Stambaugh, “An Analytic Expression for the Tritium Burnup Fraction in Burning-Plasma Devices,” Fusion Science and Technology, vol. 64, no. 1, pp. 8–12, Jul. 2013, doi: https://doi.org/10.13182/fst13-a17042.
+
+[^2]: J. F. Artaud et al., “Metis: a fast integrated tokamak modelling tool for scenario design,” Nuclear Fusion, vol. 58, no. 10, pp. 105001–105001, Aug. 2018, doi: https://doi.org/10.1088/1741-4326/aad5b1.
+
+[^3]: D. Reiter, H. Kever, G. H. Wolf, M. Baelmans, R. Behrisch, and R. Schneider, “Helium removal from tokamaks,” Plasma Physics and Controlled Fusion, vol. 33, no. 13, pp. 1579–1600, Nov. 1991, doi: https://doi.org/10.1088/0741-3335/33/13/008.
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index 6cfa762788..cbdaf4def1 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -53,6 +53,7 @@ nav:
- Overview: physics-models/plasma_beta/plasma_beta.md
- Fast Alpha: physics-models/plasma_beta/plasma_alpha_beta_contribution.md
- Density Limit: physics-models/plasma_density.md
+ - Fuelling: physics-models/plasma_fuelling.md
- Composition & Impurities: physics-models/plasma_composition.md
- Radiation: physics-models/plasma_radiation.md
- Plasma Current:
diff --git a/process/core/constants.py b/process/core/constants.py
index 8583458d35..d6b8699de9 100644
--- a/process/core/constants.py
+++ b/process/core/constants.py
@@ -9,6 +9,12 @@
MFILE = 13
"""Machine-optimised output file unit"""
+AVOGADRO_NUMBER = 6.02214076e23
+"""Avogadro's number [1/mol]
+Reference: National Institute of Standards and Technology (NIST)
+https://physics.nist.gov/cgi-bin/cuu/Value?na|search_for=avogadro
+"""
+
ELECTRON_CHARGE = 1.602176634e-19
"""Electron / elementary charge [C]
Reference: National Institute of Standards and Technology (NIST)
diff --git a/process/core/input.py b/process/core/input.py
index fb282b26ec..7f8c515546 100644
--- a/process/core/input.py
+++ b/process/core/input.py
@@ -169,7 +169,6 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]:
"beta_vol_avg_min": InputVariable("physics", float, range=(0.0, 1.0)),
"betbm0": InputVariable("physics", float, range=(0.0, 10.0)),
"b_plasma_toroidal_on_axis": InputVariable("physics", float, range=(0.0, 30.0)),
- "burnup_in": InputVariable("physics", float, range=(0.0, 1.0)),
"radius_plasma_core_norm": InputVariable(
"impurity_radiation", float, range=(0.0, 1.0)
),
@@ -1182,6 +1181,22 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]:
"f_len_sol_power_decay_inboard_outboard": InputVariable(
"physics", float, range=(0.01, 2.0)
),
+ "f_plasma_particles_lcfs_recycled": InputVariable(
+ "physics", float, range=(0.0, 1.0)
+ ),
+ "eta_plasma_fuelling": InputVariable("physics", float, range=(0.0, 1.0)),
+ "molflow_plasma_fuelling_vv_injected": InputVariable(
+ "physics", float, range=(1e18, 1e24)
+ ),
+ "f_molflow_plasma_fuelling_deuterium": InputVariable(
+ "physics", float, range=(0.0, 1.0)
+ ),
+ "f_molflow_plasma_fuelling_tritium": InputVariable(
+ "physics", float, range=(0.0, 1.0)
+ ),
+ "f_molflow_plasma_fuelling_helium3": InputVariable(
+ "physics", float, range=(0.0, 1.0)
+ ),
}
diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py
index bd34580d43..ee9c1e50ce 100644
--- a/process/core/io/plot/summary.py
+++ b/process/core/io/plot/summary.py
@@ -68,6 +68,7 @@
)
from process.models.physics.density_limit import DensityLimitModel
from process.models.physics.exhaust import calculate_brunner_divertor_power_splits
+from process.models.physics.fuelling import PlasmaFuelling
from process.models.physics.impurity_radiation import read_impurity_file
from process.models.physics.l_h_transition import PlasmaConfinementTransitionModel
from process.models.physics.physics import (
@@ -2942,7 +2943,7 @@ def plot_main_plasma_information(
f"| D: {mfile.get('f_plasma_fuel_deuterium', scan=scan):.2f} | T: {mfile.get('f_plasma_fuel_tritium', scan=scan):.2f} | 3He: {mfile.get('f_plasma_fuel_helium3', scan=scan):.2f} |\n\n"
f"Fusion Power, $P_{{\\text{{fus}}}}:$ {mfile.get('p_fusion_total_mw', scan=scan):,.2f} MW\n"
f"D-T Power, $P_{{\\text{{fus,DT}}}}:$ {mfile.get('p_dt_total_mw', scan=scan):,.2f} MW\n"
- f"D-D Power, $P_{{\\text{{fus,DD}}}}:$ {mfile.get('p_dd_total_mw', scan=scan):,.2f} MW\n"
+ f"D-D Power, $P_{{\\text{{fus,DD}}}}:$ {mfile.get('p_dd_total_mw', scan=scan):,.4f} MW\n"
f"D-3He Power, $P_{{\\text{{fus,D3He}}}}:$ {mfile.get('p_dhe3_total_mw', scan=scan):,.2f} MW\n"
f"Alpha Power, $P_{{\\alpha}}:$ {mfile.get('p_alpha_total_mw', scan=scan):,.2f} MW"
)
@@ -2966,9 +2967,9 @@ def plot_main_plasma_information(
f" - Average mass of all plasma ions: {mfile.get('m_ions_total_amu', scan=scan):.3f} amu\n"
f"Fuel mass: {mfile.get('m_plasma_fuel_ions', scan=scan) * 1000:.4f} g\n"
f" - Average mass of all fuel ions: {mfile.get('m_fuel_amu', scan=scan):.3f} amu\n\n"
- f"Fueling rate: {mfile.get('molflow_plasma_fuelling_required', scan=scan):.3e} nucleus-pairs/s\n"
- f"Fuel burn-up rate: {mfile.get('rndfuel', scan=scan):.3e} reactions/s \n"
- f"Burn-up fraction: {mfile.get('burnup', scan=scan):.4f} \n"
+ f"Fueling rate: {mfile.get('molflow_plasma_fuelling_vv_injected', scan=scan):.3e} nucleus-pairs/s\n"
+ f"Fuel burn-up rate: {mfile.get('fusrat_total', scan=scan):.3e} reactions/s \n"
+ f"Burn-up fraction: {mfile.get('f_plasma_fuel_burnup', scan=scan):.4f} \n"
)
axis.text(
@@ -12113,8 +12114,8 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
# Add plasma volume, areas and shaping information
textstr_general = (
f"Total fusion rate: {mfile.get('fusrat_total', scan=scan):.4e} reactions/s\n"
- f"Total fusion rate density: {mfile.get('fusden_total', scan=scan):.4e} reactions/m3/s\n"
- f"Plasma fusion rate density: {mfile.get('fusden_plasma', scan=scan):.4e} reactions/m3/s\n"
+ f"Total fusion rate density: {mfile.get('fusden_total', scan=scan):.4e} reactions/m$^3$/s\n"
+ f"Plasma fusion rate density: {mfile.get('fusden_plasma', scan=scan):.4e} reactions/m$^3$/s"
)
axis.text(
@@ -12136,9 +12137,11 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
# ============================================================================
textstr_dt = (
- f"Total fusion power: {mfile.get('p_dt_total_mw', scan=scan):,.2f} MW\n"
- f"Plasma fusion power: {mfile.get('p_plasma_dt_mw', scan=scan):,.2f} MW \n"
- f"Beam fusion power: {mfile.get('p_beam_dt_mw', scan=scan):,.2f} MW\n"
+ f"Total fusion power: {mfile.get('p_dt_total_mw', scan=scan):,.4f} MW\n"
+ f"Total fusion rate: {mfile.get('fusrat_dt_total', scan=scan):.4e} reactions/s\n"
+ f"Plasma fusion power: {mfile.get('p_plasma_dt_mw', scan=scan):,.4f} MW \n"
+ f"Plasma fusion rate: {mfile.get('fusrat_plasma_dt', scan=scan):.4e} reactions/s\n"
+ f"Beam fusion power: {mfile.get('p_beam_dt_mw', scan=scan):,.4f} MW"
)
axis.text(
@@ -12158,7 +12161,7 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
)
axis.text(
- 0.24,
+ 0.285,
0.8,
"$\\text{D - T}$",
fontsize=20,
@@ -12169,13 +12172,16 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
# =================================================
textstr_dd = (
- f"Total fusion power: {mfile.get('p_dd_total_mw', scan=scan):,.2f} MW\n"
- f"Tritium branching ratio: {mfile.get('f_dd_branching_trit', scan=scan):.4f} \n"
+ f"Total fusion power: {mfile.get('p_dd_total_mw', scan=scan):,.4f} MW\n"
+ f"Tritium branching ratio: {mfile.get('f_dd_branching_trit', scan=scan):.4f} \n\n"
+ f"D+D -> T fusion rate: {mfile.get('fusrat_plasma_dd_triton', scan=scan):.4e} reactions/s \n"
+ f"D+D -> 3He fusion rate: {mfile.get('fusrat_plasma_dd_helion', scan=scan):.4e} reactions/s \n"
+ f"Total D-D fusion rate: {mfile.get('fusrat_plasma_dd_total', scan=scan):.4e} reactions/s"
)
axis.text(
0.05,
- 0.65,
+ 0.625,
textstr_dd,
fontsize=9,
verticalalignment="bottom",
@@ -12190,8 +12196,8 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
)
axis.text(
- 0.22,
- 0.685,
+ 0.31,
+ 0.69,
"$\\text{D - D}$",
fontsize=20,
verticalalignment="top",
@@ -12200,8 +12206,10 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
# =================================================
- textstr_dhe3 = f"Total fusion power: {mfile.get('p_dhe3_total_mw', scan=scan):,.2f} MW \n\n"
-
+ textstr_dhe3 = (
+ f"Total fusion power: {mfile.get('p_dhe3_total_mw', scan=scan):,.4f} MW \n"
+ f"D+3He fusion rate: {mfile.get('fusrat_plasma_dhe3', scan=scan):.4e} reactions/s \n"
+ )
axis.text(
0.05,
0.55,
@@ -12219,8 +12227,8 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
)
axis.text(
- 0.21,
- 0.59,
+ 0.285,
+ 0.58,
"$\\text{D - 3He}$",
fontsize=20,
verticalalignment="top",
@@ -12230,15 +12238,15 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
# =================================================
textstr_alpha = (
- f"Total power: {mfile.get('p_alpha_total_mw', scan=scan):.2f} MW\n"
- f"Plasma power: {mfile.get('p_plasma_alpha_mw', scan=scan):.2f} MW\n"
- f"Beam power: {mfile.get('p_beam_alpha_mw', scan=scan):.2f} MW\n\n"
- f"Rate density total: {mfile.get('fusden_alpha_total', scan=scan):.4e} particles/m3/sec\n"
- f"Rate density, plasma: {mfile.get('fusden_plasma_alpha', scan=scan):.4e} particles/m3/sec\n\n"
- f"Total power density: {mfile.get('pden_alpha_total_mw', scan=scan):.4e} MW/m3\n"
- f"Plasma power density: {mfile.get('pden_plasma_alpha_mw', scan=scan):.4e} MW/m3\n\n"
- f"Power per unit volume transferred to electrons: {mfile.get('f_pden_alpha_electron_mw', scan=scan):.4e} MW/m3\n"
- f"Power per unit volume transferred to ions: {mfile.get('f_pden_alpha_ions_mw', scan=scan):.4e} MW/m3\n\n"
+ f"Total power: {mfile.get('p_alpha_total_mw', scan=scan):.4f} MW\n"
+ f"Plasma power: {mfile.get('p_plasma_alpha_mw', scan=scan):.4f} MW\n"
+ f"Beam power: {mfile.get('p_beam_alpha_mw', scan=scan):.4f} MW\n\n"
+ f"Rate density total: {mfile.get('fusden_alpha_total', scan=scan):.4e} particles/m$^3$/s\n"
+ f"Rate density, plasma: {mfile.get('fusden_plasma_alpha', scan=scan):.4e} particles/m$^3$/s\n\n"
+ f"Total power density: {mfile.get('pden_alpha_total_mw', scan=scan):.4e} MW/m$^3$\n"
+ f"Plasma power density: {mfile.get('pden_plasma_alpha_mw', scan=scan):.4e} MW/m$^3$\n\n"
+ f"Power per unit volume transferred to electrons: {mfile.get('f_pden_alpha_electron_mw', scan=scan):.4e} MW/m$^3$\n"
+ f"Power per unit volume transferred to ions: {mfile.get('f_pden_alpha_ions_mw', scan=scan):.4e} MW/m$^3$"
)
axis.text(
@@ -12269,11 +12277,12 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
# =================================================
textstr_neutron = (
- f"Total power: {mfile.get('p_neutron_total_mw', scan=scan):,.2f} MW\n"
- f"Plasma power: {mfile.get('p_plasma_neutron_mw', scan=scan):,.2f} MW\n"
- f"Beam power: {mfile.get('p_beam_neutron_mw', scan=scan):,.2f} MW\n\n"
- f"Total power density: {mfile.get('pden_neutron_total_mw', scan=scan):,.4e} MW/m3\n"
- f"Plasma power density: {mfile.get('pden_plasma_neutron_mw', scan=scan):,.4e} MW/m3\n"
+ f"Total power: {mfile.get('p_neutron_total_mw', scan=scan):,.4f} MW\n"
+ f"Plasma power: {mfile.get('p_plasma_neutron_mw', scan=scan):,.4f} MW\n"
+ f"Beam power: {mfile.get('p_beam_neutron_mw', scan=scan):,.4f} MW\n\n"
+ f"Total power density: {mfile.get('pden_neutron_total_mw', scan=scan):,.4e} MW/m$^3$\n"
+ f"Plasma power density: {mfile.get('pden_plasma_neutron_mw', scan=scan):,.4e} MW/m$^3$\n\n"
+ f"Neutron production rate: {mfile.get('fusrat_neutron_production_total', scan=scan):.4e} particles/s"
)
axis.text(
@@ -12293,8 +12302,8 @@ def plot_fusion_rate_profiles(axis: plt.Axes, fig, mfile: MFile, scan: int):
)
axis.text(
- 0.25,
- 0.2,
+ 0.26,
+ 0.21,
"$n$",
fontsize=20,
verticalalignment="top",
@@ -16474,6 +16483,325 @@ def plot_pf_dimensions(
axis.set_aspect("equal", adjustable="box")
+def plot_tritium_flow_contour(axis: plt.Axes, mfile: MFile, scan: int):
+ """Plot contour of tritium flow rate vs recycling and fuelling rate."""
+ recycling_range = np.linspace(0.01, 0.99, 20)
+ fuelling_range = np.linspace(0.01, 1.0, 20)
+ tritium_flow = np.zeros((len(recycling_range), len(fuelling_range)))
+
+ for i, recycling in enumerate(recycling_range):
+ for j, fuelling in enumerate(fuelling_range):
+ plasma_fuelling = PlasmaFuelling()
+ tritium_flow[i, j] = plasma_fuelling.calculate_plasma_tritium_flow_rate(
+ f_molflow_plasma_fuelling_tritium=mfile.get(
+ "f_molflow_plasma_fuelling_tritium", scan=scan
+ ),
+ eta_plasma_fuelling=fuelling,
+ molflow_plasma_fuelling_vv_injected=mfile.get(
+ "molflow_plasma_fuelling_vv_injected", scan=scan
+ ),
+ molflow_beam_tritium_vv_injected=mfile.get(
+ "molflow_beam_tritium_vv_injected", scan=scan
+ ),
+ fusrat_dt_total=mfile.get("fusrat_dt_total", scan=scan),
+ fusrat_plasma_dd_triton=mfile.get("fusrat_plasma_dd_triton", scan=scan),
+ t_energy_confinement=mfile.get("t_energy_confinement", scan=scan),
+ f_plasma_particles_lcfs_recycled=recycling,
+ nd_plasma_fuel_ions_vol_avg=mfile.get(
+ "nd_plasma_fuel_ions_vol_avg", scan=scan
+ ),
+ vol_plasma=mfile.get("vol_plasma", scan=scan),
+ f_plasma_fuel_tritium=mfile.get("f_plasma_fuel_tritium", scan=scan),
+ )
+
+ contour = axis.contourf(
+ fuelling_range,
+ recycling_range,
+ tritium_flow,
+ levels=15,
+ cmap="seismic",
+ norm=plt.matplotlib.colors.CenteredNorm(vcenter=0),
+ )
+
+ axis.contour(
+ fuelling_range,
+ recycling_range,
+ tritium_flow,
+ levels=[0],
+ colors="black",
+ linewidths=2,
+ )
+
+ # Plot star for mfile values
+ recycling_mfile = mfile.get("f_plasma_particles_lcfs_recycled", scan=scan)
+ fuelling_mfile = mfile.get("eta_plasma_fuelling", scan=scan)
+ axis.plot(
+ fuelling_mfile,
+ recycling_mfile,
+ marker="*",
+ markersize=15,
+ color="yellow",
+ markeredgecolor="black",
+ markeredgewidth=1.5,
+ )
+
+ axis.set_xlabel("Fuelling Rate Efficiency ($\\eta_{\\text{fuelling}}$)")
+ axis.set_ylabel("Recycling Fraction [$R$]")
+ axis.set_title("Plasma Tritium Flow Rate (particles/s)", pad=20)
+ axis.minorticks_on()
+ axis.grid(True, which="major", linestyle="-", alpha=0.7)
+ axis.grid(True, which="minor", linestyle=":", alpha=0.4)
+ cbar = plt.colorbar(contour, ax=axis, label="Tritium Flow Rate")
+ cbar.ax.axhline(y=0, color="black", linewidth=2)
+
+
+def plot_deuterium_flow_contour(axis: plt.Axes, mfile: MFile, scan: int):
+ """Plot contour of deuterium flow rate vs recycling and fuelling rate."""
+ recycling_range = np.linspace(0.01, 0.99, 20)
+ fuelling_range = np.linspace(0.01, 1.0, 20)
+ deuterium_flow = np.zeros((len(recycling_range), len(fuelling_range)))
+
+ for i, recycling in enumerate(recycling_range):
+ for j, fuelling in enumerate(fuelling_range):
+ deuterium_flow[i, j] = PlasmaFuelling().calculate_plasma_deuterium_flow_rate(
+ f_molflow_plasma_fuelling_deuterium=mfile.get(
+ "f_molflow_plasma_fuelling_deuterium", scan=scan
+ ),
+ eta_plasma_fuelling=fuelling,
+ molflow_plasma_fuelling_vv_injected=mfile.get(
+ "molflow_plasma_fuelling_vv_injected", scan=scan
+ ),
+ molflow_beam_deuterium_vv_injected=mfile.get(
+ "molflow_beam_deuterium_vv_injected", scan=scan
+ ),
+ fusrat_dt_total=mfile.get("fusrat_dt_total", scan=scan),
+ fusrat_plasma_dhe3=mfile.get("fusrat_plasma_dhe3", scan=scan),
+ fusrat_plasma_dd_total=mfile.get("fusrat_plasma_dd_total", scan=scan),
+ t_energy_confinement=mfile.get("t_energy_confinement", scan=scan),
+ f_plasma_particles_lcfs_recycled=recycling,
+ nd_plasma_fuel_ions_vol_avg=mfile.get(
+ "nd_plasma_fuel_ions_vol_avg", scan=scan
+ ),
+ vol_plasma=mfile.get("vol_plasma", scan=scan),
+ f_plasma_fuel_deuterium=mfile.get("f_plasma_fuel_deuterium", scan=scan),
+ )
+
+ contour = axis.contourf(
+ fuelling_range,
+ recycling_range,
+ deuterium_flow,
+ levels=15,
+ cmap="seismic",
+ norm=plt.matplotlib.colors.CenteredNorm(vcenter=0),
+ )
+ axis.contour(
+ fuelling_range,
+ recycling_range,
+ deuterium_flow,
+ levels=[0],
+ colors="black",
+ linewidths=2,
+ )
+
+ # Plot star for mfile values
+ recycling_mfile = mfile.get("f_plasma_particles_lcfs_recycled", scan=scan)
+ fuelling_mfile = mfile.get("eta_plasma_fuelling", scan=scan)
+ axis.plot(
+ fuelling_mfile,
+ recycling_mfile,
+ marker="*",
+ markersize=15,
+ color="yellow",
+ markeredgecolor="black",
+ markeredgewidth=1.5,
+ )
+
+ axis.set_xlabel("Fuelling Rate Efficiency ($\\eta_{\\text{fuelling}}$)")
+ axis.set_title("Plasma Deuterium Flow Rate (particles/s)", pad=20)
+ axis.minorticks_on()
+ axis.grid(True, which="major", linestyle="-", alpha=0.7)
+ axis.grid(True, which="minor", linestyle=":", alpha=0.4)
+ cbar = plt.colorbar(contour, ax=axis, label="Deuterium Flow Rate")
+ cbar.ax.axhline(y=0, color="black", linewidth=2)
+
+
+def plot_alpha_flow_contour(axis: plt.Axes, mfile: MFile, scan: int):
+ """Plot contour of alpha particle flow rate vs recycling and fuelling rate."""
+ fusion_dt_range = np.linspace(1e19, 5e21, 20)
+ f_t_alpha_energy_confinement_range = np.linspace(2.0, 10.0, 20)
+ alpha_flow = np.zeros((
+ len(fusion_dt_range),
+ len(f_t_alpha_energy_confinement_range),
+ ))
+
+ for i, fusion_dt in enumerate(fusion_dt_range):
+ for j, f_t_alpha_energy_confinement in enumerate(
+ f_t_alpha_energy_confinement_range
+ ):
+ alpha_flow[i, j] = (
+ PlasmaFuelling().calculate_plasma_alphas_thermal_flow_rate(
+ fusrat_dt_total=fusion_dt,
+ fusrat_plasma_dhe3=mfile.get("fusrat_plasma_dhe3", scan=scan),
+ t_energy_confinement=mfile.get("t_energy_confinement", scan=scan),
+ nd_plasma_alphas_thermal_vol_avg=mfile.get(
+ "nd_plasma_alphas_thermal_vol_avg", scan=scan
+ ),
+ vol_plasma=mfile.get("vol_plasma", scan=scan),
+ f_t_alpha_energy_confinement=f_t_alpha_energy_confinement,
+ )
+ )
+
+ contour = axis.contourf(
+ f_t_alpha_energy_confinement_range,
+ fusion_dt_range,
+ alpha_flow,
+ levels=15,
+ cmap="seismic",
+ norm=plt.matplotlib.colors.CenteredNorm(vcenter=0),
+ )
+ axis.contour(
+ f_t_alpha_energy_confinement_range,
+ fusion_dt_range,
+ alpha_flow,
+ levels=[0],
+ colors="black",
+ linewidths=2,
+ )
+
+ # Plot star for mfile values
+ fusion_dt_mfile = mfile.get("fusrat_dt_total", scan=scan)
+ f_t_alpha_mfile = mfile.get("f_t_alpha_energy_confinement", scan=scan)
+ axis.plot(
+ f_t_alpha_mfile,
+ fusion_dt_mfile,
+ marker="*",
+ markersize=15,
+ color="yellow",
+ markeredgecolor="black",
+ markeredgewidth=1.5,
+ )
+
+ axis.set_xlabel(
+ "Alpha to Energy Confinement Time Ratio ($f_{\\alpha, \\text{energy confinement}}$)"
+ )
+ axis.set_ylabel("Fusion DT Rate [$\\text{particles/s}$]")
+ axis.set_title("Plasma Alpha Particle Flow Rate (particles/s)", pad=20)
+ axis.minorticks_on()
+ axis.grid(True, which="major", linestyle="-", alpha=0.7)
+ axis.grid(True, which="minor", linestyle=":", alpha=0.4)
+ cbar = plt.colorbar(contour, ax=axis, label="Alpha Particle Flow Rate")
+ cbar.ax.axhline(y=0, color="black", linewidth=2)
+
+
+def plot_helium3_flow_contour(axis: plt.Axes, mfile: MFile, scan: int):
+ """Plot contour of helium-3 flow rate vs recycling and fuelling rate."""
+ recycling_range = np.linspace(0.01, 0.99, 20)
+ fuelling_range = np.linspace(0.01, 1.0, 20)
+ helium3_flow = np.zeros((len(recycling_range), len(fuelling_range)))
+
+ for i, recycling in enumerate(recycling_range):
+ for j, fuelling in enumerate(fuelling_range):
+ helium3_flow[i, j] = PlasmaFuelling().calculate_plasma_helium3_flow_rate(
+ f_molflow_plasma_fuelling_helium3=mfile.get(
+ "f_molflow_plasma_fuelling_helium3", scan=scan
+ ),
+ eta_plasma_fuelling=fuelling,
+ molflow_plasma_fuelling_vv_injected=mfile.get(
+ "molflow_plasma_fuelling_vv_injected", scan=scan
+ ),
+ fusrat_plasma_dhe3=mfile.get("fusrat_plasma_dhe3", scan=scan),
+ fusrat_plasma_dd_helion=mfile.get("fusrat_plasma_dd_helion", scan=scan),
+ t_energy_confinement=mfile.get("t_energy_confinement", scan=scan),
+ f_plasma_particles_lcfs_recycled=recycling,
+ nd_plasma_fuel_ions_vol_avg=mfile.get(
+ "nd_plasma_fuel_ions_vol_avg", scan=scan
+ ),
+ vol_plasma=mfile.get("vol_plasma", scan=scan),
+ f_plasma_fuel_helium3=mfile.get("f_plasma_fuel_helium3", scan=scan),
+ )
+
+ contour = axis.contourf(
+ fuelling_range,
+ recycling_range,
+ helium3_flow,
+ levels=15,
+ cmap="seismic",
+ norm=plt.matplotlib.colors.CenteredNorm(vcenter=0),
+ )
+ axis.contour(
+ fuelling_range,
+ recycling_range,
+ helium3_flow,
+ levels=[0],
+ colors="black",
+ linewidths=2,
+ )
+
+ # Plot star for mfile values
+ recycling_mfile = mfile.get("f_plasma_particles_lcfs_recycled", scan=scan)
+ fuelling_mfile = mfile.get("eta_plasma_fuelling", scan=scan)
+ axis.plot(
+ fuelling_mfile,
+ recycling_mfile,
+ marker="*",
+ markersize=15,
+ color="yellow",
+ markeredgecolor="black",
+ )
+ axis.set_xlabel("Fuelling Rate Efficiency ($\\eta_{\\text{fuelling}}$)")
+ cbar = plt.colorbar(contour, ax=axis, label="Helium-3 Flow Rate")
+ cbar.ax.axhline(y=0, color="black", linewidth=2)
+ axis.set_title("Plasma Helium-3 Flow Rate (particles/s)", pad=20)
+ axis.minorticks_on()
+ axis.grid(True, which="major", linestyle="-", alpha=0.7)
+ axis.grid(True, which="minor", linestyle=":", alpha=0.4)
+
+
+def plot_fuelling_info(fig: plt.Figure, mfile: MFile, scan: int):
+ """Plot fuelling information."""
+ msg = (
+ f"$\\mathbf{{Plasma \\ Fuelling \\ Information:}}$\n\n"
+ f"Fuelling rate into vessel:"
+ f"{mfile.get('molflow_plasma_fuelling_vv_injected', scan=scan):.4e} particles/s\n"
+ f"Fuelling rate into vessel: "
+ f"{mfile.get('molflow_plasma_fuelling_vv_injected_moles', scan=scan):.4e} moles/s\n"
+ f"Additional deuterium beam fuelling: "
+ f"{mfile.get('molflow_beam_deuterium_vv_injected', scan=scan):.4e} particles/s\n"
+ f"Additional tritium beam fuelling: "
+ f"{mfile.get('molflow_beam_tritium_vv_injected', scan=scan):.4e} particles/s\n\n"
+ f"Fuelling loss that doesn't enter the plasma: "
+ f"{mfile.get('molflow_plasma_fuelling_loss', scan=scan):.4e} particles/s\n"
+ f"Fuelling loss that doesn't enter the plasma: "
+ f"{mfile.get('molflow_plasma_fuelling_loss_moles', scan=scan):.4e} moles/s\n"
+ f"Fuelling Rate Efficiency ($\\eta_{{\\text{{fuelling}}}}$): "
+ f"{mfile.get('eta_plasma_fuelling', scan=scan):.4f}\n"
+ f"Recycling Fraction ($R$): "
+ f"{mfile.get('f_plasma_particles_lcfs_recycled', scan=scan):.4f}\n\n"
+ f"Fraction of Tritium Fuelling: "
+ f"{mfile.get('f_molflow_plasma_fuelling_tritium', scan=scan):.4f}\n"
+ f"Fraction of Deuterium Fuelling: "
+ f"{mfile.get('f_molflow_plasma_fuelling_deuterium', scan=scan):.4f}\n"
+ f"Fraction of 3-Helium Fuelling: "
+ f"{mfile.get('f_molflow_plasma_fuelling_helium3', scan=scan):.4f}\n\n"
+ f"Total Fuel Burnup Fraction: "
+ f"{mfile.get('f_plasma_fuel_burnup', scan=scan):.4f}\n"
+ f"Tritium Burnup Fraction: "
+ f"{mfile.get('f_plasma_tritium_burnup', scan=scan):.4f}\n"
+ f"Deuterium Burnup Fraction: "
+ f"{mfile.get('f_plasma_deuterium_burnup', scan=scan):.4f}"
+ )
+ fig.text(
+ 0.75,
+ 0.25,
+ msg,
+ ha="center",
+ va="center",
+ transform=fig.transFigure,
+ fontsize=9,
+ bbox={"boxstyle": "round", "facecolor": "wheat", "alpha": 1.0},
+ )
+
+
def main_plot(
m_file: MFile,
scan: int,
@@ -16647,6 +16975,21 @@ def _add_page(name: str | None = None):
if m_file.get("i_plasma_shape", scan=scan) == PlasmaShapeModelType.SAUTER:
plot_fusion_rate_contours(pages["rx_1_2"], pages["rx_3_4"], m_file, scan)
+ plot_tritium_flow_contour(
+ axis=_add_page("fuelling").add_subplot(231), mfile=m_file, scan=scan
+ )
+ plot_deuterium_flow_contour(
+ axis=pages["fuelling"].add_subplot(232), mfile=m_file, scan=scan
+ )
+ plot_helium3_flow_contour(
+ axis=pages["fuelling"].add_subplot(233), mfile=m_file, scan=scan
+ )
+ plot_alpha_flow_contour(
+ axis=pages["fuelling"].add_subplot(223), mfile=m_file, scan=scan
+ )
+
+ plot_fuelling_info(pages["fuelling"], m_file, scan)
+
if i_shape != PlasmaShapeModelType.SAUTER:
msg = (
"Fusion-rate contour plots require a closed (Sauter) plasma boundary "
diff --git a/process/core/solver/constraints.py b/process/core/solver/constraints.py
index 72c11014fd..6826204d2c 100644
--- a/process/core/solver/constraints.py
+++ b/process/core/solver/constraints.py
@@ -14,6 +14,7 @@
from process.data_structure.build_variables import TFCSRadialConfiguration
from process.models.physics.density_limit import DensityLimitModel
from process.models.physics.exhaust import PlasmaExhaust
+from process.models.physics.fuelling import PlasmaFuelling
from process.models.physics.physics import (
BetaComponentLimits,
PlasmaBeta,
@@ -1955,6 +1956,155 @@ def constraint_equation_92(constraint_registration, data):
)
+@ConstraintManager.register_constraint(93, "particles/s", "=")
+def constraint_equation_93(constraint_registration, data):
+ """
+ Tritium particle balance consistency equation.
+
+ This constraint ensures that the tritium particle balance is maintained in the
+ plasma.
+
+ The numerator represents the total tritium sources, including fuelling and fusion
+ reactions, while the denominator represents the total tritium sinks, which are
+ related to the plasma volume, fuel ion density, and confinement time.
+
+ The equation ensures that the rate of tritium production equals the rate of tritium
+ loss, maintaining a steady-state condition for tritium in the plasma.
+ """
+ source = PlasmaFuelling.calculate_plasma_tritium_source_rate(
+ f_molflow_plasma_fuelling_tritium=data.physics.f_molflow_plasma_fuelling_tritium,
+ eta_plasma_fuelling=data.physics.eta_plasma_fuelling,
+ molflow_plasma_fuelling_vv_injected=data.physics.molflow_plasma_fuelling_vv_injected,
+ fusrat_plasma_dd_triton=data.physics.fusrat_plasma_dd_triton,
+ molflow_beam_tritium_vv_injected=data.physics.molflow_beam_tritium_vv_injected,
+ )
+ sink = PlasmaFuelling.calculate_plasma_tritium_loss_rate(
+ fusrat_dt_total=data.physics.fusrat_dt_total,
+ t_energy_confinement=data.physics.t_energy_confinement,
+ f_plasma_particles_lcfs_recycled=data.physics.f_plasma_particles_lcfs_recycled,
+ nd_plasma_fuel_ions_vol_avg=data.physics.nd_plasma_fuel_ions_vol_avg,
+ vol_plasma=data.physics.vol_plasma,
+ f_plasma_fuel_tritium=data.physics.f_plasma_fuel_tritium,
+ )
+
+ return eq(source, -sink, constraint_registration)
+
+
+@ConstraintManager.register_constraint(94, "particles/s", "=")
+def constraint_equation_94(constraint_registration, data):
+ """
+ Deuterium particle balance consistency equation.
+
+ This constraint ensures that the deuterium particle balance is maintained in the
+ plasma.
+
+ The numerator represents the total deuterium sources, including fuelling and fusion
+ reactions, while the denominator represents the total deuterium sinks, which are
+ related to the plasma volume, fuel ion density, and confinement time.
+
+ The equation ensures that the rate of deuterium production equals the rate of
+ deuterium loss, maintaining a steady-state condition for deuterium in the plasma.
+ """
+ source = PlasmaFuelling.calculate_plasma_deuterium_source_rate(
+ f_molflow_plasma_fuelling_deuterium=data.physics.f_molflow_plasma_fuelling_deuterium,
+ eta_plasma_fuelling=data.physics.eta_plasma_fuelling,
+ molflow_plasma_fuelling_vv_injected=data.physics.molflow_plasma_fuelling_vv_injected,
+ molflow_beam_deuterium_vv_injected=data.physics.molflow_beam_deuterium_vv_injected,
+ )
+ sink = PlasmaFuelling.calculate_plasma_deuterium_loss_rate(
+ fusrat_dt_total=data.physics.fusrat_dt_total,
+ fusrat_plasma_dd_total=data.physics.fusrat_plasma_dd_total,
+ fusrat_plasma_dhe3=data.physics.fusrat_plasma_dhe3,
+ t_energy_confinement=data.physics.t_energy_confinement,
+ f_plasma_particles_lcfs_recycled=data.physics.f_plasma_particles_lcfs_recycled,
+ nd_plasma_fuel_ions_vol_avg=data.physics.nd_plasma_fuel_ions_vol_avg,
+ vol_plasma=data.physics.vol_plasma,
+ f_plasma_fuel_deuterium=data.physics.f_plasma_fuel_deuterium,
+ )
+
+ return eq(source, -sink, constraint_registration)
+
+
+@ConstraintManager.register_constraint(95, "particles/s", "=")
+def constraint_equation_95(constraint_registration, data):
+ """
+ Helium-3 particle balance consistency equation.
+
+ This constraint ensures that the helium-3 particle balance is maintained in the
+ plasma.
+
+ The numerator represents the total helium-3 sources, including fuelling and fusion
+ reactions, while the denominator represents the total helium-3 sinks, which are
+ related to the plasma volume, fuel ion density, and confinement time.
+
+ The equation ensures that the rate of helium-3 production equals the rate of helium-3
+ loss, maintaining a steady-state condition for helium-3 in the plasma.
+ """
+ source = PlasmaFuelling.calculate_plasma_helium3_source_rate(
+ f_molflow_plasma_fuelling_helium3=data.physics.f_molflow_plasma_fuelling_helium3,
+ eta_plasma_fuelling=data.physics.eta_plasma_fuelling,
+ molflow_plasma_fuelling_vv_injected=data.physics.molflow_plasma_fuelling_vv_injected,
+ fusrat_plasma_dd_helion=data.physics.fusrat_plasma_dd_helion,
+ )
+ sink = PlasmaFuelling.calculate_plasma_helium3_loss_rate(
+ fusrat_plasma_dhe3=data.physics.fusrat_plasma_dhe3,
+ t_energy_confinement=data.physics.t_energy_confinement,
+ f_plasma_particles_lcfs_recycled=data.physics.f_plasma_particles_lcfs_recycled,
+ nd_plasma_fuel_ions_vol_avg=data.physics.nd_plasma_fuel_ions_vol_avg,
+ vol_plasma=data.physics.vol_plasma,
+ f_plasma_fuel_helium3=data.physics.f_plasma_fuel_helium3,
+ )
+
+ return eq(source, -sink, constraint_registration)
+
+
+@ConstraintManager.register_constraint(96, "particles/s", "=")
+def constraint_equation_96(constraint_registration, data):
+ """
+ Thermal alpha particle balance consistency equation.
+
+ This constraint ensures that the thermal alpha particle balance is maintained in the
+ plasma.
+
+ The numerator represents the total thermal alpha particle sources,
+ while the denominator represents the total thermal alpha particle sinks, which are
+ related to the plasma volume, fuel ion density, and confinement time.
+
+ The equation ensures that the rate of thermal alpha particle production equals the
+ rate of thermal alpha particle loss, maintaining a steady-state condition for
+ thermal alpha particles in the plasma.
+ """
+ source = PlasmaFuelling.calculate_plasma_alphas_thermal_source_rate(
+ fusrat_dt_total=data.physics.fusrat_dt_total,
+ fusrat_plasma_dhe3=data.physics.fusrat_plasma_dhe3,
+ )
+ sink = PlasmaFuelling.calculate_plasma_alphas_thermal_loss_rate(
+ nd_plasma_alphas_thermal_vol_avg=data.physics.nd_plasma_alphas_thermal_vol_avg,
+ vol_plasma=data.physics.vol_plasma,
+ t_energy_confinement=data.physics.t_energy_confinement,
+ f_t_alpha_energy_confinement=data.physics.f_t_alpha_energy_confinement,
+ )
+
+ return eq(source, -sink, constraint_registration)
+
+
+@ConstraintManager.register_constraint(97, "", "=")
+def constraint_equation_97(constraint_registration, data):
+ """Equation for checking the fuelling composition is consistent.
+
+ f_molflow_plasma_fuelling_deuterium: fraction of deuterium ions
+ f_molflow_plasma_fuelling_tritium: fraction of tritium ions
+ f_molflow_plasma_fuelling_helium3: fraction of helium-3 ions
+ """
+ return eq(
+ data.physics.f_molflow_plasma_fuelling_deuterium
+ + data.physics.f_molflow_plasma_fuelling_tritium
+ + data.physics.f_molflow_plasma_fuelling_helium3,
+ 1.0,
+ constraint_registration,
+ )
+
+
def constraint_eqns(m: int, ieqn: int, data: DataStructure):
"""Evaluates the constraints given the current state of PROCESS.
diff --git a/process/core/solver/iteration_variables.py b/process/core/solver/iteration_variables.py
index d1df7c6feb..65c25b7f4b 100644
--- a/process/core/solver/iteration_variables.py
+++ b/process/core/solver/iteration_variables.py
@@ -239,6 +239,32 @@ class IterationVariable:
175: IterationVariable("kappa", "physics", 0.00, 10.00),
176: IterationVariable("f_st_coil_aspect", "stellarator", 0.70, 1.30),
177: IterationVariable("f_a_tf_turn_cable_space_extra_void", "tfcoil", 0.01, 1.0),
+ 178: IterationVariable("f_plasma_particles_lcfs_recycled", "physics", 0.01, 1.0),
+ 179: IterationVariable("eta_plasma_fuelling", "physics", 0.01, 1.0),
+ 180: IterationVariable(
+ "molflow_plasma_fuelling_vv_injected",
+ "physics",
+ 1e18,
+ 1e22,
+ ),
+ 181: IterationVariable(
+ "f_molflow_plasma_fuelling_deuterium",
+ "physics",
+ 0.0,
+ 1.0,
+ ),
+ 182: IterationVariable(
+ "f_molflow_plasma_fuelling_tritium",
+ "physics",
+ 0.0,
+ 1.0,
+ ),
+ 183: IterationVariable(
+ "f_molflow_plasma_fuelling_helium3",
+ "physics",
+ 0.0,
+ 1.0,
+ ),
}
diff --git a/process/data_structure/numerics.py b/process/data_structure/numerics.py
index 43b0b78314..1c306b767b 100644
--- a/process/data_structure/numerics.py
+++ b/process/data_structure/numerics.py
@@ -292,6 +292,11 @@ class NumericsData:
"CS achievable stress load cycles lower limit ",
"ECRH ignitability ", # Stellarator constraint
"Fuel composition consistency ",
+ "Tritium particle balance consistency ",
+ "Deuterium particle balance consistency ",
+ "Helium-3 particle balance consistency ",
+ "Alpha particle balance consistency ",
+ "Fuelling composition consistency ",
]
)
"""Labels describing constraint equations (corresponding itvs)
diff --git a/process/data_structure/physics_variables.py b/process/data_structure/physics_variables.py
index 53d7bf343a..a23096476f 100644
--- a/process/data_structure/physics_variables.py
+++ b/process/data_structure/physics_variables.py
@@ -643,11 +643,14 @@ class PhysicsData:
e_plasma_magnetic_stored: float = 0.0
"""Plasma stored magnetic energy [J]"""
- burnup: float = 0.0
- """fractional plasma burnup"""
+ f_plasma_fuel_burnup: float = 0.0
+ """Total fuel burnup fraction in plasma"""
- burnup_in: float = 0.0
- """fractional plasma burnup user input"""
+ f_plasma_tritium_burnup: float = 0.0
+ """Tritium burnup fraction in plasma"""
+
+ f_plasma_deuterium_burnup: float = 0.0
+ """Deuterium burnup fraction in plasma"""
b_plasma_vertical_required: float = 0.0
"""Vertical field needed for plasma equilibrium (Bᵥ) [T]"""
@@ -803,6 +806,27 @@ class PhysicsData:
fusrat_total: float = 0.0
"""fusion reaction rate, from beams and plasma (reactions/sec)"""
+ fusrat_plasma_dt: float = 0.0
+ """ D-T fusion reaction rate in plasma, (reactions/sec)"""
+
+ fusrat_dt_total: float = 0.0
+ """ Total D-T fusion reaction rate from beams and plasma, (reactions/sec)"""
+
+ fusrat_plasma_dd_helion: float = 0.0
+ """D-D fusion reaction rate (helium branch) in plasma, (reactions/sec)"""
+
+ fusrat_plasma_dd_triton: float = 0.0
+ """D-D fusion reaction rate (tritium branch) in plasma, (reactions/sec)"""
+
+ fusrat_plasma_dd_total: float = 0.0
+ """Total D-D fusion reaction rate in plasma, (reactions/sec)"""
+
+ fusrat_plasma_dhe3: float = 0.0
+ """D-3He fusion reaction rate in plasma, (reactions/sec)"""
+
+ fusrat_neutron_production_total: float = 0.0
+ """Total neutron production rate from plasma and beams (neutrons/sec)"""
+
fusrat_plasma_dt_profile: list[float] = field(default_factory=list)
"""Profile of D-T fusion reaction rate in plasma, (reactions/sec)"""
@@ -1323,11 +1347,38 @@ class PhysicsData:
"""Plasma safety factor at 95% flux surface (q₉₅) (`iteration variable 18`)
"""
- molflow_plasma_fuelling_required: float = 0.0
- """plasma fuelling rate (nucleus-pairs/s)"""
+ f_plasma_particles_lcfs_recycled: float = 0.9
+ """Fraction of plasma particles that are recycled at the LCFS. Recycling coefficent (R)"""
+
+ eta_plasma_fuelling: float = 0.7
+ """Fuelling efficiency (η), fraction of fuel particles injected that become confined in the plasma"""
- tauratio: float = 1.0
- """tauratio /1.0/ : ratio of He and pellet particle confinement times"""
+ molflow_plasma_fuelling_vv_injected: float = 5e21
+ """Plasma fuelling rate into the vacuum vessel [particles/s]"""
+
+ molflow_plasma_fuelling_vv_injected_moles: float = 0.0
+ """Plasma fuelling rate into the vacuum vessel [moles/s]"""
+
+ molflow_plasma_fuelling_loss: float = 0.0
+ """Plasma fuelling rate that doesn't make it to plasma [particles/s]"""
+
+ molflow_plasma_fuelling_loss_moles: float = 0.0
+ """Plasma fuelling rate that doesn't make it to plasma [moles/s]"""
+
+ f_molflow_plasma_fuelling_deuterium: float = 0.5
+ """Fraction of plasma fuelling that is deuterium"""
+
+ f_molflow_plasma_fuelling_tritium: float = 0.5
+ """Fraction of plasma fuelling that is tritium"""
+
+ f_molflow_plasma_fuelling_helium3: float = 0.0
+ """Fraction of plasma fuelling that is helium-3"""
+
+ molflow_beam_deuterium_vv_injected: float = 0.0
+ """Beam deuterium injection rate into the vacuum vessel [particles/s]"""
+
+ molflow_beam_tritium_vv_injected: float = 0.0
+ """Beam tritium injection rate into the vacuum vessel [particles/s]"""
q95_min: float = 0.0
"""Plasmalower limit for edge safety factor"""
@@ -1374,9 +1425,6 @@ class PhysicsData:
f_nd_plasma_carbon_electron: float = 0.0
"""n_carbon / n_e"""
- rndfuel: float = 0.0
- """fuel burnup rate (reactions/second)"""
-
f_nd_plasma_iron_argon_electron: float = 0.0
"""n_highZ / n_e"""
diff --git a/process/main.py b/process/main.py
index 4f2c7ccfa8..356a23958a 100644
--- a/process/main.py
+++ b/process/main.py
@@ -80,6 +80,7 @@
)
from process.models.physics.density_limit import PlasmaDensityLimit
from process.models.physics.exhaust import PlasmaExhaust
+from process.models.physics.fuelling import PlasmaFuelling
from process.models.physics.impurity_radiation import (
initialise_imprad,
)
@@ -693,6 +694,7 @@ def __init__(self, data: DataStructure):
self.plasma_density_limit = PlasmaDensityLimit()
self.plasma_exhaust = PlasmaExhaust()
self.sauter_bootstrap_current = SauterBootstrapCurrent()
+ self.plasma_fuelling = PlasmaFuelling()
self.plasma_bootstrap_current = PlasmaBootstrapCurrent(
plasma_profile=self.plasma_profile,
sauter_bootstrap=self.sauter_bootstrap_current,
@@ -718,6 +720,7 @@ def __init__(self, data: DataStructure):
plasma_dia_current=self.plasma_dia_current,
plasma_geometry=self.plasma_geom,
scrape_off_layer=self.scrape_off_layer,
+ plasma_fuelling=self.plasma_fuelling,
)
self.physics_detailed = DetailedPhysics(
plasma_profile=self.plasma_profile,
@@ -824,6 +827,7 @@ def models(self) -> tuple[Model, ...]:
self.plasma_fields,
self.sauter_bootstrap_current,
self.plasma_transition,
+ self.plasma_fuelling,
self.physics_detailed,
self.electron_cyclotron,
self.lower_hybrid,
diff --git a/process/models/costs/costs.py b/process/models/costs/costs.py
index 208f98cbe0..2de33737f6 100644
--- a/process/models/costs/costs.py
+++ b/process/models/costs/costs.py
@@ -2354,7 +2354,7 @@ def acc2272(self):
# New calculation: 2 nuclei * reactions/sec * kg/nucleus * g/kg * sec/day
self.data.physics.wtgpd = (
2.0e0
- * self.data.physics.rndfuel
+ * self.data.physics.fusrat_total
* self.data.physics.m_fuel_amu
* constants.UMASS
* 1000.0e0
diff --git a/process/models/physics/fuelling.py b/process/models/physics/fuelling.py
new file mode 100644
index 0000000000..78dd95111d
--- /dev/null
+++ b/process/models/physics/fuelling.py
@@ -0,0 +1,840 @@
+"""Plasma fuelling model."""
+
+from process.core import constants
+from process.core import process_output as po
+from process.core.model import Model
+from process.data_structure import (
+ reinke_variables,
+)
+
+
+class PlasmaFuelling(Model):
+ """Class to hold plasma fuelling calculations and output."""
+
+ def __init__(self):
+
+ self.outfile = constants.NOUT
+ self.mfile = constants.MFILE
+
+ def run(self):
+ """Run the plasma fuelling model calculations."""
+ self.data.physics.molflow_plasma_fuelling_vv_injected_moles = (
+ self.data.physics.molflow_plasma_fuelling_vv_injected
+ / constants.AVOGADRO_NUMBER
+ )
+
+ self.data.physics.molflow_plasma_fuelling_loss = (
+ self.data.physics.molflow_plasma_fuelling_vv_injected
+ * (1 - self.data.physics.eta_plasma_fuelling)
+ )
+ self.data.physics.molflow_plasma_fuelling_loss_moles = (
+ self.data.physics.molflow_plasma_fuelling_loss / constants.AVOGADRO_NUMBER
+ )
+
+ self.data.physics.f_plasma_fuel_burnup = self.calculate_fuel_burnup_fraction(
+ fusrat_total=self.data.physics.fusrat_total,
+ molflow_plasma_fuelling_vv_injected=self.data.physics.molflow_plasma_fuelling_vv_injected,
+ molflow_beam_deuterium_vv_injected=self.data.physics.molflow_beam_deuterium_vv_injected,
+ molflow_beam_tritium_vv_injected=self.data.physics.molflow_beam_tritium_vv_injected,
+ )
+ self.data.physics.f_plasma_tritium_burnup = self.calculate_tritium_burnup_fraction( # noqa: E501
+ fusrat_dt_total=self.data.physics.fusrat_dt_total,
+ molflow_plasma_fuelling_vv_injected=self.data.physics.molflow_plasma_fuelling_vv_injected,
+ f_molflow_plasma_fuelling_tritium=self.data.physics.f_molflow_plasma_fuelling_tritium,
+ molflow_beam_tritium_vv_injected=self.data.physics.molflow_beam_tritium_vv_injected,
+ )
+
+ self.data.physics.f_plasma_deuterium_burnup = self.calculate_deuterium_burnup_fraction( # noqa: E501
+ fusrat_plasma_dd_total=self.data.physics.fusrat_plasma_dd_total,
+ molflow_plasma_fuelling_vv_injected=self.data.physics.molflow_plasma_fuelling_vv_injected,
+ molflow_beam_deuterium_vv_injected=self.data.physics.molflow_beam_deuterium_vv_injected,
+ f_molflow_plasma_fuelling_deuterium=self.data.physics.f_molflow_plasma_fuelling_deuterium,
+ fusrat_dt_total=self.data.physics.fusrat_dt_total,
+ fusrat_plasma_dhe3=self.data.physics.fusrat_plasma_dhe3,
+ )
+
+ def output(self):
+ """Model doesn't output to the output file, but it does generate contour
+ plots of plasma fuel flow rates vs recycling and fuelling efficiency.
+ """
+
+ @staticmethod
+ def calculate_fuel_burnup_fraction(
+ fusrat_total: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ molflow_beam_deuterium_vv_injected: float,
+ molflow_beam_tritium_vv_injected: float,
+ ) -> float:
+ """Calculate the fuel burnup fraction
+
+ Parameters
+ ----------
+ fusrat_total : float
+ Total fusion rate (particles/s).
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate into vacuum vessel (particles/s).
+ molflow_beam_deuterium_vv_injected : float
+ Beam deuterium injection rate into the vacuum vessel (particles/s).
+ molflow_beam_tritium_vv_injected : float
+ Beam tritium injection rate into the vacuum vessel (particles/s).
+
+ Returns
+ -------
+ Fuel burnup fraction (dimensionless).
+
+ Notes
+ -----
+ The fusion rate is multiplied by two to convert from nucleus pairs to particles,
+ as the fuelling rate is in particles/s.
+
+ """
+ return (
+ 2
+ * fusrat_total
+ / (
+ molflow_plasma_fuelling_vv_injected
+ + molflow_beam_deuterium_vv_injected
+ + molflow_beam_tritium_vv_injected
+ )
+ )
+
+ @staticmethod
+ def calculate_tritium_burnup_fraction(
+ fusrat_dt_total: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ f_molflow_plasma_fuelling_tritium: float,
+ molflow_beam_tritium_vv_injected: float,
+ ) -> float:
+ """Calculate the tritium burnup fraction
+
+ Parameters
+ ----------
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate into vacuum vessel (particles/s).
+ f_molflow_plasma_fuelling_tritium : float
+ Fraction of tritium in the plasma fuelling.
+ molflow_beam_tritium_vv_injected : float
+ Beam tritium injection rate into the vacuum vessel (particles/s).
+
+ Returns
+ -------
+ Tritium burnup fraction (dimensionless).
+
+ Notes
+ -----
+ The fusion rate is multiplied by two to convert from nucleus pairs to particles,
+ as the fuelling rate is in particles/s.
+
+ """
+ return fusrat_dt_total / (
+ (molflow_plasma_fuelling_vv_injected * f_molflow_plasma_fuelling_tritium)
+ + molflow_beam_tritium_vv_injected
+ )
+
+ @staticmethod
+ def calculate_deuterium_burnup_fraction(
+ fusrat_dt_total: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ molflow_beam_deuterium_vv_injected: float,
+ f_molflow_plasma_fuelling_deuterium: float,
+ fusrat_plasma_dd_total: float,
+ fusrat_plasma_dhe3: float,
+ ) -> float:
+ """Calculate the deuterium burnup fraction
+
+ Parameters
+ ----------
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate into vacuum vessel (particles/s).
+ molflow_beam_deuterium_vv_injected : float
+ Beam deuterium injection rate into the vacuum vessel (particles/s).
+ f_molflow_plasma_fuelling_deuterium : float
+ Fraction of deuterium in the plasma fuelling.
+ fusrat_plasma_dd_total : float
+ Total deuterium consumption rate from DD fusion (particles/s).
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+
+ Returns
+ -------
+ Deuterium burnup fraction (dimensionless).
+
+ Notes
+ -----
+ The fusion rate is multiplied by two to convert from nucleus pairs to particles,
+ as the fuelling rate is in particles/s.
+
+ """
+ return (fusrat_dt_total + 2 * fusrat_plasma_dd_total + fusrat_plasma_dhe3) / (
+ (molflow_plasma_fuelling_vv_injected * f_molflow_plasma_fuelling_deuterium)
+ + molflow_beam_deuterium_vv_injected
+ )
+
+ def calculate_plasma_tritium_flow_rate(
+ self,
+ f_molflow_plasma_fuelling_tritium: float,
+ eta_plasma_fuelling: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ molflow_beam_tritium_vv_injected: float,
+ fusrat_dt_total: float,
+ fusrat_plasma_dd_triton: float,
+ t_energy_confinement: float,
+ f_plasma_particles_lcfs_recycled: float,
+ nd_plasma_fuel_ions_vol_avg: float,
+ vol_plasma: float,
+ f_plasma_fuel_tritium: float,
+ ) -> float:
+ """Calculate the tritium flow rate into the plasma.
+
+ Parameters
+ ----------
+ f_molflow_plasma_fuelling_tritium : float
+ Fraction of tritium in the plasma fuelling.
+ eta_plasma_fuelling : float
+ Fuelling rate efficiency.
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate (particles/s).
+ molflow_beam_tritium_vv_injected : float
+ Beam tritium injection rate into the vacuum vessel (particles/s).
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ fusrat_plasma_dd_triton : float
+ Tritium production rate from DD fusion (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_plasma_particles_lcfs_recycled : float
+ Fraction of plasma particles recycled at the LCFS.
+ nd_plasma_fuel_ions_vol_avg : float
+ Volume-averaged density of fuel ions in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+ f_plasma_fuel_tritium : float
+ Fraction of tritium in the plasma fuel.
+
+ Returns
+ -------
+ float
+ Tritium flow rate into the plasma (particles/s).
+
+ Notes
+ -----
+ - A positive value indicates a net flow of tritium into the plasma,
+ while a negative value indicates a net loss of tritium from the plasma.
+
+ """
+ return self.calculate_plasma_tritium_source_rate(
+ f_molflow_plasma_fuelling_tritium=f_molflow_plasma_fuelling_tritium,
+ eta_plasma_fuelling=eta_plasma_fuelling,
+ molflow_plasma_fuelling_vv_injected=molflow_plasma_fuelling_vv_injected,
+ fusrat_plasma_dd_triton=fusrat_plasma_dd_triton,
+ molflow_beam_tritium_vv_injected=molflow_beam_tritium_vv_injected,
+ ) + self.calculate_plasma_tritium_loss_rate(
+ fusrat_dt_total=fusrat_dt_total,
+ t_energy_confinement=t_energy_confinement,
+ f_plasma_particles_lcfs_recycled=f_plasma_particles_lcfs_recycled,
+ nd_plasma_fuel_ions_vol_avg=nd_plasma_fuel_ions_vol_avg,
+ vol_plasma=vol_plasma,
+ f_plasma_fuel_tritium=f_plasma_fuel_tritium,
+ )
+
+ @staticmethod
+ def calculate_plasma_tritium_source_rate(
+ f_molflow_plasma_fuelling_tritium: float,
+ eta_plasma_fuelling: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ fusrat_plasma_dd_triton: float,
+ molflow_beam_tritium_vv_injected: float,
+ ) -> float:
+ """Calculate the tritium source rate in the plasma.
+
+ Parameters
+ ----------
+ f_molflow_plasma_fuelling_tritium : float
+ Fraction of tritium in the plasma fuelling.
+ eta_plasma_fuelling : float
+ Fuelling rate efficiency.
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate (particles/s).
+ fusrat_plasma_dd_triton : float
+ Tritium production rate from D-D fusion (particles/s).
+ molflow_beam_tritium_vv_injected : float
+ Beam tritium injection rate into the vacuum vessel (particles/s).
+
+ Returns
+ -------
+ float
+ Tritium source rate in the plasma (particles/s).
+
+ """
+ return (
+ (
+ f_molflow_plasma_fuelling_tritium
+ * eta_plasma_fuelling
+ * molflow_plasma_fuelling_vv_injected
+ )
+ + fusrat_plasma_dd_triton
+ + molflow_beam_tritium_vv_injected
+ )
+
+ @staticmethod
+ def calculate_plasma_tritium_loss_rate(
+ fusrat_dt_total: float,
+ t_energy_confinement: float,
+ f_plasma_particles_lcfs_recycled: float,
+ nd_plasma_fuel_ions_vol_avg: float,
+ vol_plasma: float,
+ f_plasma_fuel_tritium: float,
+ ) -> float:
+ """Calculate the tritium loss rate from the plasma.
+
+ Parameters
+ ----------
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_plasma_particles_lcfs_recycled : float
+ Fraction of plasma particles recycled at the LCFS.
+ nd_plasma_fuel_ions_vol_avg : float
+ Volume-averaged density of fuel ions in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+ f_plasma_fuel_tritium : float
+ Fraction of tritium in the plasma fuel.
+
+ Returns
+ -------
+ float
+ Tritium loss rate from the plasma (particles/s).
+
+ """
+ return -fusrat_dt_total - (
+ (nd_plasma_fuel_ions_vol_avg * vol_plasma * f_plasma_fuel_tritium)
+ / (t_energy_confinement / (1 - f_plasma_particles_lcfs_recycled))
+ )
+
+ @staticmethod
+ def calculate_plasma_deuterium_source_rate(
+ f_molflow_plasma_fuelling_deuterium: float,
+ eta_plasma_fuelling: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ molflow_beam_deuterium_vv_injected: float,
+ ) -> float:
+ """Calculate the deuterium source rate in the plasma.
+
+ Parameters
+ ----------
+ f_molflow_plasma_fuelling_deuterium : float
+ Fraction of deuterium in the plasma fuelling.
+ eta_plasma_fuelling : float
+ Fuelling rate efficiency.
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate (particles/s).
+ molflow_beam_deuterium_vv_injected : float
+ Beam deuterium injection rate into the vacuum vessel (particles/s).
+
+ Returns
+ -------
+ float
+ Deuterium source rate in the plasma (particles/s).
+
+ """
+ return (
+ f_molflow_plasma_fuelling_deuterium
+ * eta_plasma_fuelling
+ * molflow_plasma_fuelling_vv_injected
+ ) + molflow_beam_deuterium_vv_injected
+
+ @staticmethod
+ def calculate_plasma_deuterium_loss_rate(
+ fusrat_dt_total: float,
+ fusrat_plasma_dd_total: float,
+ fusrat_plasma_dhe3: float,
+ t_energy_confinement: float,
+ f_plasma_particles_lcfs_recycled: float,
+ nd_plasma_fuel_ions_vol_avg: float,
+ vol_plasma: float,
+ f_plasma_fuel_deuterium: float,
+ ) -> float:
+ """Calculate the deuterium loss rate from the plasma.
+
+ Parameters
+ ----------
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ fusrat_plasma_dd_total : float
+ Total deuterium consumption rate from DD fusion (particles/s).
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_plasma_particles_lcfs_recycled : float
+ Fraction of plasma particles recycled at the LCFS.
+ nd_plasma_fuel_ions_vol_avg : float
+ Volume-averaged density of fuel ions in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+ f_plasma_fuel_deuterium : float
+ Fraction of deuterium in the plasma fuel.
+
+ Returns
+ -------
+ float
+ Deuterium loss rate from the plasma (particles/s).
+
+ """
+ return (
+ -fusrat_dt_total
+ - 2 * fusrat_plasma_dd_total
+ - fusrat_plasma_dhe3
+ - (
+ (nd_plasma_fuel_ions_vol_avg * vol_plasma * f_plasma_fuel_deuterium)
+ / (t_energy_confinement / (1 - f_plasma_particles_lcfs_recycled))
+ )
+ )
+
+ def calculate_plasma_deuterium_flow_rate(
+ self,
+ f_molflow_plasma_fuelling_deuterium: float,
+ eta_plasma_fuelling: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ molflow_beam_deuterium_vv_injected: float,
+ fusrat_dt_total: float,
+ fusrat_plasma_dhe3: float,
+ fusrat_plasma_dd_total: float,
+ t_energy_confinement: float,
+ f_plasma_particles_lcfs_recycled: float,
+ nd_plasma_fuel_ions_vol_avg: float,
+ vol_plasma: float,
+ f_plasma_fuel_deuterium: float,
+ ) -> float:
+ """Calculate the deuterium flow rate into the plasma.
+
+ Parameters
+ ----------
+ f_molflow_plasma_fuelling_deuterium : float
+ Fraction of deuterium in the plasma fuelling.
+ eta_plasma_fuelling : float
+ Fuelling rate efficiency.
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate (particles/s).
+ molflow_beam_deuterium_vv_injected : float
+ Beam deuterium injection rate into the vacuum vessel (particles/s).
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+ fusrat_plasma_dd_total : float
+ Total deuterium consumption rate from DD fusion (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_plasma_particles_lcfs_recycled : float
+ Fraction of plasma particles recycled at the LCFS.
+ nd_plasma_fuel_ions_vol_avg : float
+ Volume-averaged density of fuel ions in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+ f_plasma_fuel_deuterium : float
+ Fraction of deuterium in the plasma fuel.
+
+ Returns
+ -------
+ float
+ Deuterium flow rate into the plasma (particles/s).
+
+ Notes
+ -----
+ - A positive value indicates a net flow of deuterium into the plasma,
+ while a negative value indicates a net loss of deuterium from the plasma.
+
+
+ """
+ return self.calculate_plasma_deuterium_source_rate(
+ f_molflow_plasma_fuelling_deuterium=f_molflow_plasma_fuelling_deuterium,
+ eta_plasma_fuelling=eta_plasma_fuelling,
+ molflow_plasma_fuelling_vv_injected=molflow_plasma_fuelling_vv_injected,
+ molflow_beam_deuterium_vv_injected=molflow_beam_deuterium_vv_injected,
+ ) + self.calculate_plasma_deuterium_loss_rate(
+ fusrat_dt_total=fusrat_dt_total,
+ fusrat_plasma_dd_total=fusrat_plasma_dd_total,
+ fusrat_plasma_dhe3=fusrat_plasma_dhe3,
+ t_energy_confinement=t_energy_confinement,
+ f_plasma_particles_lcfs_recycled=f_plasma_particles_lcfs_recycled,
+ nd_plasma_fuel_ions_vol_avg=nd_plasma_fuel_ions_vol_avg,
+ vol_plasma=vol_plasma,
+ f_plasma_fuel_deuterium=f_plasma_fuel_deuterium,
+ )
+
+ @staticmethod
+ def calculate_plasma_helium3_source_rate(
+ f_molflow_plasma_fuelling_helium3: float,
+ eta_plasma_fuelling: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ fusrat_plasma_dd_helion: float,
+ ) -> float:
+ """Calculate the helium-3 source rate in the plasma.
+
+ Parameters
+ ----------
+ f_molflow_plasma_fuelling_helium3 : float
+ Fraction of helium-3 in the plasma fuelling.
+ eta_plasma_fuelling : float
+ Fuelling rate efficiency.
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate (particles/s).
+ fusrat_plasma_dd_helion : float
+ Helium-3 production rate from DD fusion (particles/s).
+
+ Returns
+ -------
+ float
+ Helium-3 source rate in the plasma (particles/s).
+
+ """
+ return (
+ f_molflow_plasma_fuelling_helium3
+ * eta_plasma_fuelling
+ * molflow_plasma_fuelling_vv_injected
+ ) + fusrat_plasma_dd_helion
+
+ @staticmethod
+ def calculate_plasma_helium3_loss_rate(
+ fusrat_plasma_dhe3: float,
+ t_energy_confinement: float,
+ f_plasma_particles_lcfs_recycled: float,
+ nd_plasma_fuel_ions_vol_avg: float,
+ vol_plasma: float,
+ f_plasma_fuel_helium3: float,
+ ) -> float:
+ """Calculate the helium-3 loss rate from the plasma.
+
+ Parameters
+ ----------
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_plasma_particles_lcfs_recycled : float
+ Fraction of plasma particles recycled at the LCFS.
+ nd_plasma_fuel_ions_vol_avg : float
+ Volume-averaged density of fuel ions in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+ f_plasma_fuel_helium3 : float
+ Fraction of helium-3 in the plasma fuel.
+
+ Returns
+ -------
+ float
+ Helium-3 loss rate from the plasma (particles/s).
+
+
+ """
+ return -fusrat_plasma_dhe3 - (
+ (nd_plasma_fuel_ions_vol_avg * vol_plasma * f_plasma_fuel_helium3)
+ / (t_energy_confinement / (1 - f_plasma_particles_lcfs_recycled))
+ )
+
+ def calculate_plasma_helium3_flow_rate(
+ self,
+ f_molflow_plasma_fuelling_helium3: float,
+ eta_plasma_fuelling: float,
+ molflow_plasma_fuelling_vv_injected: float,
+ fusrat_plasma_dhe3: float,
+ fusrat_plasma_dd_helion: float,
+ t_energy_confinement: float,
+ f_plasma_particles_lcfs_recycled: float,
+ nd_plasma_fuel_ions_vol_avg: float,
+ vol_plasma: float,
+ f_plasma_fuel_helium3: float,
+ ) -> float:
+ """Calculate the helium-3 flow rate into the plasma.
+
+ Parameters
+ ----------
+ f_molflow_plasma_fuelling_helium3 : float
+ Fraction of helium-3 in the plasma fuelling.
+ eta_plasma_fuelling : float
+ Fuelling rate efficiency.
+ molflow_plasma_fuelling_vv_injected : float
+ Total fuelling rate (particles/s).
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+ fusrat_plasma_dd_helion : float
+ Helium-3 production rate from DD fusion (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_plasma_particles_lcfs_recycled : float
+ Fraction of plasma particles recycled at the LCFS.
+ nd_plasma_fuel_ions_vol_avg : float
+ Volume-averaged density of fuel ions in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+ f_plasma_fuel_helium3 : float
+ Fraction of helium-3 in the plasma fuel.
+
+ Returns
+ -------
+ float
+ Helium-3 flow rate into the plasma (particles/s).
+
+ Notes
+ -----
+ - A positive value indicates a net flow of helium-3 into the plasma,
+ while a negative value indicates a net loss of helium-3 from the plasma.
+
+ """
+ return self.calculate_plasma_helium3_source_rate(
+ f_molflow_plasma_fuelling_helium3=f_molflow_plasma_fuelling_helium3,
+ eta_plasma_fuelling=eta_plasma_fuelling,
+ molflow_plasma_fuelling_vv_injected=molflow_plasma_fuelling_vv_injected,
+ fusrat_plasma_dd_helion=fusrat_plasma_dd_helion,
+ ) + self.calculate_plasma_helium3_loss_rate(
+ fusrat_plasma_dhe3=fusrat_plasma_dhe3,
+ t_energy_confinement=t_energy_confinement,
+ f_plasma_particles_lcfs_recycled=f_plasma_particles_lcfs_recycled,
+ nd_plasma_fuel_ions_vol_avg=nd_plasma_fuel_ions_vol_avg,
+ vol_plasma=vol_plasma,
+ f_plasma_fuel_helium3=f_plasma_fuel_helium3,
+ )
+
+ @staticmethod
+ def calculate_plasma_alphas_thermal_source_rate(
+ fusrat_dt_total: float,
+ fusrat_plasma_dhe3: float,
+ ) -> float:
+ """Calculate the thermal alpha particle source rate in the plasma.
+
+ Parameters
+ ----------
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+
+ Returns
+ -------
+ float
+ Thermal alpha particle source rate in the plasma (particles/s).
+
+ """
+ return fusrat_dt_total + fusrat_plasma_dhe3
+
+ @staticmethod
+ def calculate_plasma_alphas_thermal_loss_rate(
+ t_energy_confinement: float,
+ f_t_alpha_energy_confinement: float,
+ nd_plasma_alphas_thermal_vol_avg: float,
+ vol_plasma: float,
+ ) -> float:
+ """Calculate the thermal alpha particle loss rate from the plasma.
+
+ Parameters
+ ----------
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_t_alpha_energy_confinement : float
+ Ratio of alpha particle confinement time to energy confinement time
+ (dimensionless).
+ nd_plasma_alphas_thermal_vol_avg : float
+ Volume-averaged density of thermal alpha particles in the plasma
+ (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+
+ Returns
+ -------
+ float
+ Thermal alpha particle loss rate from the plasma (particles/s).
+
+ """
+ return -(nd_plasma_alphas_thermal_vol_avg * vol_plasma) / (
+ t_energy_confinement * f_t_alpha_energy_confinement
+ )
+
+ def calculate_plasma_alphas_thermal_flow_rate(
+ self,
+ fusrat_dt_total: float,
+ fusrat_plasma_dhe3: float,
+ t_energy_confinement: float,
+ f_t_alpha_energy_confinement: float,
+ nd_plasma_alphas_thermal_vol_avg: float,
+ vol_plasma: float,
+ ) -> float:
+ """Calculate the net thermal alpha particle flow rate into the plasma.
+
+ Parameters
+ ----------
+ fusrat_dt_total : float
+ Total DT fusion rate (particles/s).
+ fusrat_plasma_dhe3 : float
+ Deuterium consumption rate from D-He3 fusion (particles/s).
+ t_energy_confinement : float
+ Energy confinement time (s).
+ f_t_alpha_energy_confinement : float
+ Ratio of alpha particle confinement time to energy confinement time
+ (dimensionless).
+ nd_plasma_alphas_thermal_vol_avg : float
+ Volume-averaged density of alpha particles in the plasma (particles/m³).
+ vol_plasma : float
+ Plasma volume (m³).
+
+ Returns
+ -------
+ float
+ Thermal alpha particle flow rate into the plasma (particles/s).
+
+ Notes
+ -----
+ - A positive value indicates a net flow of thermal alpha particles into the
+ plasma, while a negative value indicates a net loss of thermal alpha particles
+ from the plasma.
+
+ """
+ return self.calculate_plasma_alphas_thermal_source_rate(
+ fusrat_dt_total=fusrat_dt_total, fusrat_plasma_dhe3=fusrat_plasma_dhe3
+ ) + self.calculate_plasma_alphas_thermal_loss_rate(
+ t_energy_confinement=t_energy_confinement,
+ f_t_alpha_energy_confinement=f_t_alpha_energy_confinement,
+ nd_plasma_alphas_thermal_vol_avg=nd_plasma_alphas_thermal_vol_avg,
+ vol_plasma=vol_plasma,
+ )
+
+ def output_fuelling_info(self):
+ """Output fuelling information to mfile."""
+ po.oheadr(self.outfile, "Plasma Fuelling")
+ po.ovarre(
+ self.outfile,
+ "Fuelling rate into vessel [particles/s]",
+ "(molflow_plasma_fuelling_vv_injected)",
+ self.data.physics.molflow_plasma_fuelling_vv_injected,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fuelling rate into vessel [moles/s]",
+ "(molflow_plasma_fuelling_vv_injected_moles)",
+ self.data.physics.molflow_plasma_fuelling_vv_injected_moles,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fuelling loss that doesn't enter the plasma [particles/s]",
+ "(molflow_plasma_fuelling_loss)",
+ self.data.physics.molflow_plasma_fuelling_loss,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fuelling loss that doesn't enter the plasma [moles/s]",
+ "(molflow_plasma_fuelling_loss_moles)",
+ self.data.physics.molflow_plasma_fuelling_loss_moles,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "Beam deuterium injection rate into the vacuum vessel [particles/s]",
+ "(molflow_beam_deuterium_vv_injected)",
+ self.data.physics.molflow_beam_deuterium_vv_injected,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Beam tritium injection rate into the vacuum vessel [particles/s]",
+ "(molflow_beam_tritium_vv_injected)",
+ self.data.physics.molflow_beam_tritium_vv_injected,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "Fraction of plasma fuelling that is deuterium",
+ "(f_molflow_plasma_fuelling_deuterium)",
+ self.data.physics.f_molflow_plasma_fuelling_deuterium,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fraction of plasma fuelling that is tritium",
+ "(f_molflow_plasma_fuelling_tritium)",
+ self.data.physics.f_molflow_plasma_fuelling_tritium,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fraction of plasma fuelling that is helium-3",
+ "(f_molflow_plasma_fuelling_helium3)",
+ self.data.physics.f_molflow_plasma_fuelling_helium3,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "Fuelling efficiency",
+ "(eta_plasma_fuelling)",
+ self.data.physics.eta_plasma_fuelling,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fraction of plasma particles recycled at the LCFS",
+ "(f_plasma_particles_lcfs_recycled)",
+ self.data.physics.f_plasma_particles_lcfs_recycled,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Fuel burn-up rate [reactions/s]",
+ "(fusrat_total)",
+ self.data.physics.fusrat_total,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "Total fuel burn-up fraction",
+ "(f_plasma_fuel_burnup)",
+ self.data.physics.f_plasma_fuel_burnup,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Tritium burn-up fraction",
+ "(f_plasma_tritium_burnup)",
+ self.data.physics.f_plasma_tritium_burnup,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Deuterium burn-up fraction",
+ "(f_plasma_deuterium_burnup)",
+ self.data.physics.f_plasma_deuterium_burnup,
+ "OP ",
+ )
+
+ if 78 in self.data.numerics.icc:
+ po.osubhd(self.outfile, "Reinke Criterion :")
+ po.ovarin(
+ self.outfile,
+ "index of impurity to be iterated for divertor detachment",
+ "(impvardiv)",
+ reinke_variables.impvardiv,
+ )
+ po.ovarre(
+ self.outfile,
+ "Minimum Impurity fraction from Reinke",
+ "(fzmin)",
+ reinke_variables.fzmin,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "Actual Impurity fraction",
+ "(fzactual)",
+ reinke_variables.fzactual,
+ )
diff --git a/process/models/physics/fusion_reactions.py b/process/models/physics/fusion_reactions.py
index 53d44266ff..5cceb0fcc0 100644
--- a/process/models/physics/fusion_reactions.py
+++ b/process/models/physics/fusion_reactions.py
@@ -347,6 +347,10 @@ def dhe3_reaction(self):
alpha_rate_density = fusion_rate_density
proton_rate_density = fusion_rate_density # Proton production rate [m^3/second]
+ self.data.physics.fusrat_plasma_dhe3 = (
+ fusion_rate_density * self.data.physics.vol_plasma
+ )
+
# Update the cumulative D-3He power density
self.dhe3_power_density = fusion_power_density
@@ -451,6 +455,10 @@ def dd_helion_reaction(self):
alpha_rate_density = 0.0
proton_rate_density = 0.0
+ self.data.physics.fusrat_plasma_dd_helion = (
+ fusion_rate_density * self.data.physics.vol_plasma
+ )
+
# Update the cumulative D-D power density
self.dd_power_density += fusion_power_density
@@ -551,6 +559,10 @@ def dd_triton_reaction(self):
# Proton production rate [particles/m³/s]
proton_rate_density = fusion_rate_density
+ self.data.physics.fusrat_plasma_dd_triton = (
+ fusion_rate_density * self.data.physics.vol_plasma
+ )
+
# Update the cumulative D-D power density
self.dd_power_density += fusion_power_density
diff --git a/process/models/physics/physics.py b/process/models/physics/physics.py
index b6e1ce43dc..4861038169 100644
--- a/process/models/physics/physics.py
+++ b/process/models/physics/physics.py
@@ -39,6 +39,7 @@
)
from process.models.physics.density_limit import PlasmaDensityLimit
from process.models.physics.exhaust import PlasmaExhaust
+ from process.models.physics.fuelling import PlasmaFuelling
from process.models.physics.l_h_transition import PlasmaConfinementTransition
from process.models.physics.plasma_current import (
PlasmaCurrent,
@@ -199,6 +200,7 @@ def __init__(
plasma_dia_current: PlasmaDiamagneticCurrent,
plasma_geometry: PlasmaGeom,
scrape_off_layer: ScrapeOffLayer,
+ plasma_fuelling: PlasmaFuelling,
):
self.outfile = constants.NOUT
self.mfile = constants.MFILE
@@ -216,6 +218,7 @@ def __init__(
self.dia_current = plasma_dia_current
self.geometry = plasma_geometry
self.scrape_off_layer = scrape_off_layer
+ self.fuelling = plasma_fuelling
def output(self) -> None:
"""Output plasma physics information."""
@@ -669,6 +672,17 @@ def run(self):
self.data.physics.p_beam_dt_mw = self.data.physics.p_beam_alpha_mw * (
1 / (1 - constants.DT_NEUTRON_ENERGY_FRACTION)
)
+
+ self.data.physics.molflow_beam_deuterium_vv_injected = (
+ self.data.current_drive.c_beam_total
+ * (1.0 - self.data.current_drive.f_beam_tritium)
+ / constants.ELECTRON_CHARGE
+ )
+ self.data.physics.molflow_beam_tritium_vv_injected = (
+ self.data.current_drive.c_beam_total
+ * self.data.current_drive.f_beam_tritium
+ / constants.ELECTRON_CHARGE
+ )
else:
# If no beams present then the total alpha rates and power are the same as
# the plasma values
@@ -680,6 +694,22 @@ def run(self):
self.data.physics.fusden_total * self.data.physics.vol_plasma
)
+ self.data.physics.fusrat_plasma_dt = (self.data.physics.p_plasma_dt_mw * 1e6) / (
+ constants.D_T_ENERGY
+ )
+ self.data.physics.fusrat_plasma_dd_total = (
+ self.data.physics.fusrat_plasma_dd_helion
+ + self.data.physics.fusrat_plasma_dd_triton
+ )
+
+ self.data.physics.fusrat_dt_total = (
+ self.data.physics.p_dt_total_mw * 1e6 / (constants.D_T_ENERGY)
+ )
+
+ self.data.physics.fusrat_neutron_production_total = (
+ self.data.physics.fusrat_plasma_dd_helion + self.data.physics.fusrat_dt_total
+ )
+
# Create some derived values and add beam contribution to fusion power
(
self.data.physics.pden_neutron_total_mw,
@@ -955,30 +985,17 @@ def run(self):
0.5e0 * self.data.physics.ind_plasma * self.data.physics.plasma_current**2
)
- # Calculate auxiliary physics related information
- sbar = 1.0e0
(
- self.data.physics.burnup,
- self.data.physics.figmer,
- self.data.physics.fusrat,
- self.data.physics.molflow_plasma_fuelling_required,
- self.data.physics.rndfuel,
self.data.physics.t_alpha_confinement,
self.data.physics.f_t_alpha_energy_confinement,
) = self.phyaux(
- self.data.physics.aspect,
- self.data.physics.nd_plasma_fuel_ions_vol_avg,
- self.data.physics.fusden_total,
- self.data.physics.fusden_alpha_total,
- self.data.physics.plasma_current,
- sbar,
- self.data.physics.nd_plasma_alphas_thermal_vol_avg,
- self.data.physics.t_energy_confinement,
- self.data.physics.vol_plasma,
- self.data.physics.burnup_in,
- self.data.physics.tauratio,
+ fusden_alpha_total=self.data.physics.fusden_alpha_total,
+ nd_plasma_alphas_thermal_vol_avg=self.data.physics.nd_plasma_alphas_thermal_vol_avg,
+ t_energy_confinement=self.data.physics.t_energy_confinement,
)
+ self.fuelling.run()
+
self.data.physics.ntau, self.data.physics.nTtau = (
self.confinement.calculate_double_and_triple_product(
nd_plasma_electrons_vol_avg=self.data.physics.nd_plasma_electrons_vol_avg,
@@ -1481,68 +1498,33 @@ def plasma_composition(self):
# ======================================================================
@staticmethod
- @nb.njit(cache=True)
def phyaux(
- aspect: float,
- nd_plasma_fuel_ions_vol_avg: float,
- fusden_total: float,
fusden_alpha_total: float,
- plasma_current: float,
- sbar: float,
nd_plasma_alphas_thermal_vol_avg: float,
t_energy_confinement: float,
- vol_plasma: float,
- burnup_in: float,
- tauratio: float,
- ) -> tuple[float, float, float, float, float, float, float, float]:
+ ) -> tuple[float, float]:
"""Auxiliary physics quantities
Parameters
----------
- aspect : float
- Plasma aspect ratio.
- nd_plasma_fuel_ions_vol_avg : float
- Fuel ion density (/m3).
- fusden_total : float
- Fusion reaction rate from plasma and beams (/m3/s).
fusden_alpha_total : float
Alpha particle production rate (/m3/s).
- plasma_current : float
- Plasma current (A).
- sbar : float
- Exponent for aspect ratio (normally 1).
nd_plasma_alphas_thermal_vol_avg : float
Alpha ash density (/m3).
t_energy_confinement : float
Global energy confinement time (s).
- vol_plasma : float
- Plasma volume (m3).
- burnup_in: float
- fractional plasma burnup user input
- tauratio: float
- ratio of He and pellet particle confinement times
+
Returns
-------
tuple
A tuple containing:
- - burnup (float): Fractional plasma burnup.
- - figmer (float): Physics figure of merit.
- - fusrat (float): Number of fusion reactions per second.
- - molflow_plasma_fuelling_required (float): Fuelling rate for D-T
- (nucleus-pairs/sec).
- - rndfuel (float): Fuel burnup rate (reactions/s).
- t_alpha_confinement (float): Alpha particle confinement time (s).
- f_t_alpha_energy_confinement (float): Fraction of alpha energy confinement.
This subroutine calculates extra physics related items needed by other
parts of the code.
"""
- figmer = 1e-6 * plasma_current * aspect**sbar
-
- # Fusion reactions per second
- fusrat = fusden_total * vol_plasma
-
# Alpha particle confinement time (s)
# Number of alphas / alpha production rate
# only likely if DD is only active fusion reaction
@@ -1552,41 +1534,9 @@ def phyaux(
else nd_plasma_alphas_thermal_vol_avg / fusden_alpha_total
)
- # Fractional burnup
- # (Consider detailed model in: G. L. Jackson, V. S. Chan, R. D. Stambaugh,
- # Fusion Science and Technology, vol.64, no.1, July 2013, pp.8-12)
- # The ratio of ash to fuel particle confinement times is given by
- # tauratio
- # Possible logic...
- # burnup = fuel ion-pairs burned/m3 / initial fuel ion-pairs/m3;
- # fuel ion-pairs burned/m3 = alpha particles/m3 (for both D-T and
- # D-He3 reactions)
- # initial fuel ion-pairs/m3 = burnt fuel ion-pairs/m3 + unburnt fuel-ion
- # pairs/m3
- # Remember that unburnt fuel-ion pairs/m3 = 0.5 * unburnt fuel-ions/m3
- if burnup_in <= 1.0e-9:
- burnup = (
- nd_plasma_alphas_thermal_vol_avg
- / (nd_plasma_alphas_thermal_vol_avg + 0.5 * nd_plasma_fuel_ions_vol_avg)
- / tauratio
- )
- else:
- burnup = burnup_in
-
- # Fuel burnup rate (reactions/second) (previously Amps)
- rndfuel = fusrat
-
- # Required fuelling rate (fuel ion pairs/second) (previously Amps)
- molflow_plasma_fuelling_required = rndfuel / burnup
-
f_t_alpha_energy_confinement = t_alpha_confinement / t_energy_confinement
return (
- burnup,
- figmer,
- fusrat,
- molflow_plasma_fuelling_required,
- rndfuel,
t_alpha_confinement,
f_t_alpha_energy_confinement,
)
@@ -1865,6 +1815,60 @@ def outplas(self):
self.data.physics.fusrat_total,
"OP ",
)
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "D-T Fusion rate: total (reactions/sec)",
+ "(fusrat_dt_total)",
+ self.data.physics.fusrat_dt_total,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "D-T Fusion rate: plasma (reactions/sec)",
+ "(fusrat_plasma_dt)",
+ self.data.physics.fusrat_plasma_dt,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "D-D -> 3He Fusion rate: plasma (reactions/sec)",
+ "(fusrat_plasma_dd_helion)",
+ self.data.physics.fusrat_plasma_dd_helion,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "D-D -> T Fusion rate: plasma (reactions/sec)",
+ "(fusrat_plasma_dd_triton)",
+ self.data.physics.fusrat_plasma_dd_triton,
+ "OP ",
+ )
+ po.ovarre(
+ self.outfile,
+ "D-D Fusion rate: total (reactions/sec)",
+ "(fusrat_plasma_dd_total)",
+ self.data.physics.fusrat_plasma_dd_total,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "D-3He Fusion rate: total (reactions/sec)",
+ "(fusrat_plasma_dhe3)",
+ self.data.physics.fusrat_plasma_dhe3,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
+ po.ovarre(
+ self.outfile,
+ "Neutron production rate: total (particles/sec)",
+ "(fusrat_neutron_production_total)",
+ self.data.physics.fusrat_neutron_production_total,
+ "OP ",
+ )
+ po.oblnkl(self.outfile)
po.ovarre(
self.outfile,
"Fusion rate density: total (reactions/m³/sec)",
@@ -2708,56 +2712,7 @@ def outplas(self):
self.plasma_bootstrap_current.output()
self.dia_current.output()
- po.oheadr(self.outfile, "Plasma Fuelling")
- po.ovarre(
- self.outfile,
- "Ratio of He and pellet particle confinement times",
- "(tauratio)",
- self.data.physics.tauratio,
- )
- po.ovarre(
- self.outfile,
- "Fuelling rate (nucleus-pairs/s)",
- "(molflow_plasma_fuelling_required)",
- self.data.physics.molflow_plasma_fuelling_required,
- "OP ",
- )
- po.ovarre(
- self.outfile,
- "Fuel burn-up rate (reactions/s)",
- "(rndfuel)",
- self.data.physics.rndfuel,
- "OP ",
- )
- po.ovarre(
- self.outfile,
- "Burn-up fraction",
- "(burnup)",
- self.data.physics.burnup,
- "OP ",
- )
-
- if 78 in self.data.numerics.icc:
- po.osubhd(self.outfile, "Reinke Criterion :")
- po.ovarre(
- self.outfile,
- "index of impurity to be iterated for divertor detachment",
- "(impvardiv)",
- self.data.reinke.impvardiv,
- )
- po.ovarre(
- self.outfile,
- "Minimum Impurity fraction from Reinke",
- "(fzmin)",
- self.data.reinke.fzmin,
- "OP ",
- )
- po.ovarre(
- self.outfile,
- "Actual Impurity fraction",
- "(fzactual)",
- self.data.reinke.fzactual,
- )
+ self.fuelling.output_fuelling_info()
def output_temperature_density_profile_info(self) -> None:
"""Output information about plasma temperature and density profiles."""
diff --git a/process/models/stellarator/stellarator.py b/process/models/stellarator/stellarator.py
index e75fc106c8..aa56547567 100644
--- a/process/models/stellarator/stellarator.py
+++ b/process/models/stellarator/stellarator.py
@@ -2376,27 +2376,20 @@ def st_phys(self, output):
# Calculate auxiliary physics related information
# for the rest of the code
- sbar = 1.0e0
(
- self.data.physics.burnup,
- self.data.physics.figmer,
- _fusrat,
- self.data.physics.molflow_plasma_fuelling_required,
- self.data.physics.rndfuel,
self.data.physics.t_alpha_confinement,
self.data.physics.f_t_alpha_energy_confinement,
) = self.physics.phyaux(
- self.data.physics.aspect,
- self.data.physics.nd_plasma_fuel_ions_vol_avg,
- self.data.physics.fusden_total,
self.data.physics.fusden_alpha_total,
- self.data.physics.plasma_current,
- sbar,
self.data.physics.nd_plasma_alphas_thermal_vol_avg,
self.data.physics.t_energy_confinement,
- self.data.physics.vol_plasma,
- self.data.physics.burnup_in,
- self.data.physics.tauratio,
+ )
+
+ self.data.physics.f_plasma_fuel_burnup = self.physics.fuelling.calculate_fuel_burnup_fraction( # noqa: E501
+ fusrat_total=self.data.physics.fusrat_total,
+ molflow_plasma_fuelling_vv_injected=self.data.physics.molflow_plasma_fuelling_vv_injected,
+ molflow_beam_deuterium_vv_injected=self.data.physics.molflow_beam_deuterium_vv_injected,
+ molflow_beam_tritium_vv_injected=self.data.physics.molflow_beam_tritium_vv_injected,
)
# Calculate the neoclassical sanity check with PROCESS parameters
diff --git a/process/models/vacuum.py b/process/models/vacuum.py
index b305bd93ea..ea1b929d27 100644
--- a/process/models/vacuum.py
+++ b/process/models/vacuum.py
@@ -49,7 +49,7 @@ def run(self, output: bool = False):
# MDK Check this!!
gasld = (
2.0e0
- * self.data.physics.molflow_plasma_fuelling_required
+ * self.data.physics.molflow_plasma_fuelling_vv_injected
* self.data.physics.m_fuel_amu
* constants.UMASS
)
@@ -112,7 +112,7 @@ def vacuum_simple(self, output) -> float:
# One ITER torus cryopump has a throughput of 50 Pa m3/s = 1.2155e+22 molecules/s
# Issue #304
n_iter_vacuum_pumps = (
- self.data.physics.molflow_plasma_fuelling_required
+ self.data.physics.molflow_plasma_fuelling_vv_injected
/ self.data.vacuum.molflow_vac_pumps
)
@@ -161,8 +161,8 @@ def _vacuum_simple_output(self, n_iter_vacuum_pumps, npumpdown, npump):
process_output.ovarre(
self.outfile,
"Plasma fuelling rate (nucleus-pairs/s)",
- "(molflow_plasma_fuelling_required)",
- self.data.physics.molflow_plasma_fuelling_required,
+ "(molflow_plasma_fuelling_vv_injected)",
+ self.data.physics.molflow_plasma_fuelling_vv_injected,
"OP ",
)
diff --git a/tests/regression/input_files/large_tokamak_eval.IN.DAT b/tests/regression/input_files/large_tokamak_eval.IN.DAT
index efc4c37dd2..f630942ff4 100644
--- a/tests/regression/input_files/large_tokamak_eval.IN.DAT
+++ b/tests/regression/input_files/large_tokamak_eval.IN.DAT
@@ -3,11 +3,19 @@ i_process_run_mode = -2
*---------------Constraint Equations---------------*
* Define number of equality constraints
-n_equality_constraints = 2
+n_equality_constraints = 6
* Equalities
icc = 1 * Beta
icc = 2 * Global power balance
+* Tritium particle balance
+icc = 93
+* Deuterium particle balance
+icc = 94
+* Alpha particle balance
+icc = 96
+* Fuelling composition consistency
+icc = 97
* Inequalities
icc = 5 * Density upper limit
@@ -40,6 +48,26 @@ ixc = 4 * temp_plasma_electron_vol_avg_kev
boundu(4) = 100.0
ixc = 6 * nd_plasma_electrons_vol_avg
+* Particles recycled at LCFS
+ixc = 178
+f_plasma_particles_lcfs_recycled = 0.89
+
+* Injected VV fuelling rate
+ixc = 180
+molflow_plasma_fuelling_vv_injected = 4.9992093e21
+
+* Deuterium fuelling fraction
+ixc = 181
+f_molflow_plasma_fuelling_deuterium = 0.50092526
+
+* Tritium fuelling fraction
+ixc = 182
+f_molflow_plasma_fuelling_tritium = 0.49907474
+
+
+
+
+
*---------------Cs Fatigue Variables---------------*
@@ -310,6 +338,9 @@ temp_plasma_electron_vol_avg_kev = 12.221383528378944 * volume averaged el
triang = 0.5 * plasma separatrix triangularity (calculated if `i_plasma_geometry = 1; 3-5 or 7`)
i_ind_plasma_internal_norm = 1 * Normalised plasma internal induction selection switch (0 = user input)
+eta_plasma_fuelling = 0.7
+
+
*----------------------Power-----------------------*
diff --git a/tests/regression/input_files/large_tokamak_nof.IN.DAT b/tests/regression/input_files/large_tokamak_nof.IN.DAT
index 828a3a6e34..4d61773ef7 100644
--- a/tests/regression/input_files/large_tokamak_nof.IN.DAT
+++ b/tests/regression/input_files/large_tokamak_nof.IN.DAT
@@ -19,7 +19,7 @@ epsvmc = 1e-7
* Number of equality constraints
* (the first n_equality_constraints icc=... statements are equality constraints)
-n_equality_constraints = 3
+n_equality_constraints = 7
* Maximum number of solver iterations
maxcal = 100
@@ -41,6 +41,18 @@ icc = 2
*--------------------------*
icc = 11
+* Tritium particle balance
+icc = 93
+
+* Deuterium particle balance
+icc = 94
+
+* Alpha particle balance
+icc = 96
+
+* Fuelling composition consistency
+icc = 97
+
* Constraint Equations - Limit Equations *
******************************************
@@ -178,6 +190,30 @@ t_burn_min = 7200.0
* Iteration Variables *
***********************
+* Particle recycling fraction
+ixc = 178
+f_plasma_particles_lcfs_recycled = 0.9
+
+* Plasma fuelling efficiecy
+ixc = 179
+eta_plasma_fuelling = 0.7
+
+* Injected VV fuelling rate
+ixc = 180
+molflow_plasma_fuelling_vv_injected = 5e21
+boundl(180) = 1e20
+
+* Deuterium fuelling fraction
+ixc = 181
+f_molflow_plasma_fuelling_deuterium = 0.5
+boundl(181) = 0.4
+
+* Tritium fuelling fraction
+ixc = 182
+f_molflow_plasma_fuelling_tritium = 0.5
+boundl(182) = 0.4
+
+
* b_plasma_toroidal_on_axis [T]
ixc = 2
b_plasma_toroidal_on_axis = 5.7
diff --git a/tests/regression/input_files/st_regression.IN.DAT b/tests/regression/input_files/st_regression.IN.DAT
index 2a346db5ac..f8f90b3f2a 100644
--- a/tests/regression/input_files/st_regression.IN.DAT
+++ b/tests/regression/input_files/st_regression.IN.DAT
@@ -55,10 +55,12 @@ i_figure_merit = -5
* DESCRIPTION: Switch for Figure-of-Merit
* JUSTIFICATION: Selected optimisation
-n_equality_constraints = 3
+n_equality_constraints = 7
* DESCRIPTION: Number of equality constraints (the first n_equality_constraints icc = ... statements are considered equality)
* JUSTIFICATION: 3 equality (consistency) equations
+
+
*________________________________________________________________________*
*------------------------------ *Key Variables* -------------------------*
*‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾*
@@ -85,6 +87,18 @@ icc = 11
* JUSTIFICATION: Consistency equations should always be on
* VARIABLES: rmajor, Rest calculated in-situ
+* Tritium particle balance
+icc = 93
+
+* Deuterium particle balance
+icc = 94
+
+* Alpha particle balance
+icc = 96
+
+* Fuelling composition consistency
+icc = 97
+
*________________________________________________________________________*
*------------------------------- *Plasma* -------------------------------*
*‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾*
@@ -555,6 +569,29 @@ f_sync_reflect = 0.6
* allowance for radiation. This is not recommended for power plant models.
* JUSTIFICATION: Turned off, assuming default = 1
+* Particle recycling fraction
+ixc = 178
+f_plasma_particles_lcfs_recycled = 0.9
+
+* Plasma fuelling efficiecy
+ixc = 179
+eta_plasma_fuelling = 0.7
+
+* Injected VV fuelling rate
+ixc = 180
+molflow_plasma_fuelling_vv_injected = 5e21
+boundl(180) = 1e20
+
+* Deuterium fuelling fraction
+ixc = 181
+f_molflow_plasma_fuelling_deuterium = 0.5
+boundl(181) = 0.4
+
+* Tritium fuelling fraction
+ixc = 182
+f_molflow_plasma_fuelling_tritium = 0.5
+boundl(182) = 0.4
+
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
icc = 17
@@ -588,10 +625,6 @@ f_p_plasma_separatrix_rad_max = 0.64
* DESCRIPTION: Fraction of alpha power deposited to plasma
* JUSTIFICATION: Using default = 0.95
-*burnup_in =
-* DESCRIPTION: User input plasma fuel burnup fraction
-* JUSTIFICATION: Turned off, allow to be calculated in-situ
-
ixc = 135
f_nd_impurity_electrons(13) = 0.0005
*boundl(135) = 0.000495
diff --git a/tests/unit/models/physics/test_physics.py b/tests/unit/models/physics/test_physics.py
index 9e3aa6f47b..15c687ace1 100644
--- a/tests/unit/models/physics/test_physics.py
+++ b/tests/unit/models/physics/test_physics.py
@@ -1837,46 +1837,12 @@ def test_vscalc(voltsecondreqparam):
class PhyauxParam(NamedTuple):
- tauratio: Any = None
-
- burnup_in: Any = None
-
- aspect: Any = None
-
- nd_plasma_electrons_vol_avg: Any = None
-
- te: Any = None
-
- nd_plasma_fuel_ions_vol_avg: Any = None
-
nd_plasma_alphas_thermal_vol_avg: Any = None
- fusden_total: Any = None
-
fusden_alpha_total: Any = None
- plasma_current: Any = None
-
- sbar: Any = None
-
t_energy_confinement: Any = None
- vol_plasma: Any = None
-
- expected_burnup: Any = None
-
- expected_ntau: Any = None
-
- expected_nTtau: Any = None
-
- expected_figmer: Any = None
-
- expected_fusrat: Any = None
-
- expected_molflow_plasma_fuelling_required: Any = None
-
- expected_rndfuel: Any = None
-
expected_t_alpha_confinement: Any = None
@@ -1884,46 +1850,20 @@ class PhyauxParam(NamedTuple):
"phyauxparam",
[
PhyauxParam(
- tauratio=1,
- burnup_in=0,
- aspect=3,
- nd_plasma_fuel_ions_vol_avg=5.858890125e19,
- nd_plasma_alphas_thermal_vol_avg=7.5e18,
- fusden_total=1.9852091609123786e17,
+ nd_plasma_alphas_thermal_vol_avg=7.499815489237494e18,
fusden_alpha_total=1.973996644759543e17,
- plasma_current=18398455.678867526,
- sbar=1,
t_energy_confinement=3.401323521525641,
- vol_plasma=1888.1711539956691,
- expected_burnup=0.20383508579699033,
- expected_figmer=55.195367036602576,
- expected_fusrat=3.7484146722826997e20,
- expected_molflow_plasma_fuelling_required=1.838944781084418e21,
- expected_rndfuel=3.7484146722826997e20,
- expected_t_alpha_confinement=37.993985551650177,
+ expected_t_alpha_confinement=37.993050845084205,
),
PhyauxParam(
- tauratio=1,
- burnup_in=0,
- aspect=3,
- nd_plasma_fuel_ions_vol_avg=5.8576156204039725e19,
- nd_plasma_alphas_thermal_vol_avg=7.5e18,
- fusden_total=1.9843269653375773e17,
+ nd_plasma_alphas_thermal_vol_avg=7.499880919696304e18,
fusden_alpha_total=1.9731194318497056e17,
- plasma_current=18398455.678867526,
- sbar=1,
t_energy_confinement=3.402116961408892,
- vol_plasma=1888.1711539956691,
- expected_burnup=0.20387039462081086,
- expected_figmer=55.195367036602576,
- expected_fusrat=3.7467489360461772e20,
- expected_molflow_plasma_fuelling_required=1.8378092331723546e21,
- expected_rndfuel=3.7467489360461772e20,
- expected_t_alpha_confinement=38.010876984618747,
+ expected_t_alpha_confinement=38.01027347171541,
),
],
)
-def test_phyaux(phyauxparam, monkeypatch, physics):
+def test_phyaux(phyauxparam, physics):
"""
Automatically generated Unit Test for phyaux.
@@ -1937,44 +1877,15 @@ def test_phyaux(phyauxparam, monkeypatch, physics):
:type monkeypatch: _pytest.monkeypatch.monkeypatch
"""
- monkeypatch.setattr(physics.data.physics, "tauratio", phyauxparam.tauratio)
-
- monkeypatch.setattr(physics.data.physics, "burnup_in", phyauxparam.burnup_in)
-
(
- burnup,
- figmer,
- fusrat,
- molflow_plasma_fuelling_required,
- rndfuel,
t_alpha_confinement,
_,
) = physics.phyaux(
- aspect=phyauxparam.aspect,
- nd_plasma_fuel_ions_vol_avg=phyauxparam.nd_plasma_fuel_ions_vol_avg,
nd_plasma_alphas_thermal_vol_avg=phyauxparam.nd_plasma_alphas_thermal_vol_avg,
- fusden_total=phyauxparam.fusden_total,
fusden_alpha_total=phyauxparam.fusden_alpha_total,
- plasma_current=phyauxparam.plasma_current,
- sbar=phyauxparam.sbar,
t_energy_confinement=phyauxparam.t_energy_confinement,
- vol_plasma=phyauxparam.vol_plasma,
- burnup_in=phyauxparam.burnup_in,
- tauratio=phyauxparam.tauratio,
)
- assert burnup == pytest.approx(phyauxparam.expected_burnup)
-
- assert figmer == pytest.approx(phyauxparam.expected_figmer)
-
- assert fusrat == pytest.approx(phyauxparam.expected_fusrat)
-
- assert molflow_plasma_fuelling_required == pytest.approx(
- phyauxparam.expected_molflow_plasma_fuelling_required
- )
-
- assert rndfuel == pytest.approx(phyauxparam.expected_rndfuel)
-
assert t_alpha_confinement == pytest.approx(phyauxparam.expected_t_alpha_confinement)
diff --git a/tests/unit/models/test_costs_1990.py b/tests/unit/models/test_costs_1990.py
index 6d442bc2c6..9095ef4cf5 100644
--- a/tests/unit/models/test_costs_1990.py
+++ b/tests/unit/models/test_costs_1990.py
@@ -151,7 +151,7 @@ def test_acc2272(monkeypatch, costs):
:param monkeypatch: Mock fixture
:type monkeypatch: object
"""
- monkeypatch.setattr(costs.data.physics, "rndfuel", 7.158e20)
+ monkeypatch.setattr(costs.data.physics, "fusrat_total", 7.158e20)
monkeypatch.setattr(costs.data.physics, "m_fuel_amu", 2.5)
monkeypatch.setattr(costs.data.costs, "fkind", 1)
monkeypatch.setattr(costs.data.costs, "c2271", 0)
@@ -4031,7 +4031,9 @@ class Acc2272Param(NamedTuple):
edrive: Any = None
- rndfuel: Any = None
+ wtgpd: Any = None
+
+ fusrat_total: Any = None
m_fuel_amu: Any = None
@@ -4054,7 +4056,7 @@ class Acc2272Param(NamedTuple):
ife=0,
gain=0,
edrive=5000000,
- rndfuel=7.0799717510383796e20,
+ fusrat_total=7.0799717510383796e20,
m_fuel_amu=2.5,
c227=0,
c22=0,
@@ -4068,7 +4070,7 @@ class Acc2272Param(NamedTuple):
ife=0,
gain=0,
edrive=5000000,
- rndfuel=7.0777619721108953e20,
+ fusrat_total=7.0777619721108953e20,
m_fuel_amu=2.5,
c227=284.96904049038437,
c22=3474.7391916096453,
@@ -4103,7 +4105,7 @@ def test_acc2272_rut(acc2272param, monkeypatch, costs):
monkeypatch.setattr(costs.data.ife, "edrive", acc2272param.edrive)
- monkeypatch.setattr(costs.data.physics, "rndfuel", acc2272param.rndfuel)
+ monkeypatch.setattr(costs.data.physics, "fusrat_total", acc2272param.fusrat_total)
monkeypatch.setattr(costs.data.physics, "m_fuel_amu", acc2272param.m_fuel_amu)
diff --git a/tests/unit/models/test_vacuum.py b/tests/unit/models/test_vacuum.py
index f1913200a2..db1bb461b0 100644
--- a/tests/unit/models/test_vacuum.py
+++ b/tests/unit/models/test_vacuum.py
@@ -40,7 +40,7 @@ def test_simple_model(monkeypatch, vacuum):
"""
monkeypatch.setattr(
vacuum.data.physics,
- "molflow_plasma_fuelling_required",
+ "molflow_plasma_fuelling_vv_injected",
7.5745668997694112e22,
)
monkeypatch.setattr(vacuum.data.physics, "a_plasma_surface", 1500.3146527709359)