diff --git a/process/core/solver/constraints.py b/process/core/solver/constraints.py index 5187004e2d..c1d104e89b 100644 --- a/process/core/solver/constraints.py +++ b/process/core/solver/constraints.py @@ -11,7 +11,11 @@ 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.physics import BetaComponentLimits, PlasmaBeta +from process.models.physics.physics import ( + BetaComponentLimits, + PlasmaBeta, + PlasmaIgnitionModel, +) from process.models.tfcoil.base import TFConductorModel ConstraintSymbolType = Literal["=", ">=", "<="] @@ -270,7 +274,10 @@ def constraint_equation_2(constraint_registration, data): pnumerator = pscaling # if plasma not ignited include injected power - if data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): pdenom = ( data.physics.f_p_alpha_plasma_deposited * data.physics.pden_alpha_total_mw + data.physics.pden_non_alpha_charged_mw @@ -303,7 +310,10 @@ def constraint_equation_3(constraint_registration, data): vol_plasma: plasma volume (m3) """ # No assume plasma ignition: - if data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): return eq( ( data.physics.pden_ion_transport_loss_mw @@ -363,7 +373,10 @@ def constraint_equation_4(constraint_registration, data): pnumerator = pscaling # if plasma not ignited include injected power - if data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): pdenom = ( data.physics.f_p_alpha_plasma_deposited * data.physics.f_pden_alpha_electron_mw @@ -453,7 +466,7 @@ def constraint_equation_7(constraint_registration, data): nd_beam_ions_out: hot beam ion density from calculation (/m³) nd_beam_ions: hot beam ion density, variable (/m³) """ - if data.physics.i_plasma_ignited == 1: + if PlasmaIgnitionModel(data.physics.i_plasma_ignited) == PlasmaIgnitionModel.IGNITED: raise ProcessValueError("Do not use constraint equation 7 if i_plasma_ignited=1") return eq( @@ -808,7 +821,10 @@ def constraint_equation_28(constraint_registration, data): during plasma start-up, and is excluded from all steady-state power balance calculations. """ - if data.physics.i_plasma_ignited != 0: + if ( + PlasmaIgnitionModel(data.physics.i_plasma_ignited) + != PlasmaIgnitionModel.NON_IGNITED + ): raise ProcessValueError("Do not use constraint 28 if i_plasma_ignited=1") return geq( @@ -1739,7 +1755,10 @@ def constraint_equation_91(constraint_registration, data): te0_ecrh_achievable: Max. achievable electron temperature at ignition point """ # Achievable ECRH te needs to be larger than needed te for igntion - if data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): value = ( data.stellarator.powerht_constraint + data.current_drive.p_hcd_primary_extra_heat_mw diff --git a/process/data_structure/physics_variables.py b/process/data_structure/physics_variables.py index 52ee70a627..0cafda166e 100644 --- a/process/data_structure/physics_variables.py +++ b/process/data_structure/physics_variables.py @@ -13,6 +13,13 @@ import numpy as np +class PlasmaIgnitionModel(IntEnum): + """Enum for plasma ignition models.""" + + NON_IGNITED = 0 + IGNITED = 1 + + class DivertorNumberModels(IntEnum): """Enum for divertor number models. `i_single_null` is the index for this enum.""" diff --git a/process/models/physics/confinement_time.py b/process/models/physics/confinement_time.py index 78d6eca7ad..87bd9ff4ad 100644 --- a/process/models/physics/confinement_time.py +++ b/process/models/physics/confinement_time.py @@ -14,6 +14,7 @@ ConfinementMode, ConfinementRadiationLossModel, ConfinementTimeModel, + PlasmaIgnitionModel, ) from process.models.physics.plasma_geometry import PlasmaGeom @@ -143,7 +144,7 @@ def calculate_confinement_time( ) # If the device is not ignited, add the injected auxiliary power - if i_plasma_ignited == 0: + if PlasmaIgnitionModel(i_plasma_ignited) == PlasmaIgnitionModel.NON_IGNITED: p_plasma_loss_mw += p_hcd_injected_total_mw # Include the radiation as a loss term based on radiation model @@ -1101,7 +1102,10 @@ def fhz(hfact: float) -> float: # Take into account whether injected power is included in tau_e calculation # (i.e. whether device is ignited) - if self.data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): fhz_value -= ( self.data.current_drive.p_hcd_injected_total_mw / self.data.physics.vol_plasma @@ -1128,7 +1132,10 @@ def output_confinement_time_info(self): """ po.oheadr(self.outfile, "Plasma Energy Confinement") - if self.data.physics.i_plasma_ignited == 1: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.IGNITED + ): po.ocmmnt( self.outfile, "Device is assumed to be ignited for the calculation of confinement " diff --git a/process/models/physics/current_drive.py b/process/models/physics/current_drive.py index 8ff08d57ac..9d63db895a 100644 --- a/process/models/physics/current_drive.py +++ b/process/models/physics/current_drive.py @@ -12,6 +12,7 @@ ) from process.core.exceptions import ProcessError, ProcessValueError from process.core.model import Model +from process.data_structure.physics_variables import PlasmaIgnitionModel from process.models.physics.plasma_profiles import PlasmaProfile logger = logging.getLogger(__name__) @@ -2290,7 +2291,10 @@ def current_drive(self): ) # Reset injected power to zero for ignited plasma (fudge) - if self.data.physics.i_plasma_ignited == 1: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.IGNITED + ): self.data.heat_transport.p_hcd_electric_total_mw = 0.0e0 # Ratio of fusion to input (injection+ohmic) power @@ -2394,7 +2398,10 @@ def output(self): "(i_plasma_ignited)", self.data.physics.i_plasma_ignited, ) - if self.data.physics.i_plasma_ignited == 1: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.IGNITED + ): po.ocmmnt( self.outfile, "Ignited plasma; injected power only used for start-up phase", diff --git a/process/models/physics/physics.py b/process/models/physics/physics.py index 17e9a0bec7..e3fd405c3d 100644 --- a/process/models/physics/physics.py +++ b/process/models/physics/physics.py @@ -18,6 +18,7 @@ from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure.impurity_radiation_variables import N_IMPURITIES +from process.data_structure.physics_variables import PlasmaIgnitionModel from process.models.physics import impurity_radiation from process.models.physics.profiles import ( DensityProfilePedestalType, @@ -601,7 +602,8 @@ def run(self): # Calculate neutral beam slowing down effects # If ignited, then ignore beam fusion effects if (self.data.current_drive.c_beam_total != 0.0e0) and ( # noqa: RUF069 - self.data.physics.i_plasma_ignited == 0 + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED ): ( self.data.physics.beta_beam, @@ -773,7 +775,8 @@ def run(self): # which is assumed to be absorbed by the first wall pinj = ( self.data.current_drive.p_hcd_injected_total_mw - if self.data.physics.i_plasma_ignited == 0 + if PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED else 0.0 ) @@ -1176,7 +1179,10 @@ def plasma_composition(self): # Beam hot ion component # If ignited, prevent beam fusion effects - if self.data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): self.data.physics.nd_beam_ions = ( self.data.physics.nd_plasma_electrons_vol_avg * self.data.physics.f_nd_beam_electron @@ -2295,7 +2301,10 @@ def outplas(self): self.data.current_drive.p_hcd_injected_electrons_mw, "OP ", ) - if self.data.physics.i_plasma_ignited == 1: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.IGNITED + ): po.ocmmnt(self.outfile, " (Injected power only used for start-up phase)") self.exhaust.output() diff --git a/process/models/stellarator/heating.py b/process/models/stellarator/heating.py index 302c63fd6f..fd4bd43aab 100644 --- a/process/models/stellarator/heating.py +++ b/process/models/stellarator/heating.py @@ -3,6 +3,7 @@ from process.core import process_output as po from process.core.exceptions import ProcessValueError from process.core.model import DataStructure +from process.data_structure.physics_variables import PlasmaIgnitionModel logger = logging.getLogger(__name__) @@ -142,7 +143,7 @@ def output(stellarator, data: DataStructure, f_p_beam_injected_ions=None): elif data.stellarator.isthtr == 3: po.ocmmnt(stellarator.outfile, "Neutral Beam Injection Heating") - if data.physics.i_plasma_ignited == 1: + if PlasmaIgnitionModel(data.physics.i_plasma_ignited) == PlasmaIgnitionModel.IGNITED: po.ocmmnt( stellarator.outfile, "Ignited plasma; injected power only used for start-up phase", diff --git a/process/models/stellarator/stellarator.py b/process/models/stellarator/stellarator.py index 0a0b17b309..e1ca8c8685 100644 --- a/process/models/stellarator/stellarator.py +++ b/process/models/stellarator/stellarator.py @@ -13,6 +13,7 @@ from process.core.coolprop_interface import FluidProperties from process.core.exceptions import ProcessValueError from process.core.model import Model +from process.data_structure.physics_variables import PlasmaIgnitionModel from process.models.engineering.pumping import CoolantType from process.models.physics.physics import Physics, rether from process.models.power import PumpingPowerModelTypes @@ -1975,7 +1976,8 @@ def st_phys(self, output): # If ignited, then ignore beam fusion effects if (self.data.current_drive.p_hcd_beam_injected_total_mw != 0.0e0) and ( # noqa: RUF069 - self.data.physics.i_plasma_ignited == 0 + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED ): ( self.data.physics.beta_beam, @@ -2152,7 +2154,10 @@ def st_phys(self, output): 0.00001e0, powht ) # To avoid negative heating power. This line is VERY important - if self.data.physics.i_plasma_ignited == 0: + if ( + PlasmaIgnitionModel(self.data.physics.i_plasma_ignited) + == PlasmaIgnitionModel.NON_IGNITED + ): # if not ignited add the auxiliary power powht += self.data.current_drive.p_hcd_injected_total_mw diff --git a/tests/unit/models/physics/test_physics.py b/tests/unit/models/physics/test_physics.py index 9d9351e200..63613de811 100644 --- a/tests/unit/models/physics/test_physics.py +++ b/tests/unit/models/physics/test_physics.py @@ -6,6 +6,7 @@ import pytest from process.core import constants +from process.data_structure.physics_variables import PlasmaIgnitionModel from process.models.physics.impurity_radiation import initialise_imprad from process.models.physics.physics import ( DetailedPhysics, @@ -1373,7 +1374,7 @@ class PlasmaCompositionParam(NamedTuple): 183.84999999999999, ]), alphat=1.45, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, f_alpha_electron=0, m_fuel_amu=0, f_plasma_fuel_tritium=0.5, @@ -1479,7 +1480,7 @@ class PlasmaCompositionParam(NamedTuple): order="F", ).transpose(), alphat=1.45, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, f_alpha_electron=0.6845930883190634, m_fuel_amu=2.5, f_plasma_fuel_tritium=0.5, @@ -2268,7 +2269,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=32, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2320,7 +2321,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=33, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2372,7 +2373,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=34, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2424,7 +2425,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=35, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2476,7 +2477,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=36, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2528,7 +2529,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=37, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2580,7 +2581,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=38, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2632,7 +2633,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=39, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2684,7 +2685,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=40, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2736,7 +2737,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=41, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2788,7 +2789,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=42, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2840,7 +2841,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=43, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2892,7 +2893,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=44, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2944,7 +2945,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=45, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -2996,7 +2997,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=46, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3, @@ -3048,7 +3049,7 @@ class ConfinementTimeParam(NamedTuple): p_plasma_ohmic_mw=0.63634001890069991, f_p_alpha_plasma_deposited=0.94999999999999996, i_confinement_time=47, - i_plasma_ignited=0, + i_plasma_ignited=PlasmaIgnitionModel.NON_IGNITED, m_fuel_amu=2.5, p_alpha_total_mw=319.03020327154269, aspect=3,