From 40564a91f5a6272dfbbc0b7789644fda6a8cc472 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 27 Jul 2026 10:23:45 +0100 Subject: [PATCH 1/8] Refactor SuperconductorModel to include critical field and temperature parameters for improved flexibility --- process/models/superconductors.py | 43 ++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/process/models/superconductors.py b/process/models/superconductors.py index 7b37a1c247..70ba9d20a5 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -76,49 +76,72 @@ class SuperconductorModel(IntEnum): ITER_NB3SN = ( 1, SuperconductorMaterial.NB3SN, + 32.97e0, # [T] + 16.06e0, # [K] SuperconductorShape.CABLE, "ITER Nb₃Sn critical surface model", ) - BI2212 = (2, SuperconductorMaterial.BI2212, SuperconductorShape.CABLE, "Bi-2212") + BI2212 = ( + 2, + SuperconductorMaterial.BI2212, + None, + None, + SuperconductorShape.CABLE, + "Bi-2212", + ) OLD_LUBELL_NBTI = ( 3, SuperconductorMaterial.NBTI, + 15.0e0, # [T] + 9.3e0, # [K] SuperconductorShape.CABLE, "Old Lubell NbTi", ) USER_DEFINED_NB3SN = ( 4, SuperconductorMaterial.NB3SN, + None, + None, SuperconductorShape.CABLE, "User-defined ITER Nb₃Sn", ) WST_NB3SN = ( 5, SuperconductorMaterial.NB3SN, + 32.97e0, # [T] + 16.06e0, # [K] SuperconductorShape.CABLE, "Western Superconducting Nb₃Sn", ) CROCO_REBCO = ( 6, SuperconductorMaterial.REBCO, + None, + None, SuperconductorShape.TAPE, "CROCO REBCO", ) DURHAM_NBTI = ( 7, SuperconductorMaterial.NBTI, + None, + None, SuperconductorShape.CABLE, "Durham Ginzburg-Landau NbTi", ) DURHAM_REBCO = ( 8, SuperconductorMaterial.REBCO, + 430.0e0, # [T] + 185.0e0, # [K] SuperconductorShape.TAPE, "Durham Ginzburg-Landau REBCO", ) HAZELTON_ZHAI_REBCO = ( 9, SuperconductorMaterial.REBCO, + 138.0e0, # [T] + 92.0e0, # [K] SuperconductorShape.TAPE, "Hazelton-Zhai REBCO", ) @@ -127,6 +150,8 @@ def __new__( cls, value: int, material: SuperconductorMaterial, + b_crit_zero_temp_strain: float, + temp_crit_zero_field_strain: float, shape: SuperconductorShape, full_name: str, ): @@ -134,6 +159,8 @@ def __new__( obj = int.__new__(cls, value) obj._value_ = value obj._material_ = material + obj._b_crit_zero_temp_strain = b_crit_zero_temp_strain + obj._temp_crit_zero_field_strain = temp_crit_zero_field_strain obj._shape_ = shape obj._full_name_ = full_name return obj @@ -153,6 +180,20 @@ def sc_shape(self): """The superconductor shape associated with this model.""" return self._shape_ + @DynamicClassAttribute + def b_crit_zero_field_strain(self): + """The upper critical field [T] for the superconductor at zero temperature and + strain (ε = 0). + """ + return self._b_crit_zero_temp_strain + + @DynamicClassAttribute + def temp_crit_zero_field_strain(self): + """The critical temperature [K] for the superconductor at zero field and strain + (ε = 0). + """ + return self._temp_crit_zero_field_strain + @DynamicClassAttribute def sc_type(self): """The superconductor type (LTS or HTS) associated with this model.""" From 0b54f759d6cb4247ebe0b2d28e21c05cc986d105 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 27 Jul 2026 10:26:59 +0100 Subject: [PATCH 2/8] Replace hardcoded bc20m and tc0m values with dynamic properties from SuperconductorModel --- process/models/tfcoil/superconducting.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index fdc25e2030..dc3aff3eed 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -2793,8 +2793,8 @@ def tf_cable_in_conduit_superconductor_properties( # ITER Nb3Sn critical surface parameterization if i_tf_superconductor == SuperconductorModel.ITER_NB3SN: # Peak field and temperature at zero strain - bc20m = 32.97e0 # [T] - tc0m = 16.06e0 # [K] + bc20m = SuperconductorModel.ITER_NB3SN.b_crit_zero_field_strain # [T] + tc0m = SuperconductorModel.ITER_NB3SN.temp_crit_zero_field_strain # [K] # If strain limit achieved, throw a warning and use the lower strain if abs(strain) > 0.5e-2: @@ -2864,8 +2864,8 @@ def tf_cable_in_conduit_superconductor_properties( # NbTi data elif i_tf_superconductor == SuperconductorModel.OLD_LUBELL_NBTI: - bc20m = 15.0e0 # [T] - tc0m = 9.3e0 # [K] + bc20m = SuperconductorModel.OLD_LUBELL_NBTI.b_crit_zero_field_strain # [T] + tc0m = SuperconductorModel.OLD_LUBELL_NBTI.temp_crit_zero_field_strain # [K] c0 = 1.0e10 # [A/m²] j_superconductor_critical, _ = superconductors.jcrit_nbti( @@ -2930,8 +2930,8 @@ def tf_cable_in_conduit_superconductor_properties( # WST Nb3Sn parameterisation elif i_tf_superconductor == SuperconductorModel.WST_NB3SN: - bc20m = 32.97e0 # [T] - tc0m = 16.06e0 # [K] + bc20m = SuperconductorModel.WST_NB3SN.b_crit_zero_field_strain # [T] + tc0m = SuperconductorModel.WST_NB3SN.temp_crit_zero_field_strain # [K] # If strain limit achieved, throw a warning and use the lower strain if abs(strain) > 0.5e-2: @@ -3007,8 +3007,8 @@ def tf_cable_in_conduit_superconductor_properties( # Durham Ginzburg-Landau critical surface model for REBCO elif i_tf_superconductor == SuperconductorModel.DURHAM_REBCO: - bc20m = 430 # [T] - tc0m = 185 # [K] + bc20m = SuperconductorModel.DURHAM_REBCO.b_crit_zero_field_strain # [T] + tc0m = SuperconductorModel.DURHAM_REBCO.temp_crit_zero_field_strain # [K] # If strain limit achieved, throw a warning and use the lower strain if abs(strain) > 0.7e-2: @@ -3048,8 +3048,12 @@ def tf_cable_in_conduit_superconductor_properties( # Hazelton experimental data + Zhai conceptual model for REBCO elif i_tf_superconductor == SuperconductorModel.HAZELTON_ZHAI_REBCO: - bc20m = 138 # [T] - tc0m = 92 # [K] + bc20m = ( + SuperconductorModel.HAZELTON_ZHAI_REBCO.b_crit_zero_field_strain + ) # [T] + tc0m = ( + SuperconductorModel.HAZELTON_ZHAI_REBCO.temp_crit_zero_field_strain + ) # [K] # If strain limit achieved, throw a warning and use the lower strain if abs(strain) > 0.7e-2: From 296b4e531d46c9aa0174dd4b151d96c493df7f4c Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 27 Jul 2026 10:28:19 +0100 Subject: [PATCH 3/8] Replace hardcoded bc20m and tc0m values with dynamic properties from SuperconductorModel --- process/models/pfcoil.py | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/process/models/pfcoil.py b/process/models/pfcoil.py index c1843a3e34..1a0e4a1cde 100644 --- a/process/models/pfcoil.py +++ b/process/models/pfcoil.py @@ -4722,8 +4722,12 @@ def j_crit_cable_frac(j_crit_sc, fcu, fhe): # Find critical current density in superconducting strand, jcritstr if isumat == SuperconductorModel.ITER_NB3SN: # ITER Nb3Sn critical surface parameterization - bc20m = 32.97e0 # [T] critical field at 0 K and 0 strain - tc0m = 16.06e0 # [K] critical temperature at 0 T and 0 strain + bc20m = ( + SuperconductorModel.ITER_NB3SN.b_crit_zero_field_strain + ) # [T] critical field at 0 K and 0 strain + tc0m = ( + SuperconductorModel.ITER_NB3SN.temp_crit_zero_field_strain + ) # [K] critical temperature at 0 T and 0 strain # j_crit_sc returned by superconductors.itersc is # the critical current density in the superconductor @@ -4761,8 +4765,12 @@ def j_crit_cable_frac(j_crit_sc, fcu, fhe): elif isumat == SuperconductorModel.OLD_LUBELL_NBTI: # NbTi data - bc20m = 15.0e0 # [T] critical field at 0 K and 0 strain - tc0m = 9.3e0 # [K] critical temperature at 0 T and 0 strain + bc20m = ( + SuperconductorModel.OLD_LUBELL_NBTI.b_crit_zero_field_strain + ) # [T] critical field at 0 K and 0 strain + tc0m = ( + SuperconductorModel.OLD_LUBELL_NBTI.temp_crit_zero_field_strain + ) # [K] critical temperature at 0 T and 0 strain c0 = 1.0e10 # # [A/m²] j_crit_sc, _ = superconductors.jcrit_nbti( temp_conductor=temp_pf_peak_field, @@ -4788,8 +4796,12 @@ def j_crit_cable_frac(j_crit_sc, fcu, fhe): elif isumat == SuperconductorModel.WST_NB3SN: # WST Nb3Sn parameterisation - bc20m = 32.97e0 # [T] critical field at 0 K and 0 strain - tc0m = 16.06e0 # [K] critical temperature at 0 T and 0 strain + bc20m = ( + SuperconductorModel.WST_NB3SN.b_crit_zero_field_strain + ) # [T] critical field at 0 K and 0 strain + tc0m = ( + SuperconductorModel.WST_NB3SN.temp_crit_zero_field_strain + ) # [K] critical temperature at 0 T and 0 strain # j_crit_sc returned by superconductors.itersc is the critical current density # in the superconductor - not the whole strand, which contains copper @@ -4825,8 +4837,12 @@ def j_crit_cable_frac(j_crit_sc, fcu, fhe): elif isumat == SuperconductorModel.DURHAM_REBCO: # Durham Ginzburg-Landau critical surface model for REBCO - bc20m = 429e0 # [T] critical field at 0 K and 0 strain - tc0m = 185e0 # [K] critical temperature at 0 T and 0 strain + bc20m = ( + SuperconductorModel.DURHAM_REBCO.b_crit_zero_field_strain + ) # [T] critical field at 0 K and 0 strain + tc0m = ( + SuperconductorModel.DURHAM_REBCO.temp_crit_zero_field_strain + ) # [K] critical temperature at 0 T and 0 strain j_crit_sc, _, _ = superconductors.gl_rebco( temp_conductor=temp_pf_peak_field, b_conductor=b_pf_peak, @@ -4839,8 +4855,12 @@ def j_crit_cable_frac(j_crit_sc, fcu, fhe): elif isumat == SuperconductorModel.HAZELTON_ZHAI_REBCO: # Hazelton experimental data + Zhai conceptual model for REBCO - bc20m = 138 # [T] critical field at 0 K and 0 strain - tc0m = 92 # [K] critical temperature at 0 T and 0 strain + bc20m = ( + SuperconductorModel.HAZELTON_ZHAI_REBCO.b_crit_zero_field_strain + ) # [T] critical field at 0 K and 0 strain + tc0m = ( + SuperconductorModel.HAZELTON_ZHAI_REBCO.temp_crit_zero_field_strain + ) # [K] critical temperature at 0 T and 0 strain j_crit_sc, _, _ = superconductors.hijc_rebco( temp_conductor=temp_pf_peak_field, b_conductor=b_pf_peak, From f920c10635f8e9ba2e7e4934071f655783da3ccd Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 27 Jul 2026 10:32:54 +0100 Subject: [PATCH 4/8] Update Durham NbTi parameters to use defined properties for critical field and temperature --- process/models/superconductors.py | 4 ++-- process/models/tfcoil/superconducting.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/process/models/superconductors.py b/process/models/superconductors.py index 70ba9d20a5..6bfa0ac936 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -124,8 +124,8 @@ class SuperconductorModel(IntEnum): DURHAM_NBTI = ( 7, SuperconductorMaterial.NBTI, - None, - None, + 14.86e0, # [T] + 9.2e0, # [K] SuperconductorShape.CABLE, "Durham Ginzburg-Landau NbTi", ) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index dc3aff3eed..0bd333367f 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -2979,8 +2979,8 @@ def tf_cable_in_conduit_superconductor_properties( # Durham Ginzburg-Landau Nb-Ti parameterisation elif i_tf_superconductor == SuperconductorModel.DURHAM_NBTI: - bc20m = data.tfcoil.b_crit_upper_nbti # [T] - tc0m = data.tfcoil.t_crit_nbti # [K] + bc20m = SuperconductorModel.DURHAM_NBTI.b_crit_zero_field_strain # [T] + tc0m = SuperconductorModel.DURHAM_NBTI.temp_crit_zero_field_strain # [K] j_superconductor_critical, _, _ = superconductors.gl_nbti( temp_conductor=temp_tf_coolant_peak_field, From 9097d944bec7d915437506381960ac6bf43e863e Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 27 Jul 2026 10:36:55 +0100 Subject: [PATCH 5/8] Remove hardcoded bc20m and tc0m values from PFCoil and CSCoil models, replacing them with dynamic properties from SuperconductorModel --- process/models/pfcoil.py | 20 ++++++-------------- tests/unit/models/test_pfcoil.py | 6 ------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/process/models/pfcoil.py b/process/models/pfcoil.py index 1a0e4a1cde..3b07e15952 100644 --- a/process/models/pfcoil.py +++ b/process/models/pfcoil.py @@ -898,8 +898,6 @@ def pfcoil(self): temp_pf_peak_field=self.data.tfcoil.tftmp, bcritsc=self.data.tfcoil.bcritsc, tcritsc=self.data.tfcoil.tcritsc, - b_crit_upper_nbti=self.data.tfcoil.b_crit_upper_nbti, - t_crit_nbti=self.data.tfcoil.t_crit_nbti, dr_hts_tape=self.data.superconducting_tfcoil.dr_tf_hts_tape, dx_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco, dx_hts_tape_total=self.data.superconducting_tfcoil.dx_tf_hts_tape_total, @@ -3613,8 +3611,6 @@ def ohcalc(self): temp_pf_peak_field=self.data.pf_coil.temp_cs_superconductor_operating, bcritsc=self.data.tfcoil.bcritsc, tcritsc=self.data.tfcoil.tcritsc, - b_crit_upper_nbti=self.data.tfcoil.b_crit_upper_nbti, - t_crit_nbti=self.data.tfcoil.t_crit_nbti, dr_hts_tape=self.data.superconducting_tfcoil.dr_tf_hts_tape, dx_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco, dx_hts_tape_total=self.data.superconducting_tfcoil.dx_tf_hts_tape_total, @@ -3663,8 +3659,6 @@ def ohcalc(self): temp_pf_peak_field=self.data.pf_coil.temp_cs_superconductor_operating, bcritsc=self.data.tfcoil.bcritsc, tcritsc=self.data.tfcoil.tcritsc, - b_crit_upper_nbti=self.data.tfcoil.b_crit_upper_nbti, - t_crit_nbti=self.data.tfcoil.t_crit_nbti, dr_hts_tape=self.data.superconducting_tfcoil.dr_tf_hts_tape, dx_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco, dx_hts_tape_total=self.data.superconducting_tfcoil.dx_tf_hts_tape_total, @@ -4643,8 +4637,6 @@ def superconpf( temp_pf_peak_field: float, bcritsc: float, tcritsc: float, - b_crit_upper_nbti: float, - t_crit_nbti: float, dr_hts_tape: float, dx_hts_tape_rebco: float, dx_hts_tape_total: float, @@ -4692,10 +4684,6 @@ def superconpf( Critical field at zero temperature and strain [T] (isumat=4 only) tcritsc : float Critical temperature at zero field and strain [K] (isumat=4 only) - b_crit_upper_nbti: float - upper critical field of GL_nbti [T] - t_crit_nbti: float - critical temperature of GL_nbti [K] dr_hts_tape: float Mean width of tape [m] dx_hts_tape_rebco: float @@ -4824,8 +4812,12 @@ def j_crit_cable_frac(j_crit_sc, fcu, fhe): elif isumat == SuperconductorModel.DURHAM_NBTI: # Durham Ginzburg-Landau critical surface model for Nb-Ti - bc20m = b_crit_upper_nbti # [T] critical field at 0 K and 0 strain - tc0m = t_crit_nbti # [K] critical temperature at 0 T and 0 strain + bc20m = ( + SuperconductorModel.DURHAM_NBTI.b_crit_zero_field_strain + ) # [T] critical field at 0 K and 0 strain + tc0m = ( + SuperconductorModel.DURHAM_NBTI.temp_crit_zero_field_strain + ) # [K] critical temperature at 0 T and 0 strain j_crit_sc, _, _ = superconductors.gl_nbti( temp_conductor=temp_pf_peak_field, b_conductor=b_pf_peak, diff --git a/tests/unit/models/test_pfcoil.py b/tests/unit/models/test_pfcoil.py index dc096cb36d..7d011fd227 100644 --- a/tests/unit/models/test_pfcoil.py +++ b/tests/unit/models/test_pfcoil.py @@ -3805,8 +3805,6 @@ def test_peakb(monkeypatch, pfcoil): class SuperconPFParam(NamedTuple): - b_crit_upper_nbti: Any = None - t_crit_nbti: Any = None bmax: Any = None fhe: Any = None fcu: Any = None @@ -3836,8 +3834,6 @@ class SuperconPFParam(NamedTuple): thelium=4.75, bcritsc=24, tcritsc=16, - b_crit_upper_nbti=14.86, - t_crit_nbti=9.04, dr_tf_hts_tape=4.0e-3, dx_tf_hts_tape_rebco=1.0e-6, dx_tf_hts_tape_total=6.5e-5, @@ -3873,8 +3869,6 @@ def test_superconpf(superconpfparam): superconpfparam.thelium, superconpfparam.bcritsc, superconpfparam.tcritsc, - superconpfparam.b_crit_upper_nbti, - superconpfparam.t_crit_nbti, superconpfparam.dr_tf_hts_tape, superconpfparam.dx_tf_hts_tape_rebco, superconpfparam.dx_tf_hts_tape_total, From 900b7467b6dbb7eb79dc9e926bd3e1ddef09b261 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 27 Jul 2026 10:43:59 +0100 Subject: [PATCH 6/8] Remove hardcoded b_crit_upper_nbti and t_crit_nbti values, replacing them with dynamic properties from SuperconductorModel --- process/core/input.py | 2 -- process/core/io/plot/scans.py | 2 +- process/core/scan.py | 2 -- process/data_structure/tfcoil_variables.py | 6 ------ process/models/stellarator/coils/calculate.py | 2 -- process/models/stellarator/coils/coils.py | 7 +++---- tests/unit/models/test_pfcoil.py | 12 ------------ tests/unit/models/tfcoil/test_sctfcoil.py | 16 ---------------- 8 files changed, 4 insertions(+), 45 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index f9466abda4..eacb941090 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -209,7 +209,6 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]: "auxcool_w": InputVariable("buildings", float, range=(10.0, 1000.0)), "p_hcd_injected_min_mw": InputVariable("constraints", float, range=(0.01, 100.0)), "f_t_plant_available_min": InputVariable("costs", float, range=(0.0, 1.0)), - "b_crit_upper_nbti": InputVariable("tfcoil", float, range=(0.0, 30.0)), "p_plant_electric_base": InputVariable( "heat_transport", float, range=(1000000.0, 10000000000.0) ), @@ -786,7 +785,6 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]: "dx_tf_turn_cable_space_general": InputVariable("tfcoil", float, range=(0.0, 0.1)), "t_crack_radial": InputVariable("cs_fatigue", float, range=(1e-05, 1.0)), "t_crack_vertical": InputVariable("cs_fatigue", float, range=(1e-05, 1.0)), - "t_crit_nbti": InputVariable("tfcoil", float, range=(0.0, 15.0)), "t_plant_pulse_plasma_current_ramp_up": InputVariable( "times", float, range=(0.0, 10000.0) ), diff --git a/process/core/io/plot/scans.py b/process/core/io/plot/scans.py index 80ac996f60..44579fad95 100644 --- a/process/core/io/plot/scans.py +++ b/process/core/io/plot/scans.py @@ -131,7 +131,7 @@ def plot_scan( 51: "f_p_div_lower", 52: "rad_fraction_sol", 53: "Obsolete", # OBSOLETE - 54: "b_crit_upper_nbti", + 54: "Obsolete", # OBSOLETE 55: "dr_shld_inboard", 56: "p_cryo_plant_electric_max_mw", # Genuinely b_plasma_toroidal_on_axis lower bound diff --git a/process/core/scan.py b/process/core/scan.py index 535eae7f36..f8d92c2b35 100644 --- a/process/core/scan.py +++ b/process/core/scan.py @@ -1200,8 +1200,6 @@ def scan_select(self, nwp, swp, iscn): self.data.physics.rad_fraction_sol = swp[iscn - 1] case 53: self.data.numerics.boundu[156] = swp[iscn - 1] - case 54: - self.data.tfcoil.b_crit_upper_nbti = swp[iscn - 1] case 55: self.data.build.dr_shld_inboard = swp[iscn - 1] case 56: diff --git a/process/data_structure/tfcoil_variables.py b/process/data_structure/tfcoil_variables.py index e15d317a3b..3e75c582dc 100644 --- a/process/data_structure/tfcoil_variables.py +++ b/process/data_structure/tfcoil_variables.py @@ -184,12 +184,6 @@ class TFData: e_tf_coil_magnetic_stored: float = 0.0 """Stored magnetic energy in a single TF coil (J)""" - b_crit_upper_nbti: float = 14.86 - """upper critical field of GL_nbti""" - - t_crit_nbti: float = 9.04 - """critical temperature of GL_nbti""" - max_force_density: float = 0.0 """Maximal (WP averaged) force density in TF coils at 1 point. (MN/m3)""" diff --git a/process/models/stellarator/coils/calculate.py b/process/models/stellarator/coils/calculate.py index 129ae460f2..6b2f1a4fd6 100644 --- a/process/models/stellarator/coils/calculate.py +++ b/process/models/stellarator/coils/calculate.py @@ -410,11 +410,9 @@ def winding_pack_total_size( b_max_k[k], data.tfcoil.tftmp + data.tfcoil.tmargmin, data.tfcoil.i_tf_sc_mat, - data.tfcoil.b_crit_upper_nbti, data.tfcoil.bcritsc, data.tfcoil.f_a_tf_turn_cable_copper, data.tfcoil.fhts, - data.tfcoil.t_crit_nbti, data.tfcoil.tcritsc, data.tfcoil.f_a_tf_turn_cable_space_extra_void, data.tfcoil.j_tf_wp, diff --git a/process/models/stellarator/coils/coils.py b/process/models/stellarator/coils/coils.py index 5b16e1122c..c2bc90c262 100644 --- a/process/models/stellarator/coils/coils.py +++ b/process/models/stellarator/coils/coils.py @@ -5,6 +5,7 @@ from process.core.exceptions import ProcessValueError from process.core.model import DataStructure from process.models import superconductors +from process.models.superconductors import SuperconductorModel logger = logging.getLogger(__name__) @@ -21,11 +22,9 @@ def jcrit_from_material( b_max, t_helium, i_tf_sc_mat, - b_crit_upper_nbti, b_crit_sc, f_a_tf_turn_cable_copper, f_hts, - t_crit_nbti, t_crit_sc, f_a_tf_turn_cable_space_extra_void, j_wp, @@ -129,8 +128,8 @@ def jcrit_from_material( j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he) elif i_tf_sc_mat == 7: # Durham Ginzburg-Landau Nb-Ti parameterisation - bc20m = b_crit_upper_nbti - tc0m = t_crit_nbti + bc20m = SuperconductorModel.DURHAM_NBTI.b_crit_zero_field_strain + tc0m = SuperconductorModel.DURHAM_NBTI.temp_crit_zero_field_strain j_crit_sc, _bcrit, _tcrit = superconductors.gl_nbti( t_helium, b_max, strain, bc20m, tc0m ) diff --git a/tests/unit/models/test_pfcoil.py b/tests/unit/models/test_pfcoil.py index 7d011fd227..a7b8c4fe64 100644 --- a/tests/unit/models/test_pfcoil.py +++ b/tests/unit/models/test_pfcoil.py @@ -2478,8 +2478,6 @@ class PFCoilParam(NamedTuple): tcritsc: Any = None str_pf_con_res: Any = None bcritsc: Any = None - b_crit_upper_nbti: Any = None - t_crit_nbti: Any = None first_call: Any = None r_tf_outboard_out: Any = None t_plant_pulse_coil_precharge: Any = None @@ -2553,8 +2551,6 @@ class PFCoilParam(NamedTuple): tcritsc=1.6e1, str_pf_con_res=-5.0e-3, bcritsc=2.4e1, - b_crit_upper_nbti=1.486e1, - t_crit_nbti=9.04, first_call=True, r_tf_outboard_out=10.0, t_plant_pulse_coil_precharge=5.0e2, @@ -2661,8 +2657,6 @@ def test_pfcoil(monkeypatch, pfcoil, pfcoilparam): "tcritsc", "str_pf_con_res", "bcritsc", - "b_crit_upper_nbti", - "t_crit_nbti", ]: monkeypatch.setattr(pfcoil.data.tfcoil, field, getattr(pfcoilparam, field)) @@ -2727,14 +2721,12 @@ class OhCalcParam(NamedTuple): str_cs_con_res: Any = None fhts: Any = None bcritsc: Any = None - t_crit_nbti: Any = None c_pf_cs_coil_pulse_start_ma: Any = None c_pf_cs_coil_flat_top_ma: Any = None c_pf_cs_coil_pulse_end_ma: Any = None rmajor: Any = None plasma_current: Any = None poisson_steel: Any = None - b_crit_upper_nbti: Any = None exp_b_pf_coil_peak: Any = None exp_j_cs_critical_flat_top_end: Any = None @@ -2780,14 +2772,12 @@ class OhCalcParam(NamedTuple): str_cs_con_res=-5.000e-3, fhts=0.5, bcritsc=2.4e1, - t_crit_nbti=9.04, c_pf_cs_coil_pulse_start_ma=np.full(22, 0.0), c_pf_cs_coil_flat_top_ma=np.full(22, 0.0), c_pf_cs_coil_pulse_end_ma=np.full(22, -175.84911993600002), rmajor=8.938, plasma_current=1.8254e7, poisson_steel=3.0e-1, - b_crit_upper_nbti=9.04, exp_b_pf_coil_peak=13.073958753751993, exp_j_cs_critical_flat_top_end=54101481.7685945, ) @@ -2854,9 +2844,7 @@ def test_ohcalc(monkeypatch, reinitialise_error_module, cs_coil, ohcalcparam): "str_cs_con_res", "fhts", "bcritsc", - "t_crit_nbti", "poisson_steel", - "b_crit_upper_nbti", ]: monkeypatch.setattr(cs_coil.data.tfcoil, field, getattr(ohcalcparam, field)) diff --git a/tests/unit/models/tfcoil/test_sctfcoil.py b/tests/unit/models/tfcoil/test_sctfcoil.py index ca7a56e990..785a96ac50 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -161,14 +161,10 @@ class SuperconParam(NamedTuple): a_tf_turn_cable_space_effective: Any = None - b_crit_upper_nbti: Any = None - i_str_wp: Any = None str_wp: Any = None - t_crit_nbti: Any = None - tf_fit_t: Any = None tf_fit_z: Any = None @@ -249,11 +245,9 @@ class SuperconParam(NamedTuple): c_tf_turn=74026.751437500003, b_tf_inboard_peak_with_ripple=12.48976756562082, str_tf_con_res=-0.0050000000000000001, - b_crit_upper_nbti=14.859999999999999, i_str_wp=1, f_a_tf_turn_cable_space_cooling=0.3, str_wp=0.0015619754370069119, - t_crit_nbti=9.0399999999999991, tf_fit_t=0.80807838916035957, tf_fit_z=0.3149613642807837, f_b_tf_inboard_peak_ripple_symmetric=1.0658869305062604, @@ -299,11 +293,9 @@ class SuperconParam(NamedTuple): c_tf_turn=74026.751437500003, b_tf_inboard_peak_with_ripple=12.48976756562082, str_tf_con_res=-0.0050000000000000001, - b_crit_upper_nbti=14.859999999999999, i_str_wp=1, f_a_tf_turn_cable_space_cooling=0.3, str_wp=0.0015619754370069119, - t_crit_nbti=9.0399999999999991, tf_fit_t=0.80807838916035957, tf_fit_z=0.3149613642807837, f_b_tf_inboard_peak_ripple_symmetric=1.0658869305062604, @@ -400,18 +392,10 @@ def test_supercon(superconparam, monkeypatch, cicc_sctfcoil): cicc_sctfcoil.data.tfcoil, "str_tf_con_res", superconparam.str_tf_con_res ) - monkeypatch.setattr( - cicc_sctfcoil.data.tfcoil, "b_crit_upper_nbti", superconparam.b_crit_upper_nbti - ) - monkeypatch.setattr(cicc_sctfcoil.data.tfcoil, "i_str_wp", superconparam.i_str_wp) monkeypatch.setattr(cicc_sctfcoil.data.tfcoil, "str_wp", superconparam.str_wp) - monkeypatch.setattr( - cicc_sctfcoil.data.tfcoil, "t_crit_nbti", superconparam.t_crit_nbti - ) - monkeypatch.setattr( cicc_sctfcoil.data.superconducting_tfcoil, "tf_fit_t", superconparam.tf_fit_t ) From a664dd0a008f6cceea72abdaf4058918220e8eda Mon Sep 17 00:00:00 2001 From: Christopher Ashe <91618944+chris-ashe@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:39:24 +0100 Subject: [PATCH 7/8] Update process/models/superconductors.py Co-authored-by: clmould <86794332+clmould@users.noreply.github.com> --- process/models/superconductors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/process/models/superconductors.py b/process/models/superconductors.py index 6bfa0ac936..4e54142adf 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -150,8 +150,8 @@ def __new__( cls, value: int, material: SuperconductorMaterial, - b_crit_zero_temp_strain: float, - temp_crit_zero_field_strain: float, + b_crit_zero_temp_strain: float | None, + temp_crit_zero_field_strain: float | None, shape: SuperconductorShape, full_name: str, ): From a7ba28cf542867000bcf1c7fe71e55e985c1c5d8 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Jul 2026 14:45:48 +0100 Subject: [PATCH 8/8] Requested changes --- process/models/stellarator/coils/coils.py | 40 ++++++++++++++--------- process/models/superconductors.py | 6 ++-- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/process/models/stellarator/coils/coils.py b/process/models/stellarator/coils/coils.py index c2bc90c262..7e5a499f2f 100644 --- a/process/models/stellarator/coils/coils.py +++ b/process/models/stellarator/coils/coils.py @@ -39,9 +39,11 @@ def jcrit_from_material( ) # of a cable conductor. - if i_tf_sc_mat == 1: # ITER Nb3Sn critical surface parameterization - bc20m = 32.97 # these are values taken from sctfcoil.f90 - tc0m = 16.06 + if ( + i_tf_sc_mat == SuperconductorModel.ITER_NB3SN + ): # ITER Nb3Sn critical surface parameterization + bc20m = SuperconductorModel.ITER_NB3SN.b_crit_zero_field_strain + tc0m = SuperconductorModel.ITER_NB3SN.temp_crit_zero_field_strain # j_crit_sc returned by itersc is the critical current density in the # superconductor - not the whole strand, which contains copper @@ -60,7 +62,7 @@ def jcrit_from_material( j_crit_sc = max(1.0e-9, j_crit_sc) j_crit_cable = max(1.0e-9, j_crit_cable) - elif i_tf_sc_mat == 2: + elif i_tf_sc_mat == SuperconductorModel.BI2212: # Bi-2212 high temperature superconductor parameterization # Current density in a strand of Bi-2212 conductor # N.B. jcrit returned by bi2212 is the critical current density @@ -78,9 +80,9 @@ def jcrit_from_material( ) # bi2212 outputs j_crit_cable j_crit_sc = j_crit_cable / (1 - f_tf_conductor_copper) _tcrit = t_helium + tmarg - elif i_tf_sc_mat == 3: # NbTi data - bc20m = 15.0 - tc0m = 9.3 + elif i_tf_sc_mat == SuperconductorModel.OLD_LUBELL_NBTI: # NbTi data + bc20m = SuperconductorModel.OLD_LUBELL_NBTI.b_crit_zero_field_strain + tc0m = SuperconductorModel.OLD_LUBELL_NBTI.temp_crit_zero_field_strain c0 = 1.0 if b_max > bc20m: @@ -99,16 +101,18 @@ def jcrit_from_material( # This is needed right now. Can we change it later? j_crit_sc = max(1.0e-9, j_crit_sc) j_crit_cable = max(1.0e-9, j_crit_cable) - elif i_tf_sc_mat == 4: # As (1), but user-defined parameters + elif ( + i_tf_sc_mat == SuperconductorModel.USER_DEFINED_NB3SN + ): # As (1), but user-defined parameters bc20m = b_crit_sc tc0m = t_crit_sc j_crit_sc, _bcrit, _tcrit = superconductors.itersc( t_helium, b_max, strain, bc20m, tc0m ) j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he) - elif i_tf_sc_mat == 5: # WST Nb3Sn parameterisation - bc20m = 32.97 - tc0m = 16.06 + elif i_tf_sc_mat == SuperconductorModel.WST_NB3SN: # WST Nb3Sn parameterisation + bc20m = SuperconductorModel.WST_NB3SN.b_crit_zero_field_strain + tc0m = SuperconductorModel.WST_NB3SN.temp_crit_zero_field_strain # j_crit_sc returned by itersc is the critical current density in the # superconductor - not the whole strand, which contains copper @@ -122,12 +126,16 @@ def jcrit_from_material( ) j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he) - elif i_tf_sc_mat == 6: # ! "REBCO" 2nd generation HTS superconductor in CrCo strand + elif ( + i_tf_sc_mat == SuperconductorModel.CROCO_REBCO + ): # ! "REBCO" 2nd generation HTS superconductor in CrCo strand j_crit_sc, _validity, _, _ = superconductors.jcrit_rebco(t_helium, b_max, 0) j_crit_sc = max(1.0e-9, j_crit_sc) j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he) - elif i_tf_sc_mat == 7: # Durham Ginzburg-Landau Nb-Ti parameterisation + elif ( + i_tf_sc_mat == SuperconductorModel.DURHAM_NBTI + ): # Durham Ginzburg-Landau Nb-Ti parameterisation bc20m = SuperconductorModel.DURHAM_NBTI.b_crit_zero_field_strain tc0m = SuperconductorModel.DURHAM_NBTI.temp_crit_zero_field_strain j_crit_sc, _bcrit, _tcrit = superconductors.gl_nbti( @@ -135,9 +143,9 @@ def jcrit_from_material( ) j_crit_cable = j_crit_cable_from_fraction(j_crit_sc, f_tf_conductor_copper, f_he) - elif i_tf_sc_mat == 8: - bc20m = 429 - tc0m = 185 + elif i_tf_sc_mat == SuperconductorModel.DURHAM_REBCO: + bc20m = SuperconductorModel.DURHAM_REBCO.b_crit_zero_field_strain + tc0m = SuperconductorModel.DURHAM_REBCO.temp_crit_zero_field_strain j_crit_sc, _bcrit, _tcrit = superconductors.gl_rebco( t_helium, b_max, strain, bc20m, tc0m ) diff --git a/process/models/superconductors.py b/process/models/superconductors.py index 4e54142adf..9247d12550 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -84,7 +84,7 @@ class SuperconductorModel(IntEnum): BI2212 = ( 2, SuperconductorMaterial.BI2212, - None, + None, # Model is fitted to experimental data, so no critical B or T is defined None, SuperconductorShape.CABLE, "Bi-2212", @@ -100,8 +100,8 @@ class SuperconductorModel(IntEnum): USER_DEFINED_NB3SN = ( 4, SuperconductorMaterial.NB3SN, - None, - None, + None, # User input via `bcritsc` + None, # User input via `tcritsc` SuperconductorShape.CABLE, "User-defined ITER Nb₃Sn", )