From 856bf87ddef68833f0c10bc53d6b709ef7a734bd Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Jun 2026 15:38:12 +0100 Subject: [PATCH 1/5] Add CoolantType enum and refactor coolant type usage across models --- process/models/blankets/blanket_library.py | 27 +++++++++++------ process/models/blankets/hcpb.py | 5 ++-- process/models/engineering/pumping.py | 9 ++++++ process/models/stellarator/stellarator.py | 5 ++-- .../models/blankets/test_blanket_library.py | 5 ++-- tests/unit/models/blankets/test_ccfe_hcpb.py | 5 ++-- tests/unit/models/test_costs_1990.py | 29 ++++++++++++++----- 7 files changed, 60 insertions(+), 25 deletions(-) diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index 8975142f9e..f05eb8b4ff 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -20,6 +20,7 @@ eshellvol, ) from process.models.engineering.pumping import ( + CoolantType, calculate_reynolds_number, darcy_friction_haaland, ) @@ -696,14 +697,14 @@ def primary_coolant_properties(self, output: bool): # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants if ( self.data.fwbs.i_fw_coolant_type == "Helium" - and self.data.fwbs.i_blkt_coolant_type == 2 + and self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS ) if ( self.data.fwbs.i_fw_coolant_type == "Water" - and self.data.fwbs.i_blkt_coolant_type == 1 + and self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS @@ -756,7 +757,9 @@ def primary_coolant_properties(self, output: bool): + self.data.fwbs.temp_blkt_coolant_out ) * 0.5 bb_fluid_properties = FluidProperties.of( - "Helium" if self.data.fwbs.i_blkt_coolant_type == 1 else "Water", + "Helium" + if self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM + else "Water", temperature=mid_temp_bl, pressure=self.data.fwbs.pres_blkt_coolant, ) @@ -855,11 +858,11 @@ def primary_coolant_properties(self, output: bool): ): po.osubhd(self.outfile, "Breeding Blanket :") - if self.data.fwbs.i_blkt_coolant_type == 1: + if self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM: po.ocmmnt( self.outfile, "Coolant type (i_blkt_coolant_type=1), Helium" ) - if self.data.fwbs.i_blkt_coolant_type == 2: + if self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER: po.ocmmnt( self.outfile, "Coolant type (i_blkt_coolant_type=2), Water" ) @@ -2142,14 +2145,14 @@ def thermo_hydraulic_model(self, output: bool): # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants if ( self.data.fwbs.i_fw_coolant_type == "Helium" - and self.data.fwbs.i_blkt_coolant_type == 2 + and self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS ) if ( self.data.fwbs.i_fw_coolant_type == "Water" - and self.data.fwbs.i_blkt_coolant_type == 1 + and self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS @@ -2485,7 +2488,9 @@ def thermo_hydraulic_model(self, output: bool): dpres_coolant=deltap_blkt, mflow_coolant_total=self.data.blanket.mflow_blkt_coolant_total, primary_coolant_switch=( - "Helium" if self.data.fwbs.i_blkt_coolant_type == 1 else "Water" + "Helium" + if self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM + else "Water" ), den_coolant=self.data.fwbs.den_blkt_coolant, label="Blanket", @@ -3356,7 +3361,11 @@ def coolant_pumping_power( pres_coolant_pump_outlet = pres_coolant_pump_inlet + dpres_coolant # Adiabatic index for helium or water - gamma = (5 / 3) if self.data.fwbs.i_blkt_coolant_type == 1 else (4 / 3) + gamma = ( + (5 / 3) + if self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM + else (4 / 3) + ) # If calculating for primary coolant if i_liquid_breeder == 1: diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index 774cb18a4d..81d78b1521 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -13,6 +13,7 @@ calculate_pipe_bend_radius, pumping_powers_as_fractions, ) +from process.models.engineering.pumping import CoolantType from process.models.power import PumpingPowerModelTypes from process.models.tfcoil.base import TFConductorModel @@ -36,7 +37,7 @@ def output(self): def run(self, output: bool = False): # Coolant type - self.data.fwbs.i_blkt_coolant_type = 1 + self.data.fwbs.i_blkt_coolant_type = CoolantType.HELIUM # Note that the first wall coolant is now input separately. # Calculate blanket, shield, vacuum vessel and cryostat volumes @@ -775,7 +776,7 @@ def powerflow_calc(self, output: bool): # If we have chosen pressurised water as the blanket coolant, set the # coolant outlet temperature as 20 deg C below the boiling point - if self.data.fwbs.i_blkt_coolant_type == 2: + if self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER: outlet_saturated_fluid_properties = FluidProperties.of( "Water", pressure=self.data.fwbs.pres_blkt_coolant * 1.0e6, diff --git a/process/models/engineering/pumping.py b/process/models/engineering/pumping.py index 8afca58ee8..9773eb5ae1 100644 --- a/process/models/engineering/pumping.py +++ b/process/models/engineering/pumping.py @@ -1,9 +1,18 @@ """Engineering models for pumping system analysis.""" import logging +from enum import IntEnum import numpy as np + +class CoolantType(IntEnum): + """Enum for coolant types.""" + + HELIUM = 1 + WATER = 2 + + logger = logging.getLogger(__name__) diff --git a/process/models/stellarator/stellarator.py b/process/models/stellarator/stellarator.py index a35695a1e7..a15a6285d7 100644 --- a/process/models/stellarator/stellarator.py +++ b/process/models/stellarator/stellarator.py @@ -17,6 +17,7 @@ global_variables, numerics, ) +from process.models.engineering.pumping import CoolantType from process.models.physics.physics import Physics, rether from process.models.power import PumpingPowerModelTypes from process.models.stellarator.build import st_build @@ -786,7 +787,7 @@ def st_fwbs(self, output: bool): # If we have chosen pressurised water as the coolant, set the # coolant outlet temperature as 20 deg C below the boiling point - if self.data.fwbs.i_blkt_coolant_type == 2: + if self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER: if self.data.fwbs.irefprop: self.data.fwbs.temp_blkt_coolant_out = ( FluidProperties.of( @@ -1248,7 +1249,7 @@ def st_fwbs(self, output: bool): # structures is used (see comment above) if (self.data.fwbs.blktmodel > 0) or ( - self.data.fwbs.i_blkt_coolant_type == 2 + self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER ): # pressurised water coolant self.data.fwbs.m_fw_blkt_div_coolant_total = coolvol * 806.719e0 else: # gaseous helium coolant diff --git a/tests/unit/models/blankets/test_blanket_library.py b/tests/unit/models/blankets/test_blanket_library.py index 1afe7e16d7..d5c9c49c34 100644 --- a/tests/unit/models/blankets/test_blanket_library.py +++ b/tests/unit/models/blankets/test_blanket_library.py @@ -4,6 +4,7 @@ import pytest from process.models.blankets.blanket_library import InboardBlanket +from process.models.engineering.pumping import CoolantType @pytest.fixture @@ -81,7 +82,7 @@ class PrimaryCoolantPropertiesParam(NamedTuple): den_fw_coolant=0, cp_fw=0, cv_fw=0, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, temp_blkt_coolant_in=573, temp_blkt_coolant_out=773, pres_blkt_coolant=8000000, @@ -109,7 +110,7 @@ class PrimaryCoolantPropertiesParam(NamedTuple): den_fw_coolant=5.6389735407435868, cp_fw=5188.5588430173211, cv_fw=3123.5687263525392, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, temp_blkt_coolant_in=573, temp_blkt_coolant_out=773, pres_blkt_coolant=8000000, diff --git a/tests/unit/models/blankets/test_ccfe_hcpb.py b/tests/unit/models/blankets/test_ccfe_hcpb.py index d1676788bb..fe32b5fd4d 100644 --- a/tests/unit/models/blankets/test_ccfe_hcpb.py +++ b/tests/unit/models/blankets/test_ccfe_hcpb.py @@ -3,6 +3,7 @@ import pytest from process.data_structure import global_variables +from process.models.engineering.pumping import CoolantType @pytest.fixture @@ -771,7 +772,7 @@ class PowerflowCalcParam(NamedTuple): p_fw_hcd_rad_total_mw=0, f_a_fw_outboard_hcd=0, p_fw_rad_total_mw=0, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, temp_blkt_coolant_out=823, pres_blkt_coolant=15500000, i_p_coolant_pumping=3, @@ -818,7 +819,7 @@ class PowerflowCalcParam(NamedTuple): f_a_fw_outboard_hcd=0, p_fw_rad_total_mw=254.39207240222791, p_div_rad_total_mw=33.056596978820579, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, temp_blkt_coolant_out=823, pres_blkt_coolant=15500000, i_p_coolant_pumping=3, diff --git a/tests/unit/models/test_costs_1990.py b/tests/unit/models/test_costs_1990.py index cb8bcfddb7..27adda6c23 100644 --- a/tests/unit/models/test_costs_1990.py +++ b/tests/unit/models/test_costs_1990.py @@ -5,6 +5,8 @@ import numpy as np import pytest +from process.models.engineering.pumping import CoolantType + @pytest.fixture def costs(process_models): @@ -23,7 +25,10 @@ def acc2261_param(**kwargs): :rtype: dict """ # Default parameters - defaults = {"i_blkt_coolant_type": 1, "expected": pytest.approx(49.68, abs=0.01)} + defaults = { + "i_blkt_coolant_type": CoolantType.HELIUM, + "expected": pytest.approx(49.68, abs=0.01), + } # Merge default dict with any optional keyword arguments to override values return {**defaults, **kwargs} @@ -40,7 +45,10 @@ def acc2261_params(): """ return [ acc2261_param(), - acc2261_param(i_blkt_coolant_type=2, expected=pytest.approx(53.85, abs=0.01)), + acc2261_param( + i_blkt_coolant_type=CoolantType.WATER, + expected=pytest.approx(53.85, abs=0.01), + ), ] @@ -375,7 +383,10 @@ def acc23_param(**kwargs): :rtype: dict """ # Default parameters - defaults = {"i_blkt_coolant_type": 1, "expected": pytest.approx(230, abs=0.01)} + defaults = { + "i_blkt_coolant_type": CoolantType.HELIUM, + "expected": pytest.approx(230, abs=0.01), + } # Merge default dict with any optional keyword arguments to override values return {**defaults, **kwargs} @@ -392,7 +403,9 @@ def acc23_params(): """ return [ acc23_param(), - acc23_param(i_blkt_coolant_type=2, expected=pytest.approx(245, abs=0.01)), + acc23_param( + i_blkt_coolant_type=CoolantType.WATER, expected=pytest.approx(245, abs=0.01) + ), ] @@ -3903,7 +3916,7 @@ class Acc2261Param(NamedTuple): ).transpose(), lsa=2, fkind=1, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, p_shld_nuclear_heat_mw=1.3609360176065353, p_blkt_nuclear_heat_total_mw=1504.711566619962, p_plant_primary_heat_mw=2620.2218111502593, @@ -3925,7 +3938,7 @@ class Acc2261Param(NamedTuple): ).transpose(), lsa=2, fkind=1, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, p_shld_nuclear_heat_mw=1.4036212304705389, p_blkt_nuclear_heat_total_mw=1549.9285082739402, p_plant_primary_heat_mw=2619.4223856129224, @@ -4759,7 +4772,7 @@ class Acc23Param(NamedTuple): np.array((230000000, 245000000), order="F"), order="F" ).transpose(), ireactor=1, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, p_plant_electric_gross_mw=982.58317918134742, c23=0, expected_c23=194.83812507173698, @@ -4769,7 +4782,7 @@ class Acc23Param(NamedTuple): np.array((230000000, 245000000), order="F"), order="F" ).transpose(), ireactor=1, - i_blkt_coolant_type=1, + i_blkt_coolant_type=CoolantType.HELIUM, p_plant_electric_gross_mw=982.28339460484608, c23=194.83812507173698, expected_c23=194.78878460447092, From 13ded563f49b20d23bb9eb098a977ba5efd90367 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Jun 2026 15:57:14 +0100 Subject: [PATCH 2/5] Refactor coolant type handling to use CoolantType enum and update related variables --- process/core/input.py | 2 +- process/core/io/plot/summary.py | 3 +- process/data_structure/fwbs_variables.py | 6 ++-- process/models/blankets/blanket_library.py | 24 ++++++------- process/models/engineering/pumping.py | 34 ++++++++++++++++--- process/models/fw.py | 11 +++--- .../input_files/spherical_tokamak_eval.IN.DAT | 2 +- .../input_files/st_regression.IN.DAT | 2 +- .../models/blankets/test_blanket_library.py | 6 ++-- tests/unit/models/test_fw.py | 6 ++-- 10 files changed, 64 insertions(+), 32 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index 540627a0a0..70c0fcd6e0 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -1061,7 +1061,7 @@ def __post_init__(self): choices=list(range(N_CONFINEMENT_SCALINGS)), ), "quench_model": InputVariable("tfcoil", str, choices=["exponential", "linear"]), - "i_fw_coolant_type": InputVariable("fwbs", str, choices=["helium", "water"]), + "i_fw_coolant_type": InputVariable("fwbs", int, choices=[1, 2]), "i_vacuum_pumping": InputVariable("vacuum", str, choices=["old", "simple"]), "dcond": InputVariable("tfcoil", float, array=True), "c_pf_coil_turn_peak_input": InputVariable("pf_coil", float, array=True), diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index a4ef142632..90a0120e0c 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -24,6 +24,7 @@ from process.data_structure.numerics import FiguresOfMerit, PROCESSRunMode from process.data_structure.pfcoil_variables import NFIXMX from process.models.build import Build +from process.models.engineering.pumping import CoolantType from process.models.geometry.blanket import ( blanket_geometry_double_null, blanket_geometry_single_null, @@ -5452,7 +5453,7 @@ def plot_first_wall_poloidal_cross_section(axis: plt.Axes, mfile: MFile, scan: i ) textstr_fw = "\n".join(( - rf"Coolant type: {i_fw_coolant_type}", + rf"Coolant type: {CoolantType(i_fw_coolant_type).name}", rf"$T_{{FW,peak}}$: {temp_fw_peak:,.3f} K", rf"$P_{{FW}}$: {pres_fw_coolant / 1e3:,.3f} kPa", rf"$P_{{FW}}$: {pres_fw_coolant / 1e5:,.3f} bar", diff --git a/process/data_structure/fwbs_variables.py b/process/data_structure/fwbs_variables.py index 3f1041e677..3375766f4b 100644 --- a/process/data_structure/fwbs_variables.py +++ b/process/data_structure/fwbs_variables.py @@ -291,10 +291,10 @@ class FWBSData: - =2 pressurized water """ - i_fw_coolant_type: str = "helium" + i_fw_coolant_type: int = 1 """switch for first wall coolant (can be different from blanket coolant): - - 'helium' - - 'water' + - =1 helium + - =2 water """ dr_fw_wall: float = 0.003 diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index f05eb8b4ff..40518202ec 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -696,14 +696,14 @@ def primary_coolant_properties(self, output: bool): # Make sure that, if the inputs for the FW and blanket inputs are different, # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants if ( - self.data.fwbs.i_fw_coolant_type == "Helium" + self.data.fwbs.i_fw_coolant_type == CoolantType.HELIUM and self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS ) if ( - self.data.fwbs.i_fw_coolant_type == "Water" + self.data.fwbs.i_fw_coolant_type == CoolantType.WATER and self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM ): self.data.fwbs.i_fw_blkt_shared_coolant = ( @@ -721,7 +721,7 @@ def primary_coolant_properties(self, output: bool): ) * 0.5 # FW/BB fw_bb_fluid_properties = FluidProperties.of( - self.data.fwbs.i_fw_coolant_type, + CoolantType(self.data.fwbs.i_fw_coolant_type).name, temperature=mid_temp, pressure=self.data.fwbs.pres_fw_coolant, ) @@ -742,7 +742,7 @@ def primary_coolant_properties(self, output: bool): self.data.fwbs.temp_fw_coolant_in + self.data.fwbs.temp_fw_coolant_out ) * 0.5 fw_fluid_properties = FluidProperties.of( - self.data.fwbs.i_fw_coolant_type, + CoolantType(self.data.fwbs.i_fw_coolant_type).name, temperature=mid_temp_fw, pressure=self.data.fwbs.pres_fw_coolant, ) @@ -805,7 +805,7 @@ def primary_coolant_properties(self, output: bool): self.outfile, "Coolant type", "(i_fw_coolant_type)", - f'"{self.data.fwbs.i_fw_coolant_type}"', + self.data.fwbs.i_fw_coolant_type, ) po.ovarrf( self.outfile, @@ -2144,14 +2144,14 @@ def thermo_hydraulic_model(self, output: bool): # Make sure that, if the inputs for the FW and blanket inputs are different, # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants if ( - self.data.fwbs.i_fw_coolant_type == "Helium" + self.data.fwbs.i_fw_coolant_type == CoolantType.HELIUM and self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS ) if ( - self.data.fwbs.i_fw_coolant_type == "Water" + self.data.fwbs.i_fw_coolant_type == CoolantType.WATER and self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM ): self.data.fwbs.i_fw_blkt_shared_coolant = ( @@ -3317,7 +3317,7 @@ def coolant_pumping_power( pres_coolant_pump_inlet: float, dpres_coolant: float, mflow_coolant_total: float, - primary_coolant_switch: str, + primary_coolant_switch: int, den_coolant: float, label: str, ) -> float: @@ -3339,8 +3339,8 @@ def coolant_pumping_power( Coolant pressure drop (Pa). mflow_coolant_total : float Total coolant mass flow rate in (kg/s). - primary_coolant_switch : str - Name of FW/blanket coolant (e.g., "Helium" or "Water") if icoolpump=1. + primary_coolant_switch : int + Type of FW/blanket coolant (e.g., 1=Helium, 2=Water) if icoolpump=1. den_coolant : float Density of coolant or liquid breeder (kg/m³). label : str @@ -3373,7 +3373,7 @@ def coolant_pumping_power( # using enthalpies before and after the pump. pump_outlet_fluid_properties = FluidProperties.of( - fluid_name=primary_coolant_switch, + fluid_name=CoolantType(primary_coolant_switch).name, temperature=temp_coolant_pump_outlet, pressure=pres_coolant_pump_outlet, ) @@ -3383,7 +3383,7 @@ def coolant_pumping_power( # Get specific enthalpy at the outlet (J/kg) before pump using pressure and entropy s1 pump_inlet_fluid_properties = FluidProperties.of( - fluid_name=primary_coolant_switch, + fluid_name=CoolantType(primary_coolant_switch).name, pressure=pres_coolant_pump_inlet, entropy=s1, ) diff --git a/process/models/engineering/pumping.py b/process/models/engineering/pumping.py index 9773eb5ae1..d5147a7d18 100644 --- a/process/models/engineering/pumping.py +++ b/process/models/engineering/pumping.py @@ -2,6 +2,7 @@ import logging from enum import IntEnum +from types import DynamicClassAttribute import numpy as np @@ -9,8 +10,33 @@ class CoolantType(IntEnum): """Enum for coolant types.""" - HELIUM = 1 - WATER = 2 + HELIUM = (1, "Helium") + WATER = (2, "Water") + + def __new__(cls, value: int, name: str): + """Create a new CoolantType enum member with value and full_name. + + Parameters + ---------- + value : int + The numeric value of the enum member. + full_name : str + The full name description of the plasma current model. + + Returns + ------- + CoolantType + A new enum member with the specified value and full_name. + """ + obj = int.__new__(cls, value) + obj._value_ = value + obj._name_ = name + return obj + + @DynamicClassAttribute + def full_name(self): + """Return the full name of the coolant type.""" + return self._name_ logger = logging.getLogger(__name__) @@ -42,7 +68,7 @@ def darcy_friction_haaland( References ---------- - - https://en.wikipedia.org/wiki/Darcy_friction_factor_formulae#Haaland_equation + [1] https://en.wikipedia.org/wiki/Darcy_friction_factor_formulae#Haaland_equation """ # Bracketed term in Haaland equation bracket = (roughness_channel / radius_channel / 3.7) ** 1.11 + 6.9 / reynolds @@ -91,7 +117,7 @@ def gnielinski_heat_transfer_coefficient( References ---------- - - https://en.wikipedia.org/wiki/Nusselt_number#Gnielinski_correlation + [1] https://en.wikipedia.org/wiki/Nusselt_number#Gnielinski_correlation """ # Calculate pipe diameter (m) diff --git a/process/models/fw.py b/process/models/fw.py index be146e78ac..f79deacde9 100644 --- a/process/models/fw.py +++ b/process/models/fw.py @@ -14,7 +14,10 @@ eshellarea, ) from process.models.engineering.materials import eurofer97_thermal_conductivity -from process.models.engineering.pumping import gnielinski_heat_transfer_coefficient +from process.models.engineering.pumping import ( + CoolantType, + gnielinski_heat_transfer_coefficient, +) logger = logging.getLogger(__name__) @@ -393,14 +396,14 @@ def fw_temp( # Calculate inlet coolant fluid properties (fixed pressure) inlet_coolant_properties = FluidProperties.of( - self.data.fwbs.i_fw_coolant_type, + CoolantType(self.data.fwbs.i_fw_coolant_type).name, temperature=self.data.fwbs.temp_fw_coolant_in, pressure=self.data.fwbs.pres_fw_coolant, ) # Calculate outlet coolant fluid properties (fixed pressure) outlet_coolant_properties = FluidProperties.of( - self.data.fwbs.i_fw_coolant_type, + CoolantType(self.data.fwbs.i_fw_coolant_type).name, temperature=self.data.fwbs.temp_fw_coolant_out, pressure=self.data.fwbs.pres_fw_coolant, ) @@ -754,7 +757,7 @@ def output_fw_pumping(self): self.outfile, "First wall coolant type", "(i_fw_coolant_type)", - f"'{self.data.fwbs.i_fw_coolant_type}'", + self.data.fwbs.i_fw_coolant_type, ) po.ovarrf( self.outfile, diff --git a/tests/regression/input_files/spherical_tokamak_eval.IN.DAT b/tests/regression/input_files/spherical_tokamak_eval.IN.DAT index 73a3b9f4be..40f9065f20 100644 --- a/tests/regression/input_files/spherical_tokamak_eval.IN.DAT +++ b/tests/regression/input_files/spherical_tokamak_eval.IN.DAT @@ -163,7 +163,7 @@ i_blkt_inboard = 0 * switch for inboard blanket; inuclear = 0 * switch for nuclear heating in the coils; i_p_coolant_pumping = 3 * Switch for pumping power for primary coolant (mechanical power only and peak first wall i_thermal_electric_conversion = 2 * Switch for power conversion cycle; -i_fw_coolant_type = helium * switch for first wall coolant (can be different from blanket coolant); +i_fw_coolant_type = 1 * switch for first wall coolant (can be different from blanket coolant); etaiso = 0.9 * isentropic efficiency of FW and blanket coolant pumps eta_coolant_pump_electric = 0.87 * electrical efficiency of primary coolant pumps i_fw_blkt_shared_coolant = 0 * Switch for whether the FW and BB are on the same pump system diff --git a/tests/regression/input_files/st_regression.IN.DAT b/tests/regression/input_files/st_regression.IN.DAT index 76d5cc679e..815f183a39 100644 --- a/tests/regression/input_files/st_regression.IN.DAT +++ b/tests/regression/input_files/st_regression.IN.DAT @@ -2166,7 +2166,7 @@ etaiso = 0.9 * DESCRIPTION: First wall coolant pressure [Pa] (`i_thermal_electric_conversion>1`) (default = 15.5D6) * JUSTIFICATION: Not yet set. -i_fw_coolant_type = helium +i_fw_coolant_type = 1 * DESCRIPTION: switch for first wall coolant (can be different from blanket coolant) (default = helium): * 'helium' * 'water' diff --git a/tests/unit/models/blankets/test_blanket_library.py b/tests/unit/models/blankets/test_blanket_library.py index d5c9c49c34..5dd92121eb 100644 --- a/tests/unit/models/blankets/test_blanket_library.py +++ b/tests/unit/models/blankets/test_blanket_library.py @@ -75,7 +75,7 @@ class PrimaryCoolantPropertiesParam(NamedTuple): "primarycoolantpropertiesparam", [ PrimaryCoolantPropertiesParam( - i_fw_coolant_type="helium", + i_fw_coolant_type=CoolantType.HELIUM, temp_fw_coolant_in=573, temp_fw_coolant_out=773, pres_fw_coolant=8000000, @@ -103,7 +103,7 @@ class PrimaryCoolantPropertiesParam(NamedTuple): expected_visc_fw_coolant=3.5036293160410249e-05, ), PrimaryCoolantPropertiesParam( - i_fw_coolant_type="helium", + i_fw_coolant_type=CoolantType.HELIUM, temp_fw_coolant_in=573, temp_fw_coolant_out=773, pres_fw_coolant=8000000, @@ -370,7 +370,7 @@ def test_pumppower_secondary_pb_li(monkeypatch, blanket_library): "pres_coolant_pump_inlet": 8000000, "dpres_coolant": 20088.23, "mflow_coolant_total": 956.3, - "primary_coolant_switch": "Helium", + "primary_coolant_switch": CoolantType.HELIUM, "den_coolant": 5.64, "label": "First Wall and Blanket", } diff --git a/tests/unit/models/test_fw.py b/tests/unit/models/test_fw.py index 0d609f00a5..544f151fbc 100644 --- a/tests/unit/models/test_fw.py +++ b/tests/unit/models/test_fw.py @@ -2,6 +2,8 @@ import pytest +from process.models.engineering.pumping import CoolantType + @pytest.fixture def fw(process_models): @@ -60,7 +62,7 @@ class FwTempParam(NamedTuple): [ FwTempParam( fw_th_conductivity=28.34, - i_fw_coolant_type="helium", + i_fw_coolant_type=CoolantType.HELIUM, temp_fw_coolant_in=573, pres_fw_coolant=8000000, temp_fw_coolant_out=773, @@ -82,7 +84,7 @@ class FwTempParam(NamedTuple): ), FwTempParam( fw_th_conductivity=28.34, - i_fw_coolant_type="helium", + i_fw_coolant_type=CoolantType.HELIUM, temp_fw_coolant_in=573, pres_fw_coolant=8000000, temp_fw_coolant_out=773, From f7e07cbc86ee3203b74ebed6d7bdcc954a47f8ff Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Jun 2026 16:06:46 +0100 Subject: [PATCH 3/5] Refactor coolant type checks to use enum comparison and update test data for first wall coolant type --- process/models/blankets/blanket_library.py | 24 ++++--------------- process/models/engineering/pumping.py | 7 +++--- .../integration/data/large_tokamak_MFILE.DAT | 2 +- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index 40518202ec..4f8a9c3904 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -695,16 +695,8 @@ def primary_coolant_properties(self, output: bool): """ # Make sure that, if the inputs for the FW and blanket inputs are different, # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants - if ( - self.data.fwbs.i_fw_coolant_type == CoolantType.HELIUM - and self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER - ): - self.data.fwbs.i_fw_blkt_shared_coolant = ( - FWBlktCoolantLoopTypes.SEPARATE_LOOPS - ) - if ( - self.data.fwbs.i_fw_coolant_type == CoolantType.WATER - and self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM + if CoolantType(self.data.fwbs.i_fw_coolant_type) != CoolantType( + self.data.fwbs.i_blkt_coolant_type ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS @@ -2143,16 +2135,8 @@ def thermo_hydraulic_model(self, output: bool): # Make sure that, if the inputs for the FW and blanket inputs are different, # the i_fw_blkt_shared_coolant variable is appropriately set for separate coolants - if ( - self.data.fwbs.i_fw_coolant_type == CoolantType.HELIUM - and self.data.fwbs.i_blkt_coolant_type == CoolantType.WATER - ): - self.data.fwbs.i_fw_blkt_shared_coolant = ( - FWBlktCoolantLoopTypes.SEPARATE_LOOPS - ) - if ( - self.data.fwbs.i_fw_coolant_type == CoolantType.WATER - and self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM + if CoolantType(self.data.fwbs.i_fw_coolant_type) != CoolantType( + self.data.fwbs.i_blkt_coolant_type ): self.data.fwbs.i_fw_blkt_shared_coolant = ( FWBlktCoolantLoopTypes.SEPARATE_LOOPS diff --git a/process/models/engineering/pumping.py b/process/models/engineering/pumping.py index d5147a7d18..78d40fecc7 100644 --- a/process/models/engineering/pumping.py +++ b/process/models/engineering/pumping.py @@ -20,13 +20,14 @@ def __new__(cls, value: int, name: str): ---------- value : int The numeric value of the enum member. - full_name : str - The full name description of the plasma current model. + name : str + The name description of the coolant type. + This should match the CoolProp name for the coolant type. Returns ------- CoolantType - A new enum member with the specified value and full_name. + A new enum member with the specified value and name. """ obj = int.__new__(cls, value) obj._value_ = value diff --git a/tests/integration/data/large_tokamak_MFILE.DAT b/tests/integration/data/large_tokamak_MFILE.DAT index 95868afd37..f3070e3f26 100644 --- a/tests/integration/data/large_tokamak_MFILE.DAT +++ b/tests/integration/data/large_tokamak_MFILE.DAT @@ -35469,7 +35469,7 @@ Peak_radiation_wall_load_(MW/m^2)________________________________________ (pflux Fast_alpha_particle_power_incident_on_the_first-wall_(MW)________________ (p_fw_alpha_mw)________________ 1.63474424550099187e+01 OP Nominal_mean_neutron_load_on_vessel_first-wall_(MW/m^2)__________________ (pflux_fw_neutron_mw)__________ 1.01712659903962166e+00 OP # First wall pumping # -First_wall_coolant_type__________________________________________________ (i_fw_coolant_type)____________ 'helium' +First_wall_coolant_type__________________________________________________ (i_fw_coolant_type)____________ 1 Outlet_temperature_of_first_wall_coolant_[K]_____________________________ (temp_fw_coolant_out)__________ 8.23000000000000000e+02 OP Inlet_temperature_of_first_wall_coolant_[K]______________________________ (temp_fw_coolant_in)___________ 5.73000000000000000e+02 OP Pressure_of_first_wall_coolant_[Pa]______________________________________ (pres_fw_coolant)______________ 1.55000000000000000e+07 OP From c4b4ba8d75d93d2d96812e18244fd3b7c51fdd1b Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Jun 2026 16:31:05 +0100 Subject: [PATCH 4/5] Update CoolantType enum to use full_name and refactor coolant property retrieval --- process/models/blankets/blanket_library.py | 10 +++------- process/models/engineering/pumping.py | 12 ++++++------ process/models/fw.py | 4 ++-- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index 4f8a9c3904..82cf4832f9 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -713,7 +713,7 @@ def primary_coolant_properties(self, output: bool): ) * 0.5 # FW/BB fw_bb_fluid_properties = FluidProperties.of( - CoolantType(self.data.fwbs.i_fw_coolant_type).name, + CoolantType(self.data.fwbs.i_fw_coolant_type).full_name, temperature=mid_temp, pressure=self.data.fwbs.pres_fw_coolant, ) @@ -734,7 +734,7 @@ def primary_coolant_properties(self, output: bool): self.data.fwbs.temp_fw_coolant_in + self.data.fwbs.temp_fw_coolant_out ) * 0.5 fw_fluid_properties = FluidProperties.of( - CoolantType(self.data.fwbs.i_fw_coolant_type).name, + CoolantType(self.data.fwbs.i_fw_coolant_type).full_name, temperature=mid_temp_fw, pressure=self.data.fwbs.pres_fw_coolant, ) @@ -2471,11 +2471,7 @@ def thermo_hydraulic_model(self, output: bool): pres_coolant_pump_inlet=self.data.fwbs.pres_blkt_coolant, dpres_coolant=deltap_blkt, mflow_coolant_total=self.data.blanket.mflow_blkt_coolant_total, - primary_coolant_switch=( - "Helium" - if self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM - else "Water" - ), + primary_coolant_switch=(self.data.fwbs.i_blkt_coolant_type), den_coolant=self.data.fwbs.den_blkt_coolant, label="Blanket", ) diff --git a/process/models/engineering/pumping.py b/process/models/engineering/pumping.py index 78d40fecc7..bf447298b0 100644 --- a/process/models/engineering/pumping.py +++ b/process/models/engineering/pumping.py @@ -13,31 +13,31 @@ class CoolantType(IntEnum): HELIUM = (1, "Helium") WATER = (2, "Water") - def __new__(cls, value: int, name: str): + def __new__(cls, value: int, full_name: str): """Create a new CoolantType enum member with value and full_name. Parameters ---------- value : int The numeric value of the enum member. - name : str - The name description of the coolant type. + full_name : str + The full name description of the coolant type. This should match the CoolProp name for the coolant type. Returns ------- CoolantType - A new enum member with the specified value and name. + A new enum member with the specified value and full_name. """ obj = int.__new__(cls, value) obj._value_ = value - obj._name_ = name + obj._full_name_ = full_name return obj @DynamicClassAttribute def full_name(self): """Return the full name of the coolant type.""" - return self._name_ + return self._full_name_ logger = logging.getLogger(__name__) diff --git a/process/models/fw.py b/process/models/fw.py index f79deacde9..56a9e94fda 100644 --- a/process/models/fw.py +++ b/process/models/fw.py @@ -396,14 +396,14 @@ def fw_temp( # Calculate inlet coolant fluid properties (fixed pressure) inlet_coolant_properties = FluidProperties.of( - CoolantType(self.data.fwbs.i_fw_coolant_type).name, + CoolantType(self.data.fwbs.i_fw_coolant_type).full_name, temperature=self.data.fwbs.temp_fw_coolant_in, pressure=self.data.fwbs.pres_fw_coolant, ) # Calculate outlet coolant fluid properties (fixed pressure) outlet_coolant_properties = FluidProperties.of( - CoolantType(self.data.fwbs.i_fw_coolant_type).name, + CoolantType(self.data.fwbs.i_fw_coolant_type).full_name, temperature=self.data.fwbs.temp_fw_coolant_out, pressure=self.data.fwbs.pres_fw_coolant, ) From 135dd8d98f6691aa1f8a6ec06c1fe1142aba392f Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Jun 2026 16:32:59 +0100 Subject: [PATCH 5/5] Refactor coolant type handling to use full_name for coolant properties in BlanketLibrary --- process/models/blankets/blanket_library.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index 82cf4832f9..a9831b8caf 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -749,9 +749,7 @@ def primary_coolant_properties(self, output: bool): + self.data.fwbs.temp_blkt_coolant_out ) * 0.5 bb_fluid_properties = FluidProperties.of( - "Helium" - if self.data.fwbs.i_blkt_coolant_type == CoolantType.HELIUM - else "Water", + CoolantType(self.data.fwbs.i_blkt_coolant_type).full_name, temperature=mid_temp_bl, pressure=self.data.fwbs.pres_blkt_coolant, ) @@ -2509,9 +2507,7 @@ def thermo_hydraulic_model(self, output: bool): pres_coolant_pump_inlet=self.data.fwbs.blpressure_liq, dpres_coolant=deltap_bl_liq, mflow_coolant_total=self.data.blanket.mfblkt_liq, - primary_coolant_switch=( - "Helium" if self.data.fwbs.i_blkt_coolant_type == 1 else "Water" - ), + primary_coolant_switch=(self.data.fwbs.i_blkt_coolant_type), den_coolant=self.data.fwbs.den_liq, label="Liquid Metal Breeder/Coolant", )