From 7081a1e4663df405cd1663d4d72c751f7df56b72 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 10:26:25 +0100 Subject: [PATCH 01/20] Refactor superconducting model parameters to use SuperconductorModel enums for clarity --- process/models/tfcoil/superconducting.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 1af8bf61f1..4d6d22522b 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -2831,7 +2831,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # ITER Nb3Sn critical surface parameterization - if i_tf_superconductor == 1: + if i_tf_superconductor == SuperconductorModel.ITER_NB3SN: # Peak field and temperature at zero strain bc20m = 32.97e0 # [T] tc0m = 16.06e0 # [K] @@ -2872,7 +2872,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # Bi-2212 high temperature superconductor parameterization - elif i_tf_superconductor == 2: + elif i_tf_superconductor == SuperconductorModel.BI2212: # Current density in a strand of Bi-2212 conductor # N.B. jcrit returned by superconductors.bi2212 is the critical # current density in the strand, not just the superconducting portion. @@ -2903,7 +2903,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # NbTi data - elif i_tf_superconductor == 3: + elif i_tf_superconductor == SuperconductorModel.OLD_LUBELL_NBTI: bc20m = 15.0e0 # [T] tc0m = 9.3e0 # [K] c0 = 1.0e10 # [A/m2] @@ -2933,7 +2933,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # ITER Nb3Sn parameterization, but user-defined parameters - elif i_tf_superconductor == 4: + elif i_tf_superconductor == SuperconductorModel.USER_DEFINED_NB3SN: bc20m = bcritsc # [T] tc0m = tcritsc # [K] @@ -2969,7 +2969,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # WST Nb3Sn parameterisation - elif i_tf_superconductor == 5: + elif i_tf_superconductor == SuperconductorModel.WST_NB3SN: bc20m = 32.97e0 # [T] tc0m = 16.06e0 # [K] @@ -3010,7 +3010,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # "REBCO" 2nd generation HTS superconductor in CrCo strand - elif i_tf_superconductor == 6: + elif i_tf_superconductor == SuperconductorModel.CROCO_REBCO: raise ProcessValueError( "sctfcoil.supercon has been called but data.tfcoil.i_tf_sc_mat=6" ) @@ -3018,7 +3018,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # Durham Ginzburg-Landau Nb-Ti parameterisation - elif i_tf_superconductor == 7: + elif i_tf_superconductor == SuperconductorModel.DURHAM_NBTI: bc20m = data.tfcoil.b_crit_upper_nbti # [T] tc0m = data.tfcoil.t_crit_nbti # [K] @@ -3046,7 +3046,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # Durham Ginzburg-Landau critical surface model for REBCO - elif i_tf_superconductor == 8: + elif i_tf_superconductor == SuperconductorModel.DURHAM_REBCO: bc20m = 430 # [T] tc0m = 185 # [K] @@ -3087,7 +3087,7 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= # Hazelton experimental data + Zhai conceptual model for REBCO - elif i_tf_superconductor == 9: + elif i_tf_superconductor == SuperconductorModel.HAZELTON_ZHAI_REBCO: bc20m = 138 # [T] tc0m = 92 # [K] From 76621581e5bd22958acbf4809b98888b5fc1923a Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 10:44:26 +0100 Subject: [PATCH 02/20] Restrict TF coil turn calculations to cable superconductors only --- process/models/tfcoil/superconducting.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 4d6d22522b..800dc0ccb7 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -19,6 +19,7 @@ CroCoCableGeometry, SuperconductorMaterial, SuperconductorModel, + SuperconductorShape, calculate_croco_cable_geometry, ) from process.models.tfcoil import quench @@ -2815,6 +2816,17 @@ def tf_cable_in_conduit_superconductor_properties( (i.e., the copper in the superconducting strands and any additional copper, such as REBCO tape support). """ + if ( + SuperconductorModel(i_tf_superconductor).sc_shape + != SuperconductorShape.CABLE + ): + raise ProcessValueError( + "Cannot calculate cable in conduit superconductor properties for " + "non-cable superconductors. Change `i_tf_sc_mat` to a cable " + "superconductor or use a different TF coil class for non-cable " + "superconductors." + ) + # Guard against negative conductor fraction f_a_tf_turn_cable_space_conductor # Kludge to allow solver to continue and hopefully be constrained away # from this point @@ -3009,14 +3021,6 @@ def tf_cable_in_conduit_superconductor_properties( # ================================================================= - # "REBCO" 2nd generation HTS superconductor in CrCo strand - elif i_tf_superconductor == SuperconductorModel.CROCO_REBCO: - raise ProcessValueError( - "sctfcoil.supercon has been called but data.tfcoil.i_tf_sc_mat=6" - ) - - # ================================================================= - # Durham Ginzburg-Landau Nb-Ti parameterisation elif i_tf_superconductor == SuperconductorModel.DURHAM_NBTI: bc20m = data.tfcoil.b_crit_upper_nbti # [T] From 2a3f79a6ce008af747cb7302daa45ccc8c448b30 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 11:19:54 +0100 Subject: [PATCH 03/20] Initialize conductor parameters in SuperconductingTFData with default values --- .../superconducting_tf_coil_variables.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index 9603342fbb..e3e40ce716 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -254,22 +254,22 @@ class SuperconductingTFData: # conductor - a_tf_turn_croco_cable_space_copper: float = None - conductor_copper_fraction: float = None - a_tf_turn_croco_copper_bar: float = None + a_tf_turn_croco_cable_space_copper: float = 0.0 + conductor_copper_fraction: float = 0.0 + a_tf_turn_croco_copper_bar: float = 0.0 """Area of the central copper strand in the CroCo TF turn [m²]""" - a_tf_turn_croco_hastelloy: float = None - conductor_hastelloy_fraction: float = None - conductor_helium_area: float = None - conductor_helium_fraction: float = None - conductor_solder_area: float = None - conductor_solder_fraction: float = None - conductor_jacket_area: float = None - conductor_jacket_fraction: float = None - conductor_rebco_area: float = None - conductor_rebco_fraction: float = None - conductor_critical_current: float = None - conductor_area: float = None + a_tf_turn_croco_hastelloy: float = 0.0 + conductor_hastelloy_fraction: float = 0.0 + conductor_helium_area: float = 0.0 + conductor_helium_fraction: float = 0.0 + conductor_solder_area: float = 0.0 + conductor_solder_fraction: float = 0.0 + conductor_jacket_area: float = 0.0 + conductor_jacket_fraction: float = 0.0 + conductor_rebco_area: float = 0.0 + conductor_rebco_fraction: float = 0.0 + conductor_critical_current: float = 0.0 + conductor_area: float = 0.0 """Area of cable space inside jacket""" t1: float = 0.0 From b8ae8e9ee48614d70b65a707ffdc52bd3c4dbeef Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 11:33:29 +0100 Subject: [PATCH 04/20] Refactor CROCOSuperconductingTFCoil to streamline superconductor property calculations and remove deprecated models --- process/models/tfcoil/superconducting.py | 319 +++++++++++++---------- 1 file changed, 184 insertions(+), 135 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 800dc0ccb7..6430840c9a 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3049,86 +3049,6 @@ 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] - - # If strain limit achieved, throw a warning and use the lower strain - if abs(strain) > 0.7e-2: - logger.error( - f"TF strain={strain} was outside the region of applicability. " - f"Used lower strain." - ) - strain = np.sign(strain) * 0.7e-2 - - j_superconductor_critical, _, _ = superconductors.gl_rebco( - temp_conductor=temp_tf_coolant_peak_field, - b_conductor=b_tf_inboard_peak, - strain=strain, - b_c20max=bc20m, - t_c0=tc0m, - ) - # Scale for the copper area fraction of the cable - j_cables_critical = j_superconductor_critical * ( - 1.0e0 - f_a_tf_turn_cable_copper - ) - - # Critical current in turn all turn cables - c_turn_cables_critical = j_cables_critical * a_tf_turn_cable_space_effective - - # Strand critical current calulation for costing in $ / kAm - # Already includes buffer and support layers so no need to include - # f_a_tf_turn_cable_copper here - data.tfcoil.j_crit_str_tf = j_superconductor_critical - - # REBCO measurements from 2 T to 14 T, extrapolating outside this - if (b_tf_inboard_peak) >= 14.0: - logger.error( - "Field on superconductor > 14 T (outside of interpolation range)" - ) - - # ================================================================= - - # Hazelton experimental data + Zhai conceptual model for REBCO - elif i_tf_superconductor == SuperconductorModel.HAZELTON_ZHAI_REBCO: - bc20m = 138 # [T] - tc0m = 92 # [K] - - # If strain limit achieved, throw a warning and use the lower strain - if abs(strain) > 0.7e-2: - logger.error( - f"TF strain={strain} was outside the region of applicability. " - f"Used lower strain." - ) - strain = np.sign(strain) * 0.7e-2 - - # 'high current density' as per parameterisation described in Wolf, - # and based on Hazelton experimental data and Zhai conceptual model; - # see subroutine for full references - j_superconductor_critical, _, _ = superconductors.hijc_rebco( - temp_conductor=temp_tf_coolant_peak_field, - b_conductor=b_tf_inboard_peak, - b_c20max=bc20m, - t_c0=tc0m, - dr_hts_tape=data.superconducting_tfcoil.dr_tf_hts_tape, - dx_hts_tape_rebco=data.superconducting_tfcoil.dx_tf_hts_tape_rebco, - dx_hts_tape_total=data.superconducting_tfcoil.dx_tf_hts_tape_total, - ) - # Scale for the copper area fraction of the cable - j_cables_critical = j_superconductor_critical * ( - 1.0e0 - f_a_tf_turn_cable_copper - ) - - # Critical current in turn all turn cables - c_turn_cables_critical = j_cables_critical * a_tf_turn_cable_space_effective - - # Strand critical current calulation for costing in $ / kAm - # = superconducting filaments jc * (1 -strand copper fraction) - data.tfcoil.j_crit_str_tf = j_superconductor_critical * ( - 1.0e0 - f_a_tf_turn_cable_copper - ) - else: raise ProcessValueError( "Illegal value for i_tf_sc_mat", i_tf_superconductor=i_tf_superconductor @@ -4094,44 +4014,43 @@ def run(self, output: bool = False): * self.data.tfcoil.n_tf_coil_turns ) - if ( - SuperconductorModel(self.data.tfcoil.i_tf_sc_mat) - == SuperconductorModel.CROCO_REBCO - ): - superconductor_critical_properties: TFSuperconductorLimits = ( - self.tf_croco_superconductor_properties( - a_tf_turn=self.data.tfcoil.a_tf_turn, - b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple, - cur_tf_turn=self.data.tfcoil.c_tf_turn, - temp_tf_peak=self.data.tfcoil.tftmp, - ) - ) + superconductor_critical_properties: TFSuperconductorLimits = self.tf_croco_superconductor_properties( + a_tf_turn=self.data.tfcoil.a_tf_turn, + b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple, + cur_tf_turn=self.data.tfcoil.c_tf_turn, + temp_tf_peak=self.data.tfcoil.tftmp, + a_tf_turn_cable_space_effective=self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective, + i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat, + dr_tf_hts_tape=self.data.superconducting_tfcoil.dr_tf_hts_tape, + dx_tf_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco, + dx_tf_hts_tape_total=self.data.superconducting_tfcoil.dx_tf_hts_tape_total, + ) - self.data.tfcoil.j_tf_wp_critical = ( - superconductor_critical_properties.j_tf_wp_critical - ) - self.data.superconducting_tfcoil.j_tf_superconductor_critical = ( - superconductor_critical_properties.j_superconductor_critical - ) - self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical = ( - superconductor_critical_properties.f_c_tf_turn_operating_critical - ) - self.data.superconducting_tfcoil.j_tf_superconductor = ( - superconductor_critical_properties.j_superconductor - ) - self.data.superconducting_tfcoil.j_tf_coil_turn = ( - superconductor_critical_properties.j_tf_coil_turn - ) + self.data.tfcoil.j_tf_wp_critical = ( + superconductor_critical_properties.j_tf_wp_critical + ) + self.data.superconducting_tfcoil.j_tf_superconductor_critical = ( + superconductor_critical_properties.j_superconductor_critical + ) + self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical = ( + superconductor_critical_properties.f_c_tf_turn_operating_critical + ) + self.data.superconducting_tfcoil.j_tf_superconductor = ( + superconductor_critical_properties.j_superconductor + ) + self.data.superconducting_tfcoil.j_tf_coil_turn = ( + superconductor_critical_properties.j_tf_coil_turn + ) - self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain = superconductor_critical_properties.bc20m - self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain = superconductor_critical_properties.tc0m - self.data.superconducting_tfcoil.c_tf_turn_cables_critical = ( - superconductor_critical_properties.c_turn_cables_critical - ) + self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain = superconductor_critical_properties.bc20m + self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain = superconductor_critical_properties.tc0m + self.data.superconducting_tfcoil.c_tf_turn_cables_critical = ( + superconductor_critical_properties.c_turn_cables_critical + ) - self.data.tfcoil.v_tf_coil_dump_quench_kv = ( - self.croco_voltage() / 1.0e3 - ) # TFC Quench voltage in kV + self.data.tfcoil.v_tf_coil_dump_quench_kv = ( + self.croco_voltage() / 1.0e3 + ) # TFC Quench voltage in kV # Negative areas or fractions error reporting if ( @@ -4537,34 +4456,160 @@ def tf_croco_superconductor_properties( b_tf_inboard_peak: float, cur_tf_turn: float, temp_tf_peak: float, + a_tf_turn_cable_space_effective: float, + i_tf_superconductor: int, + dr_tf_hts_tape: float, + dx_tf_hts_tape_rebco: float, + dx_tf_hts_tape_total: float, ) -> TFSuperconductorLimits: """TF superconducting CroCo conductor using REBCO tape Parameters ---------- a_tf_turn : - + Cross-sectional area of the TF turn (m²) b_tf_inboard_peak : Peak field at conductor (T) cur_tf_turn : Operating current per turn (A) temp_tf_peak : - He temperature at peak field point (K) + Coil temperature at peak field point (K) + a_tf_turn_cable_space_effective : + Effective cross-sectional area of the TF turn cable space (m²) + i_tf_superconductor : + Integer identifier for the superconductor material model to use. + dr_tf_hts_tape : + Thickness of the HTS tape (m) + dx_tf_hts_tape_rebco : + Width of the REBCO layer in the HTS tape (m) + dx_tf_hts_tape_total : + Total width of the HTS tape (m) + + Returns + ------- + TFSuperconductorLimits + A dataclass containing the calculated superconducting properties of the TF coil, including: + - j_tf_wp_critical: Critical current density in the TF winding pack (A/m²). + - j_superconductor_critical: Critical current density in the superconductor (A/m²). + - f_c_tf_turn_operating_critical: Ratio of operating current to critical current for the TF turn (dimensionless). + - j_tf_superconductor: Current density in the superconductor at operating conditions (A/m²). + - j_tf_coil_turn: Current density in the TF coil turn at operating conditions (A/m²). + - bc20m: Critical magnetic field at 20 K and zero strain (T). + - tc0m: Critical temperature at zero magnetic field and zero strain (K). + - c_turn_cables_critical: Critical current in the TF turn cables (A). """ - # Find critical current density in superconducting cable, j_crit_cable - j_crit_sc, _, bc20m, tc0m = superconductors.jcrit_rebco( - temp_conductor=temp_tf_peak, b_conductor=b_tf_inboard_peak - ) + if SuperconductorModel(i_tf_superconductor).sc_shape != SuperconductorShape.TAPE: + raise ProcessValueError( + "Cannot calculate tape superconductor properties for " + "non-tape superconductors. Change `i_tf_sc_mat` to a tape " + "superconductor or use a different TF coil class for non-tape " + "superconductors." + ) + + if self.data.tfcoil.i_str_wp == 0: + strain = self.data.tfcoil.str_tf_con_res + else: + strain = self.data.tfcoil.str_wp + + f_a_tf_turn_tape_superconductor = dx_tf_hts_tape_rebco / dx_tf_hts_tape_total + + # ================================================================= + + if i_tf_superconductor == SuperconductorModel.CROCO_REBCO: + # Find critical current density in superconducting cable, j_crit_cable + j_superconductor_critical, _, bc20m, tc0m = superconductors.jcrit_rebco( + temp_conductor=temp_tf_peak, b_conductor=b_tf_inboard_peak + ) + + # ================================================================= + + # Durham Ginzburg-Landau critical surface model for REBCO + elif i_tf_superconductor == SuperconductorModel.DURHAM_REBCO: + bc20m = 430 # [T] + tc0m = 185 # [K] + + # If strain limit achieved, throw a warning and use the lower strain + if abs(strain) > 0.7e-2: + logger.error( + f"TF strain={strain} was outside the region of applicability. " + f"Used lower strain." + ) + strain = np.sign(strain) * 0.7e-2 + + j_superconductor_critical, _, _ = superconductors.gl_rebco( + temp_conductor=temp_tf_peak, + b_conductor=b_tf_inboard_peak, + strain=strain, + b_c20max=bc20m, + t_c0=tc0m, + ) + # Scale for the copper area fraction of the cable + j_tape_critical = j_superconductor_critical * f_a_tf_turn_tape_superconductor + + # Critical current in turn all turn cables + c_turn_cables_critical = j_tape_critical * a_tf_turn_cable_space_effective + + # Strand critical current calulation for costing in $ / kAm + # Already includes buffer and support layers so no need to include + # f_a_tf_turn_cable_copper here + self.data.tfcoil.j_crit_str_tf = j_superconductor_critical + + # REBCO measurements from 2 T to 14 T, extrapolating outside this + if (b_tf_inboard_peak) >= 14.0: + logger.error( + "Field on superconductor > 14 T (outside of interpolation range)" + ) + + # ================================================================= + + # Hazelton experimental data + Zhai conceptual model for REBCO + elif i_tf_superconductor == SuperconductorModel.HAZELTON_ZHAI_REBCO: + bc20m = 138 # [T] + tc0m = 92 # [K] - self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical = ( - j_crit_sc * self.data.superconducting_tfcoil.a_tf_croco_strand + # If strain limit achieved, throw a warning and use the lower strain + if abs(strain) > 0.7e-2: + logger.error( + f"TF strain={strain} was outside the region of applicability. " + f"Used lower strain." + ) + strain = np.sign(strain) * 0.7e-2 + + # 'high current density' as per parameterisation described in Wolf, + # and based on Hazelton experimental data and Zhai conceptual model; + # see subroutine for full references + j_superconductor_critical, _, _ = superconductors.hijc_rebco( + temp_conductor=temp_tf_peak, + b_conductor=b_tf_inboard_peak, + b_c20max=bc20m, + t_c0=tc0m, + dr_hts_tape=dr_tf_hts_tape, + dx_hts_tape_rebco=dx_tf_hts_tape_rebco, + dx_hts_tape_total=dx_tf_hts_tape_total, + ) + # Scale for the copper area fraction of the cable + j_tape_critical = j_superconductor_critical * f_a_tf_turn_tape_superconductor + + # Critical current in turn all turn cables + c_turn_cables_critical = j_tape_critical * a_tf_turn_cable_space_effective + + # Strand critical current calulation for costing in $ / kAm + # = superconducting filaments jc * (1 -strand copper fraction) + self.data.tfcoil.j_crit_str_tf = ( + j_superconductor_critical * f_a_tf_turn_tape_superconductor + ) + + # ================================================================= + + cur_tf_turn_croco_strand_critical = ( + j_superconductor_critical + * self.data.superconducting_tfcoil.a_tf_croco_strand ) # Conductor properties self.data.superconducting_tfcoil.conductor_critical_current = ( - self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical - * N_CROCO_STRANDS_TURN + cur_tf_turn_croco_strand_critical * N_CROCO_STRANDS_TURN ) self.data.superconducting_tfcoil.tf_coppera_m2 = ( @@ -4577,18 +4622,22 @@ def tf_croco_superconductor_properties( # Critical current density in winding pack # a_tf_turn : Area per turn (i.e. entire jacketed conductor with insulation) (m2) j_tf_wp_critical = cur_critical / a_tf_turn + # Ratio of operating / critical current - iooic = cur_tf_turn / cur_critical + f_c_tf_turn_operating_critical = cur_tf_turn / cur_critical + # Operating current density - jwdgop = cur_tf_turn / a_tf_turn + j_tf_coil_turn = cur_tf_turn / a_tf_turn + # Actual current density in superconductor, # which should be equal to jcrit(thelium+tmarg) - # when we have found the desired value of tmarg - jsc = iooic * j_crit_sc + j_superconductor = f_c_tf_turn_operating_critical * j_superconductor_critical # Temperature margin - current_sharing_t = superconductors.current_sharing_rebco(b_tf_inboard_peak, jsc) + current_sharing_t = superconductors.current_sharing_rebco( + b_tf_inboard_peak, j_superconductor + ) tmarg = current_sharing_t - temp_tf_peak self.data.tfcoil.temp_margin = ( tmarg # Only used in the availabilty routine - see comment to Issue #526 @@ -4596,13 +4645,13 @@ def tf_croco_superconductor_properties( return TFSuperconductorLimits( j_tf_wp_critical=j_tf_wp_critical, - j_superconductor_critical=j_crit_sc, - f_c_tf_turn_operating_critical=iooic, - j_superconductor=jsc, - j_tf_coil_turn=jwdgop, + j_superconductor_critical=j_superconductor_critical, + f_c_tf_turn_operating_critical=f_c_tf_turn_operating_critical, + j_superconductor=j_superconductor, + j_tf_coil_turn=j_tf_coil_turn, bc20m=bc20m, tc0m=tc0m, - c_turn_cables_critical=self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical, + c_turn_cables_critical=cur_tf_turn_croco_strand_critical, ) @staticmethod From 1706b77efcb5a80def42f0f9d69dd75027a0bf05 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 12:03:20 +0100 Subject: [PATCH 05/20] Refactor CROCOSuperconductingTFCoil to optimize critical current calculations and improve code clarity --- process/models/tfcoil/superconducting.py | 42 +++++++++--------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 6430840c9a..3b2f6dbd30 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -4544,22 +4544,6 @@ def tf_croco_superconductor_properties( b_c20max=bc20m, t_c0=tc0m, ) - # Scale for the copper area fraction of the cable - j_tape_critical = j_superconductor_critical * f_a_tf_turn_tape_superconductor - - # Critical current in turn all turn cables - c_turn_cables_critical = j_tape_critical * a_tf_turn_cable_space_effective - - # Strand critical current calulation for costing in $ / kAm - # Already includes buffer and support layers so no need to include - # f_a_tf_turn_cable_copper here - self.data.tfcoil.j_crit_str_tf = j_superconductor_critical - - # REBCO measurements from 2 T to 14 T, extrapolating outside this - if (b_tf_inboard_peak) >= 14.0: - logger.error( - "Field on superconductor > 14 T (outside of interpolation range)" - ) # ================================================================= @@ -4588,19 +4572,25 @@ def tf_croco_superconductor_properties( dx_hts_tape_rebco=dx_tf_hts_tape_rebco, dx_hts_tape_total=dx_tf_hts_tape_total, ) - # Scale for the copper area fraction of the cable - j_tape_critical = j_superconductor_critical * f_a_tf_turn_tape_superconductor - # Critical current in turn all turn cables - c_turn_cables_critical = j_tape_critical * a_tf_turn_cable_space_effective + # ================================================================= - # Strand critical current calulation for costing in $ / kAm - # = superconducting filaments jc * (1 -strand copper fraction) - self.data.tfcoil.j_crit_str_tf = ( - j_superconductor_critical * f_a_tf_turn_tape_superconductor - ) + # Scale for the copper area fraction of the cable + j_tape_critical = j_superconductor_critical * f_a_tf_turn_tape_superconductor - # ================================================================= + # Critical current in turn all turn cables + c_turn_cables_critical = j_tape_critical * a_tf_turn_cable_space_effective + + # Strand critical current calulation for costing in $ / kAm + # Already includes buffer and support layers so no need to include + # f_a_tf_turn_cable_copper here + self.data.tfcoil.j_crit_str_tf = j_superconductor_critical + + # REBCO measurements from 2 T to 14 T, extrapolating outside this + if (b_tf_inboard_peak) >= 14.0: + logger.error( + "Field on superconductor > 14 T (outside of interpolation range)" + ) cur_tf_turn_croco_strand_critical = ( j_superconductor_critical From 07d2cd2af1d74627843d82f2adeb1cb8d82b60aa Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 13:42:41 +0100 Subject: [PATCH 06/20] Enhance TF coil plots by adding critical current density and field information --- process/core/io/plot/summary.py | 4 ++++ process/models/superconductors.py | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index f70c1bb1cc..5afbb706ad 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -7498,6 +7498,8 @@ def _pack_strands_rectangular_with_obstacles( f"Critical field at zero \ntemperature and strain: {mfile.get('b_tf_superconductor_critical_zero_temp_strain', scan=scan):.4f} T\n" f"Critical temperature at \nzero field and strain: {mfile.get('temp_tf_superconductor_critical_zero_field_strain', scan=scan):.4f} K\n" f"Temperature at conductor: {mfile.get('tftmp', scan=scan):.4f} K\n" + f"Field at conductor: {mfile.get('b_tf_inboard_peak_with_ripple', scan=scan):.4f} T\n" + f"Superconductor critical current density at \noperating conditions: {mfile.get('j_tf_superconductor_critical', scan=scan):.2e} A/m$^2$\n" f"$I_{{\\text{{TF,turn critical}}}}$: {mfile.get('c_turn_cables_critical', scan=scan):,.2f} A\n" f"$I_{{\\text{{TF,turn}}}}$: {mfile.get('c_tf_turn', scan=scan):,.2f} A\n" f"Critcal current ratio: {mfile.get('f_c_tf_turn_operating_critical', scan=scan):,.4f}\n" @@ -7776,6 +7778,8 @@ def plot_tf_croco_turn(axis: plt.Axes, fig, mfile: MFile, scan: int): f"Critical field at zero \ntemperature and strain: {mfile.get('b_tf_superconductor_critical_zero_temp_strain', scan=scan):.4f} T\n" f"Critical temperature at \nzero field and strain: {mfile.get('temp_tf_superconductor_critical_zero_field_strain', scan=scan):.4f} K\n" f"Temperature at conductor: {mfile.get('tftmp', scan=scan):.4f} K\n" + f"Field at conductor: {mfile.get('b_tf_inboard_peak_with_ripple', scan=scan):.4f} T\n" + f"Superconductor critical current density at \noperating conditions: {mfile.get('j_tf_superconductor_critical', scan=scan):.2e} A/m$^2$\n" f"$I_{{\\text{{TF,turn critical}}}}$: {mfile.get('c_turn_cables_critical', scan=scan):,.2f} A\n" f"$I_{{\\text{{TF,turn}}}}$: {mfile.get('c_tf_turn', scan=scan):,.2f} A\n" f"Critcal current ratio: {mfile.get('f_c_tf_turn_operating_critical', scan=scan):,.4f}\n" diff --git a/process/models/superconductors.py b/process/models/superconductors.py index 6e38d73330..67f4ecddef 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -809,34 +809,34 @@ def hijc_rebco( # finding A(T); constants based on a Newton polynomial fit to pubished data a_t = a_0 + (u * temp_conductor**2) + (v * temp_conductor) - # Critical current density (A/m2) + # Critical current # In the original formula bcrit must be > bmax to prevent NaNs. # However, negative jcrit is permissible (I think). # So when bcrit < bmax, I reverse the sign of the bracket, # giving a negative but real value of jcrit. if b_critical > b_conductor: - j_critical = ( + cur_critical = ( (a_t / b_conductor) * b_critical**b * (b_conductor / b_critical) ** p * (1 - b_conductor / b_critical) ** q ) else: - j_critical = ( + cur_critical = ( (a_t / b_conductor) * b_critical**b * (b_conductor / b_critical) ** p * (b_conductor / b_critical - 1) ** q ) - # Jc times HTS area: default area is width 4mm times HTS layer thickness 1 um, + # Critical current times HTS area: default area is width 4mm times HTS layer thickness 1 um, # divided by the tape area to provide engineering Jc per tape,! # A scaling factor of 0.4 used to be applied below to assume the difference # between tape stacks and CORC cable layouts. j_critical = ( - j_critical + cur_critical * (dr_hts_tape * dx_hts_tape_rebco) / (dr_hts_tape * dx_hts_tape_total) ) From 7dcd5d5685557af847bf5d18d1efb9ab9c2c62cf Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 14:03:23 +0100 Subject: [PATCH 07/20] Add output for peak inboard toroidal field with ripple in SuperconductingTFCoil --- process/models/tfcoil/superconducting.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 3b2f6dbd30..7994ab2712 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -877,6 +877,13 @@ def output_tf_superconductor_info(self): "(tftmp)", self.data.tfcoil.tftmp, ) + po.ovarre( + self.outfile, + "Peak inboard toroidal field including ripple (T)", + "(b_tf_inboard_peak_with_ripple)", + self.data.tfcoil.b_tf_inboard_peak_with_ripple, + ) + po.oblnkl(self.outfile) po.ovarre( self.outfile, "Total cooling area fraction inside cable space", From cad313613fc88d952a5063ac366415b4731a4381 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:04:10 +0100 Subject: [PATCH 08/20] Add copper area calculations and update related attributes in CROCOSuperconductingTFCoil --- .../superconducting_tf_coil_variables.py | 11 +++- process/models/tfcoil/superconducting.py | 56 +++++++++---------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index e3e40ce716..4a23f8e78b 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -255,9 +255,18 @@ class SuperconductingTFData: # conductor a_tf_turn_croco_cable_space_copper: float = 0.0 - conductor_copper_fraction: float = 0.0 + """Area of the copper in the CroCo cable space of the TF turn (includes tapes, + outer tube and central copper) (m²)""" + + a_tf_turn_copper_total: float = 0.0 + """Area of all copper in the TF turn (m²)""" + + f_a_tf_turn_copper: float = 0.0 + """Fraction of the TF turn area that is copper (m²)""" + a_tf_turn_croco_copper_bar: float = 0.0 """Area of the central copper strand in the CroCo TF turn [m²]""" + a_tf_turn_croco_hastelloy: float = 0.0 conductor_hastelloy_fraction: float = 0.0 conductor_helium_area: float = 0.0 diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 7994ab2712..a0fec86d65 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3972,9 +3972,25 @@ def run(self, output: bool = False): * N_CROCO_STRANDS_TURN + self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar ) - self.data.superconducting_tfcoil.conductor_copper_fraction = ( + + self.data.superconducting_tfcoil.a_tf_turn_copper_total = ( self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper - / self.data.superconducting_tfcoil.conductor_area + ) + + self.data.superconducting_tfcoil.f_a_tf_turn_copper = ( + self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper + / self.data.tfcoil.a_tf_turn + ) + + self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling = ( + self.data.tfcoil.a_tf_turn_cable_space_no_void + - ( + ( + N_CROCO_STRANDS_TURN + * self.data.superconducting_tfcoil.a_tf_croco_strand + ) + - self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar + ) ) # Helium area is set by the user. @@ -4031,6 +4047,7 @@ def run(self, output: bool = False): dr_tf_hts_tape=self.data.superconducting_tfcoil.dr_tf_hts_tape, dx_tf_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco, dx_tf_hts_tape_total=self.data.superconducting_tfcoil.dx_tf_hts_tape_total, + a_tf_croco_strand=self.data.superconducting_tfcoil.a_tf_croco_strand, ) self.data.tfcoil.j_tf_wp_critical = ( @@ -4468,6 +4485,7 @@ def tf_croco_superconductor_properties( dr_tf_hts_tape: float, dx_tf_hts_tape_rebco: float, dx_tf_hts_tape_total: float, + a_tf_croco_strand: float, ) -> TFSuperconductorLimits: """TF superconducting CroCo conductor using REBCO tape @@ -4599,10 +4617,7 @@ def tf_croco_superconductor_properties( "Field on superconductor > 14 T (outside of interpolation range)" ) - cur_tf_turn_croco_strand_critical = ( - j_superconductor_critical - * self.data.superconducting_tfcoil.a_tf_croco_strand - ) + cur_tf_turn_croco_strand_critical = j_superconductor_critical * a_tf_croco_strand # Conductor properties self.data.superconducting_tfcoil.conductor_critical_current = ( @@ -4858,27 +4873,6 @@ def output_croco_info(self) -> None: self.data.superconducting_tfcoil.a_tf_croco_strand_solder, "OP ", ) - po.ovarre( - self.outfile, - "Total: area of CroCo strand (m²) ", - "(a_tf_croco_strand)", - self.data.superconducting_tfcoil.a_tf_croco_strand, - "OP ", - ) - if ( - abs( - self.data.superconducting_tfcoil.a_tf_croco_strand - - ( - self.data.superconducting_tfcoil.a_tf_croco_strand_rebco - + self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total - + self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy - + self.data.superconducting_tfcoil.a_tf_croco_strand_solder - ) - ) - > 1e-6 - ): - po.ocmmnt(self.outfile, "ERROR: Areas in CroCo strand do not add up") - logger.error("Areas in CroCo strand do not add up - see OUT.DAT") po.oblnkl(self.outfile) po.ocmmnt(self.outfile, "Cable information") @@ -4911,7 +4905,7 @@ def output_croco_info(self) -> None: po.ovarre( self.outfile, "Area of conductor (m²)", - "(area)", + "(conductor_area)", self.data.superconducting_tfcoil.conductor_area, "OP ", ) @@ -4925,21 +4919,21 @@ def output_croco_info(self) -> None: po.ovarre( self.outfile, "Area of central copper bar (m²)", - "(copper_bar_area)", + "(a_tf_turn_croco_copper_bar)", self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar, "OP ", ) po.ovarre( self.outfile, "Total copper area of conductor, total (m²)", - "(a_tf_croco_strand_copper_total)", + "(a_tf_turn_croco_cable_space_copper)", self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper, "OP ", ) po.ovarre( self.outfile, "Hastelloy area of conductor (m²)", - "(a_tf_croco_strand_hastelloy)", + "(a_tf_turn_croco_hastelloy)", self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy, "OP ", ) From bda71537ebbb9139f8d8cf99bb79561b2f78a8d9 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:15:25 +0100 Subject: [PATCH 09/20] Refactor CROCOSuperconductingTFCoil to remove unused helium area calculations and add fraction of superconducting material area --- .../superconducting_tf_coil_variables.py | 10 ++++----- process/models/tfcoil/superconducting.py | 21 ++----------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index 4a23f8e78b..db11bbfe77 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -246,14 +246,9 @@ class SuperconductingTFData: a_tf_croco_strand: float = 0.0 """Total area of a CroCo strand (m²)""" - # croco_strand - - tf_croco_strand_area: float = 0.0 cur_tf_turn_croco_strand_critical: float = 0.0 """Critical current in the TF turn CroCo strand (A)""" - # conductor - a_tf_turn_croco_cable_space_copper: float = 0.0 """Area of the copper in the CroCo cable space of the TF turn (includes tapes, outer tube and central copper) (m²)""" @@ -267,7 +262,12 @@ class SuperconductingTFData: a_tf_turn_croco_copper_bar: float = 0.0 """Area of the central copper strand in the CroCo TF turn [m²]""" + f_a_tf_turn_superconductor: float = 0.0 + """Fraction of the TF turn area that is superconducting material [m²]""" + a_tf_turn_croco_hastelloy: float = 0.0 + """Area of the Hastelloy in the CroCo cable space of the TF turn (includes tapes and outer tube) (m²)""" + conductor_hastelloy_fraction: float = 0.0 conductor_helium_area: float = 0.0 conductor_helium_fraction: float = 0.0 diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index a0fec86d65..4e940660ce 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3991,17 +3991,7 @@ def run(self, output: bool = False): ) - self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar ) - ) - - # Helium area is set by the user. - # conductor_helium_area = cable_helium_fraction * self.data.tfcoil.a_tf_turn_cable_space_no_void - self.data.superconducting_tfcoil.conductor_helium_area = ( - np.pi / 2.0 * self.data.superconducting_tfcoil.dia_tf_turn_croco_cable**2 - ) - self.data.superconducting_tfcoil.conductor_helium_fraction = ( - self.data.superconducting_tfcoil.conductor_helium_area - / self.data.superconducting_tfcoil.conductor_area - ) + ) / self.data.tfcoil.a_tf_turn_cable_space_no_void self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy = ( self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy @@ -4025,7 +4015,7 @@ def run(self, output: bool = False): self.data.superconducting_tfcoil.a_tf_croco_strand_rebco * N_CROCO_STRANDS_TURN ) - self.data.superconducting_tfcoil.conductor_rebco_fraction = ( + self.data.superconducting_tfcoil.f_a_tf_turn_superconductor = ( self.data.superconducting_tfcoil.conductor_rebco_area / self.data.superconducting_tfcoil.conductor_area ) @@ -4951,13 +4941,6 @@ def output_croco_info(self) -> None: self.data.superconducting_tfcoil.conductor_jacket_area, "OP ", ) - po.ovarre( - self.outfile, - "Helium area of conductor (m²)", - "(helium_area)", - self.data.superconducting_tfcoil.conductor_helium_area, - "OP ", - ) po.ovarre( self.outfile, From eed150b09f37b2248c6debb1fac6297b4da4a583 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:36:42 +0100 Subject: [PATCH 10/20] Refactor CROCOSuperconductingTFCoil to update conductor area calculations and remove unused void area logic --- process/models/tfcoil/superconducting.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 4e940660ce..67a1f3ef1a 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3830,15 +3830,6 @@ def run(self, output: bool = False): # No central channel in CroCo conductor, self.data.tfcoil.a_tf_wp_coolant_channels = 0.0 - # Total conductor cross-sectional area, taking account of void area - # and central helium channel [m²] - self.data.tfcoil.a_tf_wp_conductor = ( - self.data.tfcoil.a_tf_turn_cable_space_no_void - * self.data.tfcoil.n_tf_coil_turns - * (1.0e0 - self.data.tfcoil.f_a_tf_turn_cable_space_extra_void) - - self.data.tfcoil.a_tf_wp_coolant_channels - ) - # Void area in conductor for He, not including central channel [m²] self.data.tfcoil.a_tf_wp_extra_void = ( self.data.tfcoil.a_tf_turn_cable_space_no_void @@ -3973,6 +3964,12 @@ def run(self, output: bool = False): + self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar ) + # Total conductor cross-sectional area, taking account of void area + # and central helium channel [m²] + self.data.tfcoil.a_tf_wp_conductor = ( + N_CROCO_STRANDS_TURN * self.data.superconducting_tfcoil.a_tf_croco_strand + ) * self.data.tfcoil.n_tf_coil_turns + self.data.superconducting_tfcoil.a_tf_turn_copper_total = ( self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper ) From d38bb9d5484add867c985620f005d664f4832a94 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:46:28 +0100 Subject: [PATCH 11/20] Refactor TF coil variables to rename conductor width to conduit full average and update related calculations --- process/core/io/obsolete_vars.py | 2 +- process/data_structure/tfcoil_variables.py | 4 +- process/models/tfcoil/superconducting.py | 92 +++++++++++++--------- tests/unit/models/tfcoil/test_sctfcoil.py | 20 ++--- 4 files changed, 67 insertions(+), 51 deletions(-) diff --git a/process/core/io/obsolete_vars.py b/process/core/io/obsolete_vars.py index 9afa1ff419..63b22407fd 100644 --- a/process/core/io/obsolete_vars.py +++ b/process/core/io/obsolete_vars.py @@ -48,7 +48,7 @@ "thkwp": "dr_tf_wp_with_insulation", "leni": "dx_tf_turn_cable_space_average", "leno": "t_turn", - "conductor_width": "t_conductor", + "conductor_width": "dx_tf_turn_conduit_full_average", "deltf": "dr_tf_shld_gap", "ddwi": "dr_vv_outboard", "pnuccp": "pnuc_cp", diff --git a/process/data_structure/tfcoil_variables.py b/process/data_structure/tfcoil_variables.py index c01a16cbb1..dc7e6f7f92 100644 --- a/process/data_structure/tfcoil_variables.py +++ b/process/data_structure/tfcoil_variables.py @@ -95,8 +95,8 @@ class TFData: tfc_sidewall_is_fraction: bool = False """logical switch to make dx_tf_side_case_min a fraction of TF coil thickness (`casths_fraction`)""" - t_conductor: float = 0.0 - """Conductor (cable + steel conduit) area averaged dimension [m]""" + dx_tf_turn_conduit_full_average: float = 0.0 + """Average full width of the conduit surrounding the TF turn cable space [m]""" dx_tf_turn_general: float = 0.0 """TF coil turn edge length including turn insulation [m] diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 67a1f3ef1a..abe68095d8 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -600,14 +600,14 @@ def output_general_superconducting_tf_info(self) -> None: ) po.ovarre( self.outfile, - "Width of conductor (square) (m)", - "(t_conductor)", - self.data.tfcoil.t_conductor, + "Width of conduit surrounding cable space (square) (m)", + "(dx_tf_turn_conduit_full_average)", + self.data.tfcoil.dx_tf_turn_conduit_full_average, "OP ", ) po.ovarre( self.outfile, - "Width of space inside conductor (m)", + "Width of cable space inside conduit (m)", "(dx_tf_turn_cable_space_average)", self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average, "OP ", @@ -2217,7 +2217,7 @@ class CICCAveragedTurnGeometry: dx_tf_turn_general: float dr_tf_turn: float dx_tf_turn: float - t_conductor: float + dx_tf_turn_conduit_full_average: float radius_tf_turn_cable_space_corners: float dx_tf_turn_cable_space_average: float a_tf_turn_cable_space_effective: float @@ -2238,7 +2238,7 @@ class CICCIntegerTurnGeometry: n_tf_coil_turns: int t_conductor_radial: float t_conductor_toroidal: float - t_conductor: float + dx_tf_turn_conduit_full_average: float dr_tf_turn_cable_space: float dx_tf_turn_cable_space: float dx_tf_turn_cable_space_average: float @@ -2289,7 +2289,9 @@ def run(self, output: bool = False): self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general self.data.superconducting_tfcoil.dr_tf_turn = avg_turn_geometry.dr_tf_turn self.data.superconducting_tfcoil.dx_tf_turn = avg_turn_geometry.dx_tf_turn - self.data.tfcoil.t_conductor = avg_turn_geometry.t_conductor + self.data.tfcoil.dx_tf_turn_conduit_full_average = ( + avg_turn_geometry.dx_tf_turn_conduit_full_average + ) self.data.superconducting_tfcoil.radius_tf_turn_cable_space_corners = ( avg_turn_geometry.radius_tf_turn_cable_space_corners ) @@ -2338,7 +2340,9 @@ def run(self, output: bool = False): self.data.superconducting_tfcoil.t_conductor_toroidal = ( int_turn_geometry.t_conductor_toroidal ) - self.data.tfcoil.t_conductor = int_turn_geometry.t_conductor + self.data.tfcoil.dx_tf_turn_conduit_full_average = ( + int_turn_geometry.dx_tf_turn_conduit_full_average + ) self.data.superconducting_tfcoil.dr_tf_turn_cable_space = ( int_turn_geometry.dr_tf_turn_cable_space ) @@ -3246,7 +3250,7 @@ def tf_cable_in_conduit_averaged_turn_geometry( - a_tf_turn: Area of the TF turn (in square meters). - dx_tf_turn: Dimension of the TF turn (in meters). - dr_tf_turn: Dimension of the TF turn (in meters). - - t_conductor: Thickness of the conductor in the TF turn (in meters). + - dx_tf_turn_conduit_full_average: Thickness of the conductor in the TF turn (in meters). - n_tf_coil_turns: Number of turns in the TF coil (not necessarily an integer). - a_tf_turn_insulation: Area of the insulation in the TF turn @@ -3300,7 +3304,7 @@ def tf_cable_in_conduit_averaged_turn_geometry( # See derivation in the following document # k:\power plant physics and technology\process\hts\hts coil module # for process.docx - t_conductor = ( + dx_tf_turn_conduit_full_average = ( -layer_ins + np.sqrt(layer_ins**2 + 4.0e00 * a_tf_turn) ) / 2 - 2.0e0 * dx_tf_turn_insulation @@ -3308,7 +3312,7 @@ def tf_cable_in_conduit_averaged_turn_geometry( n_tf_coil_turns = a_tf_wp_no_insulation / a_tf_turn # Area of inter-turn insulation: single turn [m2] - a_tf_turn_insulation = a_tf_turn - t_conductor**2 + a_tf_turn_insulation = a_tf_turn - dx_tf_turn_conduit_full_average**2 # NOTE: Fortran has a_tf_turn_cable_space_no_void as an intent(out) variable # that was outputting into data.tfcoil.a_tf_turn_cable_space_no_void. @@ -3323,7 +3327,9 @@ def tf_cable_in_conduit_averaged_turn_geometry( radius_tf_turn_cable_space_corners = dx_tf_turn_steel * 0.75e0 # Dimension of square cable space inside conduit [m] - dx_tf_turn_cable_space_average = t_conductor - 2.0e0 * dx_tf_turn_steel + dx_tf_turn_cable_space_average = ( + dx_tf_turn_conduit_full_average - 2.0e0 * dx_tf_turn_steel + ) # Cross-sectional area of cable space per turn # taking account of rounded inside corners [m2] @@ -3349,7 +3355,7 @@ def tf_cable_in_conduit_averaged_turn_geometry( ) if a_tf_turn_cable_space_no_void <= 0.0e0: - if t_conductor < 0.0e0: + if dx_tf_turn_conduit_full_average < 0.0e0: logger.error( "Negative cable space dimension. %s %s", a_tf_turn_cable_space_no_void, @@ -3366,7 +3372,9 @@ def tf_cable_in_conduit_averaged_turn_geometry( a_tf_turn_cable_space_no_void = dx_tf_turn_cable_space_average**2 # Cross-sectional area of conduit jacket per turn [m2] - a_tf_turn_steel = t_conductor**2 - a_tf_turn_cable_space_no_void + a_tf_turn_steel = ( + dx_tf_turn_conduit_full_average**2 - a_tf_turn_cable_space_no_void + ) return CICCAveragedTurnGeometry( a_tf_turn_cable_space_no_void=a_tf_turn_cable_space_no_void, @@ -3377,7 +3385,7 @@ def tf_cable_in_conduit_averaged_turn_geometry( dx_tf_turn_general=dx_tf_turn_general, dr_tf_turn=dr_tf_turn, dx_tf_turn=dx_tf_turn, - t_conductor=t_conductor, + dx_tf_turn_conduit_full_average=dx_tf_turn_conduit_full_average, radius_tf_turn_cable_space_corners=radius_tf_turn_cable_space_corners, dx_tf_turn_cable_space_average=dx_tf_turn_cable_space_average, a_tf_turn_cable_space_effective=a_tf_turn_cable_space_effective, @@ -3439,7 +3447,7 @@ def tf_cable_in_conduit_integer_turn_geometry( (in square meters). - n_tf_coil_turns: Number of turns in the TF coil (not necessarily an integer). - - t_conductor: Thickness of the conductor in the TF turn (in meters). + - dx_tf_turn_conduit_full_average: Thickness of the conductor in the TF turn (in meters). - dx_tf_turn_cable_space_average: Average dimension of the cable space in the TF turn (in meters). - a_tf_turn_cable_space_effective: Effective area of the cable space in the @@ -3490,7 +3498,9 @@ def tf_cable_in_conduit_integer_turn_geometry( # Radial and toroidal dimension of conductor [m] t_conductor_radial = dr_tf_turn - 2.0e0 * dx_tf_turn_insulation t_conductor_toroidal = dx_tf_turn - 2.0e0 * dx_tf_turn_insulation - t_conductor = np.sqrt(t_conductor_radial * t_conductor_toroidal) + dx_tf_turn_conduit_full_average = np.sqrt( + t_conductor_radial * t_conductor_toroidal + ) # Dimension of square cable space inside conduit [m] dr_tf_turn_cable_space = t_conductor_radial - 2.0e0 * dx_tf_turn_steel @@ -3566,7 +3576,7 @@ def tf_cable_in_conduit_integer_turn_geometry( n_tf_coil_turns=n_tf_coil_turns, t_conductor_radial=t_conductor_radial, t_conductor_toroidal=t_conductor_toroidal, - t_conductor=t_conductor, + dx_tf_turn_conduit_full_average=dx_tf_turn_conduit_full_average, dr_tf_turn_cable_space=dr_tf_turn_cable_space, dx_tf_turn_cable_space=dx_tf_turn_cable_space, dx_tf_turn_cable_space_average=dx_tf_turn_cable_space_average, @@ -3756,7 +3766,7 @@ class CROCOAveragedTurnGeometry: dx_tf_turn_general: float dr_tf_turn: float dx_tf_turn: float - t_conductor: float + dx_tf_turn_conduit_full_average: float dx_tf_turn_cable_space_average: float @@ -3814,7 +3824,9 @@ def run(self, output: bool = False): self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general self.data.superconducting_tfcoil.dr_tf_turn = avg_turn_geometry.dr_tf_turn self.data.superconducting_tfcoil.dx_tf_turn = avg_turn_geometry.dx_tf_turn - self.data.tfcoil.t_conductor = avg_turn_geometry.t_conductor + self.data.tfcoil.dx_tf_turn_conduit_full_average = ( + avg_turn_geometry.dx_tf_turn_conduit_full_average + ) self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = ( avg_turn_geometry.dx_tf_turn_cable_space_average ) @@ -3872,11 +3884,9 @@ def run(self, output: bool = False): / self.data.tfcoil.a_tf_inboard_total ) - croco_cable_space_geometry: CroCoCableSpaceGeometry = ( - self.tf_turn_croco_cable_space_properties( - t_conductor=self.data.tfcoil.t_conductor, - dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel, - ) + croco_cable_space_geometry: CroCoCableSpaceGeometry = self.tf_turn_croco_cable_space_properties( + dx_tf_turn_conduit_full_average=self.data.tfcoil.dx_tf_turn_conduit_full_average, + dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel, ) self.data.superconducting_tfcoil.dia_tf_turn_croco_cable = ( @@ -4379,7 +4389,7 @@ def tf_croco_averaged_turn_geometry( - a_tf_turn: Area of the TF turn (in square meters). - dx_tf_turn: Dimension of the TF turn (in meters). - dr_tf_turn: Dimension of the TF turn (in meters). - - t_conductor: Thickness of the conductor in the TF turn (in meters). + - dx_tf_turn_conduit_full_average: Thickness of the conductor in the TF turn (in meters). - n_tf_coil_turns: Number of turns in the TF coil (not necessarily an integer). - a_tf_turn_insulation: Area of the insulation in the TF turn @@ -4428,7 +4438,7 @@ def tf_croco_averaged_turn_geometry( dr_tf_turn = dx_tf_turn_general dx_tf_turn = dx_tf_turn_general - t_conductor = ( + dx_tf_turn_conduit_full_average = ( -layer_ins + np.sqrt(layer_ins**2 + 4.0e00 * a_tf_turn) ) / 2 - 2.0e0 * dx_tf_turn_insulation @@ -4436,17 +4446,21 @@ def tf_croco_averaged_turn_geometry( n_tf_coil_turns = a_tf_wp_no_insulation / a_tf_turn # Area of inter-turn insulation: single turn [m²] - a_tf_turn_insulation = a_tf_turn - t_conductor**2 + a_tf_turn_insulation = a_tf_turn - dx_tf_turn_conduit_full_average**2 a_tf_turn_cable_space_no_void = copy.copy( self.data.tfcoil.a_tf_turn_cable_space_no_void ) # Diameter of circular cable space inside conduit [m] - dx_tf_turn_cable_space_average = t_conductor - 2.0e0 * dx_tf_turn_steel + dx_tf_turn_cable_space_average = ( + dx_tf_turn_conduit_full_average - 2.0e0 * dx_tf_turn_steel + ) # Cross-sectional area of conduit jacket per turn [m²] - a_tf_turn_steel = t_conductor**2 - a_tf_turn_cable_space_no_void + a_tf_turn_steel = ( + dx_tf_turn_conduit_full_average**2 - a_tf_turn_cable_space_no_void + ) return CROCOAveragedTurnGeometry( a_tf_turn_cable_space_no_void=a_tf_turn_cable_space_no_void, @@ -4457,7 +4471,7 @@ def tf_croco_averaged_turn_geometry( dx_tf_turn_general=dx_tf_turn_general, dr_tf_turn=dr_tf_turn, dx_tf_turn=dx_tf_turn, - t_conductor=t_conductor, + dx_tf_turn_conduit_full_average=dx_tf_turn_conduit_full_average, dx_tf_turn_cable_space_average=dx_tf_turn_cable_space_average, ) @@ -4655,14 +4669,14 @@ def tf_croco_superconductor_properties( @staticmethod def tf_turn_croco_cable_space_properties( - t_conductor: float, dx_tf_turn_steel: float + dx_tf_turn_conduit_full_average: float, dx_tf_turn_steel: float ) -> CroCoCableSpaceGeometry: """Calculate the properties of the cable space in the TF turn for a CroCo conductor. Parameters ---------- - t_conductor : float + dx_tf_turn_conduit_full_average : float Thickness of the conductor in the TF turn (in meters). dx_tf_turn_steel : float Thickness of the steel layer in the TF turn (in meters). @@ -4689,8 +4703,8 @@ def tf_turn_croco_cable_space_properties( """ - dia_tf_turn_croco_cable = t_conductor / 3.0e0 - dx_tf_turn_steel * ( - 2.0e0 / 3.0e0 + dia_tf_turn_croco_cable = ( + dx_tf_turn_conduit_full_average / 3.0e0 - dx_tf_turn_steel * (2.0e0 / 3.0e0) ) # Area of the full cable circle in the turn @@ -4703,7 +4717,9 @@ def tf_turn_croco_cable_space_properties( a_tf_turn_cable_space_no_void - 0.25e0 * np.pi * dia_tf_turn_croco_cable**2 ) - conductor_area = t_conductor**2 # does this not assume it's a sqaure??? + conductor_area = ( + dx_tf_turn_conduit_full_average**2 + ) # does this not assume it's a sqaure??? conductor_jacket_area = conductor_area - a_tf_turn_cable_space_no_void a_tf_turn_steel = conductor_jacket_area @@ -4885,8 +4901,8 @@ def output_croco_info(self) -> None: po.ovarre( self.outfile, "Width of square conductor (cable + steel jacket) (m)", - "(t_conductor)", - self.data.tfcoil.t_conductor, + "(dx_tf_turn_conduit_full_average)", + self.data.tfcoil.dx_tf_turn_conduit_full_average, "OP ", ) po.ovarre( diff --git a/tests/unit/models/tfcoil/test_sctfcoil.py b/tests/unit/models/tfcoil/test_sctfcoil.py index 3634fbdc9d..42516abdeb 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -984,7 +984,7 @@ class TfIntegerTurnGeomParam(NamedTuple): dx_tf_wp_insertion_gap: Any = None - t_conductor: Any = None + dx_tf_turn_conduit_full_average: Any = None dx_tf_turn_general: Any = None @@ -1050,7 +1050,7 @@ class TfIntegerTurnGeomParam(NamedTuple): dr_tf_wp_with_insulation=0.54261087836601019, dx_tf_wp_insulation=0.0080000000000000019, dx_tf_wp_insertion_gap=0.01, - t_conductor=0, + dx_tf_turn_conduit_full_average=0, dx_tf_turn_general=0, c_tf_coil=14805350.287500001, dx_tf_wp_toroidal_min=1.299782604942499, @@ -1084,7 +1084,7 @@ class TfIntegerTurnGeomParam(NamedTuple): dr_tf_wp_with_insulation=0.54261087836601019, dx_tf_wp_insulation=0.0080000000000000019, dx_tf_wp_insertion_gap=0.01, - t_conductor=0.052553108427885735, + dx_tf_turn_conduit_full_average=0.052553108427885735, dx_tf_turn_general=0.056579413904423038, c_tf_coil=14805350.287500001, dx_tf_wp_toroidal_min=1.299782604942499, @@ -1149,7 +1149,7 @@ def test_tf_cable_in_conduit_integer_turn_geometry( 0.75 * tfintegerturngeomparam.dx_tf_turn_steel ) - assert integer_turn_geometry.t_conductor == pytest.approx( + assert integer_turn_geometry.dx_tf_turn_conduit_full_average == pytest.approx( tfintegerturngeomparam.expected_t_conductor ) @@ -1209,7 +1209,7 @@ def test_tf_cable_in_conduit_integer_turn_geometry( class TfAveragedTurnGeomParam(NamedTuple): layer_ins: Any = None - t_conductor: Any = None + dx_tf_turn_conduit_full_average: Any = None dx_tf_turn_general: Any = None @@ -1259,7 +1259,7 @@ class TfAveragedTurnGeomParam(NamedTuple): [ TfAveragedTurnGeomParam( layer_ins=0, - t_conductor=0, + dx_tf_turn_conduit_full_average=0, dx_tf_turn_general=0, i_dx_tf_turn_general_input=False, c_tf_turn=65000, @@ -1284,7 +1284,7 @@ class TfAveragedTurnGeomParam(NamedTuple): ), TfAveragedTurnGeomParam( layer_ins=0, - t_conductor=0.047932469413859431, + dx_tf_turn_conduit_full_average=0.047932469413859431, dx_tf_turn_general=0.049532469413859428, i_dx_tf_turn_general_input=False, c_tf_turn=65000, @@ -1309,7 +1309,7 @@ class TfAveragedTurnGeomParam(NamedTuple): ), TfAveragedTurnGeomParam( layer_ins=0, - t_conductor=5.712e-02, + dx_tf_turn_conduit_full_average=5.712e-02, dx_tf_turn_general=0.05872, i_dx_tf_turn_general_input=True, c_tf_turn=0, @@ -1334,7 +1334,7 @@ class TfAveragedTurnGeomParam(NamedTuple): ), TfAveragedTurnGeomParam( layer_ins=0, - t_conductor=0.058296, + dx_tf_turn_conduit_full_average=0.058296, dx_tf_turn_general=0, i_dx_tf_turn_general_input=False, c_tf_turn=0, @@ -1392,7 +1392,7 @@ def test_tf_cable_in_conduit_averaged_turn_geometry( ) # Existing checks - assert avg_turn_geometry.t_conductor == pytest.approx( + assert avg_turn_geometry.dx_tf_turn_conduit_full_average == pytest.approx( tfaveragedturngeomparam.expected_t_conductor ) assert avg_turn_geometry.dx_tf_turn_general == pytest.approx( From 08761da7fde0f6bb70ae06b573c350d9472848fc Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:50:02 +0100 Subject: [PATCH 12/20] Refactor SuperconductingTFData and related tests to rename conductor dimensions for clarity --- .../superconducting_tf_coil_variables.py | 8 ++-- process/models/tfcoil/superconducting.py | 39 ++++++++++--------- tests/unit/models/tfcoil/test_sctfcoil.py | 16 ++++---- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index db11bbfe77..fd54025729 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -113,11 +113,11 @@ class SuperconductingTFData: tan_theta_coil: float = 0.0 """Tan half toroidal angular extent of a single TF coil inboard leg""" - t_conductor_radial: float = 0.0 - """Conductor area radial and toroidal dimension (integer turn only) [m]""" + dr_tf_turn_conduit_full: float = 0.0 + """Radial thickness of the full conduit around the cable space (integer turn only) [m]""" - t_conductor_toroidal: float = 0.0 - """Conductor area radial and toroidal dimension (integer turn only) [m]""" + dx_tf_turn_conduit_full_toroidal: float = 0.0 + """Toroidal thickness of the full conduit around the cable space (integer turn only) [m]""" dr_tf_turn_cable_space: float = 0.0 """Cable area radial and toroidal dimension (integer turn only) [m]""" diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index abe68095d8..dc8f802b8f 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -561,15 +561,15 @@ def output_general_superconducting_tf_info(self) -> None: po.ovarre( self.outfile, "Radial width of conductor (m)", - "(t_conductor_radial)", - self.data.superconducting_tfcoil.t_conductor_radial, + "(dr_tf_turn_conduit_full)", + self.data.superconducting_tfcoil.dr_tf_turn_conduit_full, "OP ", ) po.ovarre( self.outfile, "Toroidal width of conductor (m)", - "(t_conductor_toroidal)", - self.data.superconducting_tfcoil.t_conductor_toroidal, + "(dx_tf_turn_conduit_full_toroidal)", + self.data.superconducting_tfcoil.dx_tf_turn_conduit_full_toroidal, "OP ", ) po.ovarre( @@ -2236,8 +2236,8 @@ class CICCIntegerTurnGeometry: a_tf_turn_insulation: float c_tf_turn: float n_tf_coil_turns: int - t_conductor_radial: float - t_conductor_toroidal: float + dr_tf_turn_conduit_full: float + dx_tf_turn_conduit_full_toroidal: float dx_tf_turn_conduit_full_average: float dr_tf_turn_cable_space: float dx_tf_turn_cable_space: float @@ -2334,11 +2334,11 @@ def run(self, output: bool = False): ) self.data.tfcoil.c_tf_turn = int_turn_geometry.c_tf_turn self.data.tfcoil.n_tf_coil_turns = int_turn_geometry.n_tf_coil_turns - self.data.superconducting_tfcoil.t_conductor_radial = ( - int_turn_geometry.t_conductor_radial + self.data.superconducting_tfcoil.dr_tf_turn_conduit_full = ( + int_turn_geometry.dr_tf_turn_conduit_full ) - self.data.superconducting_tfcoil.t_conductor_toroidal = ( - int_turn_geometry.t_conductor_toroidal + self.data.superconducting_tfcoil.dx_tf_turn_conduit_full_toroidal = ( + int_turn_geometry.dx_tf_turn_conduit_full_toroidal ) self.data.tfcoil.dx_tf_turn_conduit_full_average = ( int_turn_geometry.dx_tf_turn_conduit_full_average @@ -3496,15 +3496,17 @@ def tf_cable_in_conduit_integer_turn_geometry( c_tf_turn = c_tf_coil / n_tf_coil_turns # Radial and toroidal dimension of conductor [m] - t_conductor_radial = dr_tf_turn - 2.0e0 * dx_tf_turn_insulation - t_conductor_toroidal = dx_tf_turn - 2.0e0 * dx_tf_turn_insulation + dr_tf_turn_conduit_full = dr_tf_turn - 2.0e0 * dx_tf_turn_insulation + dx_tf_turn_conduit_full_toroidal = dx_tf_turn - 2.0e0 * dx_tf_turn_insulation dx_tf_turn_conduit_full_average = np.sqrt( - t_conductor_radial * t_conductor_toroidal + dr_tf_turn_conduit_full * dx_tf_turn_conduit_full_toroidal ) # Dimension of square cable space inside conduit [m] - dr_tf_turn_cable_space = t_conductor_radial - 2.0e0 * dx_tf_turn_steel - dx_tf_turn_cable_space = t_conductor_toroidal - 2.0e0 * dx_tf_turn_steel + dr_tf_turn_cable_space = dr_tf_turn_conduit_full - 2.0e0 * dx_tf_turn_steel + dx_tf_turn_cable_space = ( + dx_tf_turn_conduit_full_toroidal - 2.0e0 * dx_tf_turn_steel + ) dx_tf_turn_cable_space_average = np.sqrt( dr_tf_turn_cable_space * dx_tf_turn_cable_space ) @@ -3558,7 +3560,8 @@ def tf_cable_in_conduit_integer_turn_geometry( # Cross-sectional area of conduit jacket per turn [m²] a_tf_turn_steel = ( - t_conductor_radial * t_conductor_toroidal - a_tf_turn_cable_space_no_void + dr_tf_turn_conduit_full * dx_tf_turn_conduit_full_toroidal + - a_tf_turn_cable_space_no_void ) # Area of inter-turn insulation: single turn [m²] @@ -3574,8 +3577,8 @@ def tf_cable_in_conduit_integer_turn_geometry( a_tf_turn_insulation=a_tf_turn_insulation, c_tf_turn=c_tf_turn, n_tf_coil_turns=n_tf_coil_turns, - t_conductor_radial=t_conductor_radial, - t_conductor_toroidal=t_conductor_toroidal, + dr_tf_turn_conduit_full=dr_tf_turn_conduit_full, + dx_tf_turn_conduit_full_toroidal=dx_tf_turn_conduit_full_toroidal, dx_tf_turn_conduit_full_average=dx_tf_turn_conduit_full_average, dr_tf_turn_cable_space=dr_tf_turn_cable_space, dx_tf_turn_cable_space=dx_tf_turn_cable_space, diff --git a/tests/unit/models/tfcoil/test_sctfcoil.py b/tests/unit/models/tfcoil/test_sctfcoil.py index 42516abdeb..b296253b61 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -992,9 +992,9 @@ class TfIntegerTurnGeomParam(NamedTuple): dx_tf_wp_toroidal_min: Any = None - t_conductor_radial: Any = None + dr_tf_turn_conduit_full: Any = None - t_conductor_toroidal: Any = None + dx_tf_turn_conduit_full_toroidal: Any = None dr_tf_turn_cable_space: Any = None @@ -1054,8 +1054,8 @@ class TfIntegerTurnGeomParam(NamedTuple): dx_tf_turn_general=0, c_tf_coil=14805350.287500001, dx_tf_wp_toroidal_min=1.299782604942499, - t_conductor_radial=0, - t_conductor_toroidal=0, + dr_tf_turn_conduit_full=0, + dx_tf_turn_conduit_full_toroidal=0, dr_tf_turn_cable_space=0, dx_tf_turn_cable_space=0, dr_tf_turn=0, @@ -1088,8 +1088,8 @@ class TfIntegerTurnGeomParam(NamedTuple): dx_tf_turn_general=0.056579413904423038, c_tf_coil=14805350.287500001, dx_tf_wp_toroidal_min=1.299782604942499, - t_conductor_radial=0.046661087836601015, - t_conductor_toroidal=0.059189130247124938, + dr_tf_turn_conduit_full=0.046661087836601015, + dx_tf_turn_conduit_full_toroidal=0.059189130247124938, dr_tf_turn_cable_space=0.030661087836601014, dx_tf_turn_cable_space=0.043189130247124938, dr_tf_turn=0.050661087836601018, @@ -1157,11 +1157,11 @@ def test_tf_cable_in_conduit_integer_turn_geometry( tfintegerturngeomparam.expected_dx_tf_turn_general ) - assert integer_turn_geometry.t_conductor_radial == pytest.approx( + assert integer_turn_geometry.dr_tf_turn_conduit_full == pytest.approx( tfintegerturngeomparam.expected_t_conductor_radial ) - assert integer_turn_geometry.t_conductor_toroidal == pytest.approx( + assert integer_turn_geometry.dx_tf_turn_conduit_full_toroidal == pytest.approx( tfintegerturngeomparam.expected_t_conductor_toroidal ) From 39ab432dd8ecadb13b3c0db628bbefb0e0e108b5 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 17:10:18 +0100 Subject: [PATCH 13/20] Refactor TFData and SuperconductingTFCoil to clarify mass calculations and improve variable naming --- process/data_structure/tfcoil_variables.py | 5 ++- process/models/tfcoil/superconducting.py | 49 +++++----------------- 2 files changed, 15 insertions(+), 39 deletions(-) diff --git a/process/data_structure/tfcoil_variables.py b/process/data_structure/tfcoil_variables.py index dc7e6f7f92..68e7118ce3 100644 --- a/process/data_structure/tfcoil_variables.py +++ b/process/data_structure/tfcoil_variables.py @@ -757,7 +757,10 @@ class TFData: """mass of ground-wall insulation layer per coil (kg/coil)""" m_tf_coils_total: float = 0.0 - """total mass of the TF coils (kg)""" + """Total mass of all TF coils (kg)""" + + m_tf_coil: float = 0.0 + """Total mass of one TF coil (kg)""" dx_tf_wp_primary_toroidal: float = 0.0 """width of first step of winding pack (m)""" diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index dc8f802b8f..a3712b0dcc 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -699,8 +699,8 @@ def output_general_superconducting_tf_info(self) -> None: po.ovarre( self.outfile, "Mass of each TF coil (kg)", - "(m_tf_coils_total/n_tf_coils)", - self.data.tfcoil.m_tf_coils_total / self.data.tfcoil.n_tf_coils, + "(m_tf_coil)", + self.data.tfcoil.m_tf_coil, "OP ", ) po.ovarre( @@ -2011,11 +2011,16 @@ def superconducting_tf_coil_areas_and_masses(self): # --------------------------------- # Total TF coil mass [kg] (all coils) - self.data.tfcoil.m_tf_coils_total = ( + self.data.tfcoil.m_tf_coil = ( self.data.tfcoil.m_tf_coil_case + self.data.tfcoil.m_tf_coil_conductor + self.data.tfcoil.m_tf_coil_wp_insulation - ) * self.data.tfcoil.n_tf_coils + ) + + # Total TF coil mass [kg] (all coils) + self.data.tfcoil.m_tf_coils_total = ( + self.data.tfcoil.m_tf_coil * self.data.tfcoil.n_tf_coils + ) # If spherical tokamak, distribute between centrepost and outboard legs # (in this case, total TF coil length = inboard `cplen` + @@ -3686,48 +3691,16 @@ def output_cable_in_conduit_cable_info(self) -> None: po.ovarre( self.outfile, - "Copper fraction of conductor", + "Copper area fraction of cable conductor", "(f_a_tf_turn_cable_copper)", self.data.tfcoil.f_a_tf_turn_cable_copper, ) po.ovarre( self.outfile, - "Superconductor fraction of conductor", + "Superconductor area fraction of cable conductor", "(1-f_a_tf_turn_cable_copper)", 1 - self.data.tfcoil.f_a_tf_turn_cable_copper, ) - ap = ( - self.data.tfcoil.a_tf_wp_conductor - + self.data.tfcoil.n_tf_coil_turns * self.data.tfcoil.a_tf_turn_steel - + self.data.tfcoil.a_tf_coil_wp_turn_insulation - + self.data.tfcoil.a_tf_wp_extra_void - + self.data.tfcoil.a_tf_wp_coolant_channels - ) - po.ovarrf( - self.outfile, - "Check total area fractions in winding pack = 1", - "", - ( - self.data.tfcoil.a_tf_wp_conductor - + self.data.tfcoil.n_tf_coil_turns * self.data.tfcoil.a_tf_turn_steel - + self.data.tfcoil.a_tf_coil_wp_turn_insulation - + self.data.tfcoil.a_tf_wp_extra_void - + self.data.tfcoil.a_tf_wp_coolant_channels - ) - / ap, - ) - po.ovarrf( - self.outfile, - "minimum TF conductor temperature margin (K)", - "(temp_tf_superconductor_margin_min)", - self.data.tfcoil.temp_tf_superconductor_margin_min, - ) - po.ovarrf( - self.outfile, - "TF conductor temperature margin (K)", - "(temp_tf_superconductor_margin)", - self.data.tfcoil.temp_tf_superconductor_margin, - ) po.ovarin( self.outfile, From 4b5b7d9fffa14c69a2b892de86afcaa624d57222 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 13:21:08 +0100 Subject: [PATCH 14/20] Update tests for ST to use croco turn type for tapes --- process/models/tfcoil/superconducting.py | 10 ---------- .../input_files/spherical_tokamak_eval.IN.DAT | 1 + tests/regression/input_files/st_regression.IN.DAT | 5 ++++- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index a3712b0dcc..8e256fde96 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -4015,7 +4015,6 @@ def run(self, output: bool = False): b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple, cur_tf_turn=self.data.tfcoil.c_tf_turn, temp_tf_peak=self.data.tfcoil.tftmp, - a_tf_turn_cable_space_effective=self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective, i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat, dr_tf_hts_tape=self.data.superconducting_tfcoil.dr_tf_hts_tape, dx_tf_hts_tape_rebco=self.data.superconducting_tfcoil.dx_tf_hts_tape_rebco, @@ -4457,7 +4456,6 @@ def tf_croco_superconductor_properties( b_tf_inboard_peak: float, cur_tf_turn: float, temp_tf_peak: float, - a_tf_turn_cable_space_effective: float, i_tf_superconductor: int, dr_tf_hts_tape: float, dx_tf_hts_tape_rebco: float, @@ -4514,8 +4512,6 @@ def tf_croco_superconductor_properties( else: strain = self.data.tfcoil.str_wp - f_a_tf_turn_tape_superconductor = dx_tf_hts_tape_rebco / dx_tf_hts_tape_total - # ================================================================= if i_tf_superconductor == SuperconductorModel.CROCO_REBCO: @@ -4577,12 +4573,6 @@ def tf_croco_superconductor_properties( # ================================================================= - # Scale for the copper area fraction of the cable - j_tape_critical = j_superconductor_critical * f_a_tf_turn_tape_superconductor - - # Critical current in turn all turn cables - c_turn_cables_critical = j_tape_critical * a_tf_turn_cable_space_effective - # Strand critical current calulation for costing in $ / kAm # Already includes buffer and support layers so no need to include # f_a_tf_turn_cable_copper here diff --git a/tests/regression/input_files/spherical_tokamak_eval.IN.DAT b/tests/regression/input_files/spherical_tokamak_eval.IN.DAT index 40f9065f20..d8598bb15f 100644 --- a/tests/regression/input_files/spherical_tokamak_eval.IN.DAT +++ b/tests/regression/input_files/spherical_tokamak_eval.IN.DAT @@ -69,6 +69,7 @@ gapomin = 0.0 * minimum gap between outboard vacuum vessel and TF coil (m) (`it iohcl = 0 * Switch for existence of central solenoid; i_cs_precomp = 0 * Switch for existence of central solenoid pre-compression structure; i_tf_inside_cs = 0 * Switch for placing the TF coil inside the CS +i_tf_turn_type = 2 * CroCo Turn geometry for HTS Tapes dr_cs = 0.20016400484967947 * Central solenoid thickness (m) (`iteration variable 16`) i_r_cp_top = 2 * Switch selecting the he parametrization of the outer radius of the top of the CP part of the TF coil dr_fw_plasma_gap_inboard = 0.1 * Gap between plasma and first wall; inboard side (m) (if `i_plasma_wall_gap=1`) diff --git a/tests/regression/input_files/st_regression.IN.DAT b/tests/regression/input_files/st_regression.IN.DAT index 967e8da19f..84c8a3c9fc 100644 --- a/tests/regression/input_files/st_regression.IN.DAT +++ b/tests/regression/input_files/st_regression.IN.DAT @@ -789,7 +789,10 @@ pseprmax = 40.0 n_tf_coils = 12 * DESCRIPTION: Number of TF Coils -* JUSTIFICATION: +* JUSTIFICATION: + +i_tf_turn_type = 2 +* CroCo Turn geometry for HTS Tapes i_tf_shape = 2 * DESCRIPTION: Switch for TF coil toroidal shape (2: Picture frame coils) From e43933b7b37e2d395381fba66c90610f2b1768cf Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 13:34:03 +0100 Subject: [PATCH 15/20] Add strain calculation and superconductor temperature margin logic in CROCOSuperconductingTFCoil --- process/models/tfcoil/superconducting.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 8e256fde96..225aea0adf 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -4044,6 +4044,23 @@ def run(self, output: bool = False): superconductor_critical_properties.c_turn_cables_critical ) + if self.data.tfcoil.i_str_wp == 0: + strain = self.data.tfcoil.str_tf_con_res + else: + strain = self.data.tfcoil.str_wp + + self.data.tfcoil.temp_tf_superconductor_margin = self.calculate_superconductor_temperature_margin( + i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat, + j_superconductor=self.data.superconducting_tfcoil.j_tf_superconductor, + b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple, + strain=strain, + bc20m=self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain, + tc0m=self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain, + c0=1.0e10, + temp_tf_coolant_peak_field=self.data.tfcoil.tftmp, + data=self.data, + ) + self.data.tfcoil.v_tf_coil_dump_quench_kv = ( self.croco_voltage() / 1.0e3 ) # TFC Quench voltage in kV From aa1bf3c19160a10bebfb43b7a49c79ba29254c43 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 14:17:14 +0100 Subject: [PATCH 16/20] Add mapping for obsolete variable 't_conductor' to 'dx_tf_turn_conduit_full_average' --- process/core/io/obsolete_vars.py | 1 + 1 file changed, 1 insertion(+) diff --git a/process/core/io/obsolete_vars.py b/process/core/io/obsolete_vars.py index 63b22407fd..d4b2e8d9b4 100644 --- a/process/core/io/obsolete_vars.py +++ b/process/core/io/obsolete_vars.py @@ -457,6 +457,7 @@ "dr_hts_tape": "dr_tf_hts_tape", "coppera_m2_max": "tf_coppera_m2_max", "f_ster_div_single": None, + "t_conductor": "dx_tf_turn_conduit_full_average", } OBS_VARS_HELP = { From 889003a6fc466461a3faa07d0c5b06a2b626ade8 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 14:21:52 +0100 Subject: [PATCH 17/20] Remove outdated comments regarding critical current density in CICCSuperconductingTFCoil class --- process/models/tfcoil/superconducting.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 225aea0adf..a3b37560ad 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -2824,13 +2824,6 @@ def tf_cable_in_conduit_superconductor_properties( and also the protection information (for a quench). Not used for the CroCo conductor. - The critical current density for a superconductor - (``j_superconductor_critical``) is for the superconducting strands/tape, - not including copper. The critical current density for - a cable (``j_crit_cable``) accounts for both the fraction of the cable taken - up by helium coolant channels, and the cable conductor copper fraction - (i.e., the copper in the superconducting strands and any additional copper, - such as REBCO tape support). """ if ( SuperconductorModel(i_tf_superconductor).sc_shape From bd1a013ff0eb6c562fe9666e974764e2c82330c3 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 18:31:36 +0100 Subject: [PATCH 18/20] Refactor code structure for improved readability and maintainability --- process/core/input.py | 4 +- .../superconducting_tf_coil_variables.py | 19 +- process/models/tfcoil/superconducting.py | 227 +++++------------- 3 files changed, 67 insertions(+), 183 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index 644078ef83..9ab657301b 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -266,7 +266,9 @@ def __post_init__(self): "crane_arm_h": InputVariable("buildings", float, range=(1.0, 100.0)), "crane_clrnc_h": InputVariable("buildings", float, range=(0.0, 10.0)), "crane_clrnc_v": InputVariable("buildings", float, range=(0.0, 10.0)), - "dx_tf_croco_strand_copper": InputVariable("rebco", float, range=(0.001, 0.1)), + "dx_tf_croco_strand_copper": InputVariable( + "superconducting_tfcoil", float, range=(0.001, 0.1) + ), "cryomag_h": InputVariable("buildings", float, range=(1.0, 100.0)), "cryomag_l": InputVariable("buildings", float, range=(10.0, 1000.0)), "cryomag_w": InputVariable("buildings", float, range=(10.0, 1000.0)), diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index fd54025729..0ff662dd5a 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -254,33 +254,20 @@ class SuperconductingTFData: outer tube and central copper) (m²)""" a_tf_turn_copper_total: float = 0.0 - """Area of all copper in the TF turn (m²)""" + """Area of all copper in the TF turn [m²]""" f_a_tf_turn_copper: float = 0.0 - """Fraction of the TF turn area that is copper (m²)""" + """Fraction of the TF turn area that is copper""" a_tf_turn_croco_copper_bar: float = 0.0 """Area of the central copper strand in the CroCo TF turn [m²]""" f_a_tf_turn_superconductor: float = 0.0 - """Fraction of the TF turn area that is superconducting material [m²]""" + """Fraction of the TF turn area that is superconducting material""" a_tf_turn_croco_hastelloy: float = 0.0 """Area of the Hastelloy in the CroCo cable space of the TF turn (includes tapes and outer tube) (m²)""" - conductor_hastelloy_fraction: float = 0.0 - conductor_helium_area: float = 0.0 - conductor_helium_fraction: float = 0.0 - conductor_solder_area: float = 0.0 - conductor_solder_fraction: float = 0.0 - conductor_jacket_area: float = 0.0 - conductor_jacket_fraction: float = 0.0 - conductor_rebco_area: float = 0.0 - conductor_rebco_fraction: float = 0.0 - conductor_critical_current: float = 0.0 - conductor_area: float = 0.0 - """Area of cable space inside jacket""" - t1: float = 0.0 time2: float = 0.0 diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index a3b37560ad..08146031b4 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -81,7 +81,7 @@ def full_name(self): return self.name.title().replace("_", " ") -@dataclass +@dataclass(slots=True) class TFWPGeometry: """Data class for storing the geometry of the TF coil winding pack and ground insulation. @@ -100,7 +100,7 @@ class TFWPGeometry: a_tf_wp_ground_insulation: float -@dataclass +@dataclass(slots=True) class TFSuperconductorLimits: j_tf_wp_critical: float j_superconductor_critical: float @@ -631,12 +631,33 @@ def output_general_superconducting_tf_info(self) -> None: "(dx_tf_turn_insulation)", self.data.tfcoil.dx_tf_turn_insulation, ) + po.oblnkl(self.outfile) po.ovarre( self.outfile, "TF coil turn area (m²)", "(a_tf_turn)", self.data.tfcoil.a_tf_turn, ) + po.ovarre( + self.outfile, + "Total area of available cable space [m²]", + "(a_tf_turn_cable_space_no_void)", + self.data.tfcoil.a_tf_turn_cable_space_no_void, + "OP ", + ) + po.ovarre( + self.outfile, + "True area of turn cable space usable by conductor [m²]", + "(a_tf_turn_cable_space_effective)", + self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective, + ) + + po.ovarre( + self.outfile, + "Extra coolant area fraction in turn cable space", + "(f_a_tf_turn_cable_space_extra_void)", + self.data.tfcoil.f_a_tf_turn_cable_space_extra_void, + ) po.oblnkl(self.outfile) po.ocmmnt(self.outfile, "----------------------------") @@ -2210,9 +2231,9 @@ def run_and_output_stress(self) -> None: self.data.tfcoil.sig_tf_wp = 0.0e0 -@dataclass -class CICCAveragedTurnGeometry: - """Averaged turn geometry for a CICC conductor with LTS cables.""" +@dataclass(slots=True) +class TFGeneralTurnGeometry: + """General turn geometry info needed for all TF turn types.""" a_tf_turn_cable_space_no_void: float a_tf_turn_steel: float @@ -2223,30 +2244,29 @@ class CICCAveragedTurnGeometry: dr_tf_turn: float dx_tf_turn: float dx_tf_turn_conduit_full_average: float - radius_tf_turn_cable_space_corners: float dx_tf_turn_cable_space_average: float + + +@dataclass(slots=True) +class CICCAveragedTurnGeometry(TFGeneralTurnGeometry): + """Averaged turn geometry for a CICC conductor with LTS cables.""" + + radius_tf_turn_cable_space_corners: float a_tf_turn_cable_space_effective: float f_a_tf_turn_cable_space_cooling: float -@dataclass -class CICCIntegerTurnGeometry: +@dataclass(slots=True) +class CICCIntegerTurnGeometry(TFGeneralTurnGeometry): """Integer turn geometry for a CICC conductor with LTS cables.""" radius_tf_turn_cable_space_corners: float - dr_tf_turn: float - dx_tf_turn: float - a_tf_turn_cable_space_no_void: float - a_tf_turn_steel: float - a_tf_turn_insulation: float - c_tf_turn: float - n_tf_coil_turns: int dr_tf_turn_conduit_full: float dx_tf_turn_conduit_full_toroidal: float - dx_tf_turn_conduit_full_average: float dr_tf_turn_cable_space: float dx_tf_turn_cable_space: float - dx_tf_turn_cable_space_average: float + a_tf_turn_cable_space_effective: float + f_a_tf_turn_cable_space_cooling: float class CICCSuperconductingTFCoil(SuperconductingTFCoil): @@ -3618,26 +3638,8 @@ def output_cable_in_conduit_cable_info(self) -> None: "(len_tf_superconductor_total)", self.data.superconducting_tfcoil.len_tf_superconductor_total, ) - po.ocmmnt(self.outfile, "Fractions by area") - po.ovarre( - self.outfile, - "internal area of the cable space", - "(a_tf_turn_cable_space_no_void)", - self.data.tfcoil.a_tf_turn_cable_space_no_void, - ) - po.ovarre( - self.outfile, - "True area of turn cable space with gaps and channels removed", - "(a_tf_turn_cable_space_effective)", - self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective, - ) + po.oblnkl(self.outfile) - po.ovarre( - self.outfile, - "Coolant fraction in conductor excluding central channel", - "(f_a_tf_turn_cable_space_extra_void)", - self.data.tfcoil.f_a_tf_turn_cable_space_extra_void, - ) po.ovarre( self.outfile, "Area of steel in turn", @@ -3725,29 +3727,20 @@ def output_cable_in_conduit_cable_info(self) -> None: ) -@dataclass -class CROCOAveragedTurnGeometry: - a_tf_turn_cable_space_no_void: float - a_tf_turn_steel: float - a_tf_turn_insulation: float - n_tf_coil_turns: int - c_tf_turn: float - dx_tf_turn_general: float - dr_tf_turn: float - dx_tf_turn: float - dx_tf_turn_conduit_full_average: float - dx_tf_turn_cable_space_average: float +@dataclass(slots=True) +class CROCOAveragedTurnGeometry(TFGeneralTurnGeometry): + """Data class for the averaged turn geometry of a CroCo conductor.""" -@dataclass +@dataclass(slots=True) class CroCoCableSpaceGeometry: + """Data class for the geometry of the cable space in a CroCo conductor.""" + dia_tf_turn_croco_cable: float a_tf_turn_cable_space_no_void: float a_tf_turn_cable_space_effective: float a_tf_turn_steel: float - conductor_area: float - conductor_jacket_area: float - conductor_jacket_fraction: float + f_a_tf_turn_cable_space_cooling: float class CROCOSuperconductingTFCoil(SuperconductingTFCoil): @@ -3811,6 +3804,8 @@ def run(self, output: bool = False): # No central channel in CroCo conductor, self.data.tfcoil.a_tf_wp_coolant_channels = 0.0 + self.data.tfcoil.f_a_tf_turn_cable_space_extra_void = 0.0 + # Void area in conductor for He, not including central channel [m²] self.data.tfcoil.a_tf_wp_extra_void = ( self.data.tfcoil.a_tf_turn_cable_space_no_void @@ -3868,14 +3863,8 @@ def run(self, output: bool = False): croco_cable_space_geometry.a_tf_turn_cable_space_effective ) self.data.tfcoil.a_tf_turn_steel = croco_cable_space_geometry.a_tf_turn_steel - self.data.superconducting_tfcoil.conductor_area = ( - croco_cable_space_geometry.conductor_area - ) - self.data.superconducting_tfcoil.conductor_jacket_area = ( - croco_cable_space_geometry.conductor_jacket_area - ) - self.data.superconducting_tfcoil.conductor_jacket_fraction = ( - croco_cable_space_geometry.conductor_jacket_fraction + self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling = ( + croco_cable_space_geometry.f_a_tf_turn_cable_space_cooling ) croco_cable_geometry: CroCoCableGeometry = calculate_croco_cable_geometry( @@ -3973,28 +3962,6 @@ def run(self, output: bool = False): self.data.superconducting_tfcoil.a_tf_croco_strand_hastelloy * N_CROCO_STRANDS_TURN ) - self.data.superconducting_tfcoil.conductor_hastelloy_fraction = ( - self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy - / self.data.superconducting_tfcoil.conductor_area - ) - - self.data.superconducting_tfcoil.conductor_solder_area = ( - self.data.superconducting_tfcoil.a_tf_croco_strand_solder - * N_CROCO_STRANDS_TURN - ) - self.data.superconducting_tfcoil.conductor_solder_fraction = ( - self.data.superconducting_tfcoil.conductor_solder_area - / self.data.superconducting_tfcoil.conductor_area - ) - - self.data.superconducting_tfcoil.conductor_rebco_area = ( - self.data.superconducting_tfcoil.a_tf_croco_strand_rebco - * N_CROCO_STRANDS_TURN - ) - self.data.superconducting_tfcoil.f_a_tf_turn_superconductor = ( - self.data.superconducting_tfcoil.conductor_rebco_area - / self.data.superconducting_tfcoil.conductor_area - ) # Cross-sectional area per turn self.data.tfcoil.a_tf_turn = self.data.tfcoil.c_tf_total / ( @@ -4597,23 +4564,14 @@ def tf_croco_superconductor_properties( cur_tf_turn_croco_strand_critical = j_superconductor_critical * a_tf_croco_strand # Conductor properties - self.data.superconducting_tfcoil.conductor_critical_current = ( - cur_tf_turn_croco_strand_critical * N_CROCO_STRANDS_TURN - ) - - self.data.superconducting_tfcoil.tf_coppera_m2 = ( - cur_tf_turn - / self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper - ) - - cur_critical = self.data.superconducting_tfcoil.conductor_critical_current + cur_tf_turn_critical = cur_tf_turn_croco_strand_critical * N_CROCO_STRANDS_TURN # Critical current density in winding pack # a_tf_turn : Area per turn (i.e. entire jacketed conductor with insulation) (m2) - j_tf_wp_critical = cur_critical / a_tf_turn + j_tf_wp_critical = cur_tf_turn_critical / a_tf_turn # Ratio of operating / critical current - f_c_tf_turn_operating_critical = cur_tf_turn / cur_critical + f_c_tf_turn_operating_critical = cur_tf_turn / cur_tf_turn_critical # Operating current density j_tf_coil_turn = cur_tf_turn / a_tf_turn @@ -4660,24 +4618,6 @@ def tf_turn_croco_cable_space_properties( Returns ------- CroCoCableSpaceGeometry - A dataclass containing the calculated properties of the cable space in - the TF turn, including: - - dia_tf_turn_croco_cable: Diameter of the circular cable space in the TF - turn (in meters). - - a_tf_turn_cable_space_no_void: Area of the cable space in the TF turn - without voids (in square meters). - - a_tf_turn_cable_space_effective: Effective area of the cable space in - the TF turn after accounting for cooling channels and voids - (in square meters). - - a_tf_turn_steel: Area of the steel in the TF turn (in square meters). - - conductor_area: Total area of the conductor in the TF turn - (in square meters). - - conductor_jacket_area: Area of the conductor jacket in the TF turn - (in square meters). - - conductor_jacket_fraction: Fraction of the conductor area that is the - jacket (dimensionless). - - """ dia_tf_turn_croco_cable = ( dx_tf_turn_conduit_full_average / 3.0e0 - dx_tf_turn_steel * (2.0e0 / 3.0e0) @@ -4688,28 +4628,25 @@ def tf_turn_croco_cable_space_properties( 9.0e0 / 4.0e0 * np.pi * dia_tf_turn_croco_cable**2 ) - # Area of the full cable spac circle minus the central copper strand + # Just the area of the CroCo strands in the turn (i.e. not including voids) a_tf_turn_cable_space_effective = ( - a_tf_turn_cable_space_no_void - 0.25e0 * np.pi * dia_tf_turn_croco_cable**2 + N_CROCO_STRANDS_TURN * np.pi * (dia_tf_turn_croco_cable / 2.0e0) ** 2 ) - conductor_area = ( - dx_tf_turn_conduit_full_average**2 - ) # does this not assume it's a sqaure??? - - conductor_jacket_area = conductor_area - a_tf_turn_cable_space_no_void - a_tf_turn_steel = conductor_jacket_area + a_tf_turn_steel = ( + dx_tf_turn_conduit_full_average**2 - a_tf_turn_cable_space_no_void + ) - conductor_jacket_fraction = conductor_jacket_area / conductor_area + f_a_tf_turn_cable_space_cooling = a_tf_turn_cable_space_no_void - ( + (N_CROCO_STRANDS_TURN + 1) * np.pi * (dia_tf_turn_croco_cable / 2.0e0) ** 2 + ) return CroCoCableSpaceGeometry( dia_tf_turn_croco_cable=dia_tf_turn_croco_cable, a_tf_turn_cable_space_no_void=a_tf_turn_cable_space_no_void, a_tf_turn_cable_space_effective=a_tf_turn_cable_space_effective, a_tf_turn_steel=a_tf_turn_steel, - conductor_area=conductor_area, - conductor_jacket_area=conductor_jacket_area, - conductor_jacket_fraction=conductor_jacket_fraction, + f_a_tf_turn_cable_space_cooling=f_a_tf_turn_cable_space_cooling, ) def croco_voltage(self) -> float: @@ -4861,13 +4798,6 @@ def output_croco_info(self) -> None: "", N_CROCO_STRANDS_TURN, ) - po.ovarre( - self.outfile, - "Total area of circular cable space (m²)", - "(a_tf_turn_cable_space_no_void)", - self.data.tfcoil.a_tf_turn_cable_space_no_void, - "OP ", - ) po.oblnkl(self.outfile) po.ocmmnt( @@ -4881,20 +4811,6 @@ def output_croco_info(self) -> None: self.data.tfcoil.dx_tf_turn_conduit_full_average, "OP ", ) - po.ovarre( - self.outfile, - "Area of conductor (m²)", - "(conductor_area)", - self.data.superconducting_tfcoil.conductor_area, - "OP ", - ) - po.ovarre( - self.outfile, - "REBCO area of conductor (m²)", - "(a_tf_croco_strand_rebco)", - self.data.superconducting_tfcoil.conductor_rebco_area, - "OP ", - ) po.ovarre( self.outfile, "Area of central copper bar (m²)", @@ -4916,20 +4832,6 @@ def output_croco_info(self) -> None: self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy, "OP ", ) - po.ovarre( - self.outfile, - "Solder area of conductor (m²)", - "(a_tf_croco_strand_solder)", - self.data.superconducting_tfcoil.conductor_solder_area, - "OP ", - ) - po.ovarre( - self.outfile, - "Jacket area of conductor (m²)", - "(jacket_area)", - self.data.superconducting_tfcoil.conductor_jacket_area, - "OP ", - ) po.ovarre( self.outfile, @@ -4938,13 +4840,6 @@ def output_croco_info(self) -> None: self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical, "OP ", ) - po.ovarre( - self.outfile, - "Critical current of conductor (A) ", - "(conductor_critical_current)", - self.data.superconducting_tfcoil.conductor_critical_current, - "OP ", - ) @staticmethod From e3addbc21ecd94de5aef74a2e7237aa6f610bbe6 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 16 Jun 2026 10:30:48 +0100 Subject: [PATCH 19/20] Enhance CICC and CroCo TF coil area calculations and add new data structure for area fractions --- process/models/tfcoil/superconducting.py | 431 ++++++++++++++-------- tests/unit/models/tfcoil/test_sctfcoil.py | 2 +- 2 files changed, 279 insertions(+), 154 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 08146031b4..98f84899c1 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -474,9 +474,48 @@ def output_general_superconducting_tf_info(self) -> None: # WP material fraction po.osubhd(self.outfile, "TF winding pack (WP) material area/fractions:") + + po.ovarre( + self.outfile, + "Area of all turn insulation in WP [m²]", + "(a_tf_coil_wp_turn_insulation)", + self.data.tfcoil.a_tf_coil_wp_turn_insulation, + ) + po.ovarre( + self.outfile, + "Total insulation area in TF coil (turn and WP) [m²]", + "(a_tf_coil_inboard_insulation)", + self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation, + ) + po.ovarre( + self.outfile, + "Total steel area in inboard TF coil (turn and case) [m²]", + "(a_tf_coil_inboard_steel)", + self.data.superconducting_tfcoil.a_tf_coil_inboard_steel, + ) + po.ovarre( + self.outfile, + "Total conductor area in WP [m²]", + "(a_tf_wp_conductor)", + self.data.tfcoil.a_tf_wp_conductor, + ) + po.ovarre( + self.outfile, + "Total additional void area in WP [m²]", + "(a_tf_wp_extra_void)", + self.data.tfcoil.a_tf_wp_extra_void, + ) + + po.ovarre( + self.outfile, + "Area of all coolant channels in WP [m²]", + "(a_tf_wp_coolant_channels)", + self.data.tfcoil.a_tf_wp_coolant_channels, + ) + po.ovarre( self.outfile, - "Steel WP cross-section (total) (m²)", + "Steel WP cross-section (total) [m²]", "(a_tf_wp_steel*n_tf_coils)", self.data.tfcoil.a_tf_wp_steel * self.data.tfcoil.n_tf_coils, ) @@ -518,9 +557,9 @@ def output_general_superconducting_tf_info(self) -> None: self.data.tfcoil.i_tf_turns_integer, ) if self.data.tfcoil.i_tf_turns_integer == 0: - po.ocmmnt(self.outfile, " Non-integer number of turns") + po.ocmmnt(self.outfile, "-> Non-integer number of turns") else: - po.ocmmnt(self.outfile, " Integer number of turns") + po.ocmmnt(self.outfile, "-> Integer number of turns") po.ovarre( self.outfile, @@ -634,7 +673,7 @@ def output_general_superconducting_tf_info(self) -> None: po.oblnkl(self.outfile) po.ovarre( self.outfile, - "TF coil turn area (m²)", + "TF coil turn area [m²]", "(a_tf_turn)", self.data.tfcoil.a_tf_turn, ) @@ -651,6 +690,12 @@ def output_general_superconducting_tf_info(self) -> None: "(a_tf_turn_cable_space_effective)", self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective, ) + po.ovarre( + self.outfile, + "Area of steel in turn [m²]", + "(a_tf_turn_steel)", + self.data.tfcoil.a_tf_turn_steel, + ) po.ovarre( self.outfile, @@ -2247,6 +2292,21 @@ class TFGeneralTurnGeometry: dx_tf_turn_cable_space_average: float +@dataclass(slots=True) +class SuperconTFAreasFractions: + """Superconducting TF coil winding pack areas and fractions.""" + + a_tf_wp_coolant_channels: float + a_tf_wp_conductor: float + a_tf_wp_extra_void: float + a_tf_coil_wp_turn_insulation: float + a_tf_wp_steel: float + a_tf_coil_inboard_steel: float + f_a_tf_coil_inboard_steel: float + a_tf_coil_inboard_insulation: float + f_a_tf_coil_inboard_insulation: float + + @dataclass(slots=True) class CICCAveragedTurnGeometry(TFGeneralTurnGeometry): """Averaged turn geometry for a CICC conductor with LTS cables.""" @@ -2377,6 +2437,13 @@ def run(self, output: bool = False): self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = ( int_turn_geometry.dx_tf_turn_cable_space_average ) + self.data.superconducting_tfcoil.a_tf_turn_cable_space_effective = ( + int_turn_geometry.a_tf_turn_cable_space_effective + ) + self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling = ( + int_turn_geometry.f_a_tf_turn_cable_space_cooling + ) + self.data.tfcoil.dx_tf_turn_general = int_turn_geometry.dx_tf_turn_general # Calculate number of cables in turn if CICC conductor # --------------------------------------------------- @@ -2396,65 +2463,39 @@ def run(self, output: bool = False): n_tf_turn_superconducting_cables=self.data.superconducting_tfcoil.n_tf_turn_superconducting_cables, ) - # Areas and fractions - # ------------------- - # Central helium channel down the conductor core [m2] - self.data.tfcoil.a_tf_wp_coolant_channels = ( - 0.25e0 - * self.data.tfcoil.n_tf_coil_turns - * np.pi - * self.data.tfcoil.dia_tf_turn_coolant_channel**2 - ) - - # Total conductor cross-sectional area, taking account of void area - # and central helium channel [m2] - self.data.tfcoil.a_tf_wp_conductor = ( - self.data.tfcoil.a_tf_turn_cable_space_no_void - * self.data.tfcoil.n_tf_coil_turns - * (1.0e0 - self.data.tfcoil.f_a_tf_turn_cable_space_extra_void) - - self.data.tfcoil.a_tf_wp_coolant_channels + inboard_areas_fractions = self.tf_cicc_inboard_areas_and_fractions( + n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns, + dia_tf_turn_coolant_channel=self.data.tfcoil.dia_tf_turn_coolant_channel, + a_tf_turn_cable_space_no_void=self.data.tfcoil.a_tf_turn_cable_space_no_void, + f_a_tf_turn_cable_space_extra_void=self.data.tfcoil.f_a_tf_turn_cable_space_extra_void, + a_tf_turn_insulation=self.data.tfcoil.a_tf_turn_insulation, + a_tf_turn_steel=self.data.tfcoil.a_tf_turn_steel, + n_tf_coils=self.data.tfcoil.n_tf_coils, + a_tf_inboard_total=self.data.tfcoil.a_tf_inboard_total, + a_tf_coil_inboard_case=self.data.tfcoil.a_tf_coil_inboard_case, + a_tf_wp_ground_insulation=self.data.superconducting_tfcoil.a_tf_wp_ground_insulation, ) - # Void area in conductor for He, not including central channel [m2] - self.data.tfcoil.a_tf_wp_extra_void = ( - self.data.tfcoil.a_tf_turn_cable_space_no_void - * self.data.tfcoil.n_tf_coil_turns - * self.data.tfcoil.f_a_tf_turn_cable_space_extra_void + self.data.tfcoil.a_tf_wp_coolant_channels = ( + inboard_areas_fractions.a_tf_wp_coolant_channels ) - - # Area of inter-turn insulation: total [m2] + self.data.tfcoil.a_tf_wp_conductor = inboard_areas_fractions.a_tf_wp_conductor + self.data.tfcoil.a_tf_wp_extra_void = inboard_areas_fractions.a_tf_wp_extra_void self.data.tfcoil.a_tf_coil_wp_turn_insulation = ( - self.data.tfcoil.n_tf_coil_turns * self.data.tfcoil.a_tf_turn_insulation + inboard_areas_fractions.a_tf_coil_wp_turn_insulation ) - - # Area of steel structure in winding pack [m2] - self.data.tfcoil.a_tf_wp_steel = ( - self.data.tfcoil.n_tf_coil_turns * self.data.tfcoil.a_tf_turn_steel - ) - - # Inboard coil steel area [m2] + self.data.tfcoil.a_tf_wp_steel = inboard_areas_fractions.a_tf_wp_steel self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = ( - self.data.tfcoil.a_tf_coil_inboard_case + self.data.tfcoil.a_tf_wp_steel + inboard_areas_fractions.a_tf_coil_inboard_steel ) - - # Inboard coil steel fraction [-] self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = ( - self.data.tfcoil.n_tf_coils - * self.data.superconducting_tfcoil.a_tf_coil_inboard_steel - / self.data.tfcoil.a_tf_inboard_total + inboard_areas_fractions.f_a_tf_coil_inboard_steel ) - - # Inboard coil insulation cross-section [m2] self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = ( - self.data.tfcoil.a_tf_coil_wp_turn_insulation - + self.data.superconducting_tfcoil.a_tf_wp_ground_insulation + inboard_areas_fractions.a_tf_coil_inboard_insulation ) - - # Inboard coil insulation fraction [-] self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = ( - self.data.tfcoil.n_tf_coils - * self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation - / self.data.tfcoil.a_tf_inboard_total + inboard_areas_fractions.f_a_tf_coil_inboard_insulation ) # Negative areas or fractions error reporting @@ -3505,7 +3546,7 @@ def tf_cable_in_conduit_integer_turn_geometry( ) # Average turn dimension [m] - data.tfcoil.dx_tf_turn_general = np.sqrt(dr_tf_turn * dx_tf_turn) + dx_tf_turn_general = np.sqrt(dr_tf_turn * dx_tf_turn) # Number of TF turns n_tf_coil_turns = np.double(n_tf_wp_layers * n_tf_wp_pancakes) @@ -3537,7 +3578,7 @@ def tf_cable_in_conduit_integer_turn_geometry( # Calculate the true effective cable space by taking away the cooling # channel and the extra void fraction - data.superconducting_tfcoil.a_tf_turn_cable_space_effective = ( + a_tf_turn_cable_space_effective = ( a_tf_turn_cable_space_no_void - # Coolant channel area @@ -3553,9 +3594,8 @@ def tf_cable_in_conduit_integer_turn_geometry( ) ) - data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling = 1 - ( - data.superconducting_tfcoil.a_tf_turn_cable_space_effective - / a_tf_turn_cable_space_no_void + f_a_tf_turn_cable_space_cooling = 1 - ( + a_tf_turn_cable_space_effective / a_tf_turn_cable_space_no_void ) if a_tf_turn_cable_space_no_void <= 0.0e0: @@ -3601,10 +3641,86 @@ def tf_cable_in_conduit_integer_turn_geometry( dr_tf_turn_cable_space=dr_tf_turn_cable_space, dx_tf_turn_cable_space=dx_tf_turn_cable_space, dx_tf_turn_cable_space_average=dx_tf_turn_cable_space_average, + a_tf_turn_cable_space_effective=a_tf_turn_cable_space_effective, + f_a_tf_turn_cable_space_cooling=f_a_tf_turn_cable_space_cooling, + dx_tf_turn_general=dx_tf_turn_general, ) # ------------- + @staticmethod + def tf_cicc_inboard_areas_and_fractions( + n_tf_coil_turns: int, + dia_tf_turn_coolant_channel: float, + a_tf_turn_cable_space_no_void: float, + f_a_tf_turn_cable_space_extra_void: float, + a_tf_turn_insulation: float, + a_tf_turn_steel: float, + n_tf_coils: int, + a_tf_inboard_total: float, + a_tf_coil_inboard_case: float, + a_tf_wp_ground_insulation: float, + ) -> SuperconTFAreasFractions: + + # Areas and fractions + # ------------------- + # Central helium channel down the conductor core [m2] + a_tf_wp_coolant_channels = ( + 0.25e0 * n_tf_coil_turns * np.pi * dia_tf_turn_coolant_channel**2 + ) + + # Total conductor cross-sectional area, taking account of void area + # and central helium channel [m2] + a_tf_wp_conductor = ( + a_tf_turn_cable_space_no_void + * n_tf_coil_turns + * (1.0e0 - f_a_tf_turn_cable_space_extra_void) + - a_tf_wp_coolant_channels + ) + + # Void area in conductor for He, not including central channel [m2] + a_tf_wp_extra_void = ( + a_tf_turn_cable_space_no_void + * n_tf_coil_turns + * f_a_tf_turn_cable_space_extra_void + ) + + # Area of inter-turn insulation: total [m2] + a_tf_coil_wp_turn_insulation = n_tf_coil_turns * a_tf_turn_insulation + + # Area of steel structure in winding pack [m2] + a_tf_wp_steel = n_tf_coil_turns * a_tf_turn_steel + + # Inboard coil steel area [m2] + a_tf_coil_inboard_steel = a_tf_coil_inboard_case + a_tf_wp_steel + + # Inboard coil steel fraction [-] + f_a_tf_coil_inboard_steel = ( + n_tf_coils * a_tf_coil_inboard_steel / a_tf_inboard_total + ) + + # Inboard coil insulation cross-section [m2] + a_tf_coil_inboard_insulation = ( + a_tf_coil_wp_turn_insulation + a_tf_wp_ground_insulation + ) + + # Inboard coil insulation fraction [-] + f_a_tf_coil_inboard_insulation = ( + n_tf_coils * a_tf_coil_inboard_insulation / a_tf_inboard_total + ) + + return SuperconTFAreasFractions( + a_tf_wp_coolant_channels=a_tf_wp_coolant_channels, + a_tf_wp_conductor=a_tf_wp_conductor, + a_tf_wp_extra_void=a_tf_wp_extra_void, + a_tf_coil_wp_turn_insulation=a_tf_coil_wp_turn_insulation, + a_tf_wp_steel=a_tf_wp_steel, + a_tf_coil_inboard_steel=a_tf_coil_inboard_steel, + f_a_tf_coil_inboard_steel=f_a_tf_coil_inboard_steel, + a_tf_coil_inboard_insulation=a_tf_coil_inboard_insulation, + f_a_tf_coil_inboard_insulation=f_a_tf_coil_inboard_insulation, + ) + def output_cable_in_conduit_cable_info(self) -> None: """Outputs the calculated cable in condutit cable space geometry information for the TF coil.""" po.oheadr(self.outfile, "TF CICC Cable Space Information") @@ -3640,50 +3756,6 @@ def output_cable_in_conduit_cable_info(self) -> None: ) po.oblnkl(self.outfile) - po.ovarre( - self.outfile, - "Area of steel in turn", - "(a_tf_turn_steel)", - self.data.tfcoil.a_tf_turn_steel, - ) - po.ovarre( - self.outfile, - "Area of all turn insulation in WP", - "(a_tf_coil_wp_turn_insulation)", - self.data.tfcoil.a_tf_coil_wp_turn_insulation, - ) - po.ovarre( - self.outfile, - "Total insulation area in TF coil (turn and WP)", - "(a_tf_coil_inboard_insulation)", - self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation, - ) - po.ovarre( - self.outfile, - "Total steel area in inboard TF coil (turn and case)", - "(a_tf_coil_inboard_steel)", - self.data.superconducting_tfcoil.a_tf_coil_inboard_steel, - ) - po.ovarre( - self.outfile, - "Total conductor area in WP", - "(a_tf_wp_conductor)", - self.data.tfcoil.a_tf_wp_conductor, - ) - po.ovarre( - self.outfile, - "Total additional void area in WP", - "(a_tf_wp_extra_void)", - self.data.tfcoil.a_tf_wp_extra_void, - ) - - po.ovarre( - self.outfile, - "Area of all coolant channels in WP", - "(a_tf_wp_coolant_channels)", - self.data.tfcoil.a_tf_wp_coolant_channels, - ) - po.ovarre( self.outfile, "Copper area fraction of cable conductor", @@ -3697,6 +3769,8 @@ def output_cable_in_conduit_cable_info(self) -> None: 1 - self.data.tfcoil.f_a_tf_turn_cable_copper, ) + po.oblnkl(self.outfile) + po.ovarin( self.outfile, "Elastic properties behavior", @@ -3798,56 +3872,6 @@ def run(self, output: bool = False): "Integer turn geometry not implemented for CroCo conductor." ) - # Areas and fractions - # ------------------- - # Central helium channel down the conductor core [m²] - # No central channel in CroCo conductor, - self.data.tfcoil.a_tf_wp_coolant_channels = 0.0 - - self.data.tfcoil.f_a_tf_turn_cable_space_extra_void = 0.0 - - # Void area in conductor for He, not including central channel [m²] - self.data.tfcoil.a_tf_wp_extra_void = ( - self.data.tfcoil.a_tf_turn_cable_space_no_void - * self.data.tfcoil.n_tf_coil_turns - * self.data.tfcoil.f_a_tf_turn_cable_space_extra_void - ) - - # Area of inter-turn insulation: total [m²] - self.data.tfcoil.a_tf_coil_wp_turn_insulation = ( - self.data.tfcoil.n_tf_coil_turns * self.data.tfcoil.a_tf_turn_insulation - ) - - # Area of steel structure in winding pack [m²] - self.data.tfcoil.a_tf_wp_steel = ( - self.data.tfcoil.n_tf_coil_turns * self.data.tfcoil.a_tf_turn_steel - ) - - # Inboard coil steel area [m²] - self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = ( - self.data.tfcoil.a_tf_coil_inboard_case + self.data.tfcoil.a_tf_wp_steel - ) - - # Inboard coil steel fraction [-] - self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = ( - self.data.tfcoil.n_tf_coils - * self.data.superconducting_tfcoil.a_tf_coil_inboard_steel - / self.data.tfcoil.a_tf_inboard_total - ) - - # Inboard coil insulation cross-section [m²] - self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = ( - self.data.tfcoil.a_tf_coil_wp_turn_insulation - + self.data.superconducting_tfcoil.a_tf_wp_ground_insulation - ) - - # Inboard coil insulation fraction [-] - self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = ( - self.data.tfcoil.n_tf_coils - * self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation - / self.data.tfcoil.a_tf_inboard_total - ) - croco_cable_space_geometry: CroCoCableSpaceGeometry = self.tf_turn_croco_cable_space_properties( dx_tf_turn_conduit_full_average=self.data.tfcoil.dx_tf_turn_conduit_full_average, dx_tf_turn_steel=self.data.tfcoil.dx_tf_turn_steel, @@ -3922,6 +3946,42 @@ def run(self, output: bool = False): self.data.superconducting_tfcoil.a_tf_croco_strand ) + self.data.tfcoil.f_a_tf_turn_cable_space_extra_void = 0.0 + + inbaord_areas_fractions = self.tf_croco_inboard_areas_and_fractions( + a_tf_turn_cable_space_no_void=self.data.tfcoil.a_tf_turn_cable_space_no_void, + n_tf_coil_turns=self.data.tfcoil.n_tf_coil_turns, + f_a_tf_turn_cable_space_extra_void=self.data.tfcoil.f_a_tf_turn_cable_space_extra_void, + a_tf_turn_insulation=self.data.tfcoil.a_tf_turn_insulation, + a_tf_turn_steel=self.data.tfcoil.a_tf_turn_steel, + a_tf_coil_inboard_case=self.data.tfcoil.a_tf_coil_inboard_case, + n_tf_coils=self.data.tfcoil.n_tf_coils, + a_tf_inboard_total=self.data.tfcoil.a_tf_inboard_total, + a_tf_wp_ground_insulation=self.data.superconducting_tfcoil.a_tf_wp_ground_insulation, + a_tf_croco_strand=self.data.superconducting_tfcoil.a_tf_croco_strand, + ) + self.data.tfcoil.a_tf_wp_coolant_channels = ( + inbaord_areas_fractions.a_tf_wp_coolant_channels + ) + self.data.tfcoil.a_tf_wp_conductor = inbaord_areas_fractions.a_tf_wp_conductor + self.data.tfcoil.a_tf_wp_extra_void = inbaord_areas_fractions.a_tf_wp_extra_void + self.data.tfcoil.a_tf_coil_wp_turn_insulation = ( + inbaord_areas_fractions.a_tf_coil_wp_turn_insulation + ) + self.data.tfcoil.a_tf_wp_steel = inbaord_areas_fractions.a_tf_wp_steel + self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = ( + inbaord_areas_fractions.a_tf_coil_inboard_steel + ) + self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = ( + inbaord_areas_fractions.f_a_tf_coil_inboard_steel + ) + self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = ( + inbaord_areas_fractions.a_tf_coil_inboard_insulation + ) + self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = ( + inbaord_areas_fractions.f_a_tf_coil_inboard_insulation + ) + # Area of core = area of strand self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar = ( self.data.superconducting_tfcoil.a_tf_croco_strand @@ -4000,9 +4060,9 @@ def run(self, output: bool = False): self.data.superconducting_tfcoil.b_tf_superconductor_critical_zero_temp_strain = superconductor_critical_properties.bc20m self.data.superconducting_tfcoil.temp_tf_superconductor_critical_zero_field_strain = superconductor_critical_properties.tc0m - self.data.superconducting_tfcoil.c_tf_turn_cables_critical = ( - superconductor_critical_properties.c_turn_cables_critical - ) + self.data.superconducting_tfcoil.cur_tf_turn_croco_strand_critical = ( + self.data.superconducting_tfcoil.c_tf_turn_cables_critical + ) = superconductor_critical_properties.c_turn_cables_critical if self.data.tfcoil.i_str_wp == 0: strain = self.data.tfcoil.str_tf_con_res @@ -4649,6 +4709,71 @@ def tf_turn_croco_cable_space_properties( f_a_tf_turn_cable_space_cooling=f_a_tf_turn_cable_space_cooling, ) + @staticmethod + def tf_croco_inboard_areas_and_fractions( + a_tf_turn_cable_space_no_void: float, + n_tf_coil_turns: int, + f_a_tf_turn_cable_space_extra_void: float, + a_tf_turn_insulation: float, + a_tf_turn_steel: float, + a_tf_coil_inboard_case: float, + n_tf_coils: int, + a_tf_inboard_total: float, + a_tf_wp_ground_insulation: float, + a_tf_croco_strand: float, + ) -> SuperconTFAreasFractions: + + # Areas and fractions + # ------------------- + # Central helium channel down the conductor core [m²] + # No central channel in CroCo conductor, + a_tf_wp_coolant_channels = 0.0 + + a_tf_wp_conductor = n_tf_coil_turns * a_tf_croco_strand * N_CROCO_STRANDS_TURN + + # Void area in conductor for He, not including central channel [m²] + a_tf_wp_extra_void = ( + a_tf_turn_cable_space_no_void + * n_tf_coil_turns + * f_a_tf_turn_cable_space_extra_void + ) + + # Area of inter-turn insulation: total [m²] + a_tf_coil_wp_turn_insulation = n_tf_coil_turns * a_tf_turn_insulation + + # Area of steel structure in winding pack [m²] + a_tf_wp_steel = n_tf_coil_turns * a_tf_turn_steel + + # Inboard coil steel area [m²] + a_tf_coil_inboard_steel = a_tf_coil_inboard_case + a_tf_wp_steel + + # Inboard coil steel fraction [-] + f_a_tf_coil_inboard_steel = ( + n_tf_coils * a_tf_coil_inboard_steel / a_tf_inboard_total + ) + + # Inboard coil insulation cross-section [m²] + a_tf_coil_inboard_insulation = ( + a_tf_coil_wp_turn_insulation + a_tf_wp_ground_insulation + ) + + # Inboard coil insulation fraction [-] + f_a_tf_coil_inboard_insulation = ( + n_tf_coils * a_tf_coil_inboard_insulation / a_tf_inboard_total + ) + + return SuperconTFAreasFractions( + a_tf_wp_coolant_channels=a_tf_wp_coolant_channels, + a_tf_wp_conductor=a_tf_wp_conductor, + a_tf_wp_extra_void=a_tf_wp_extra_void, + a_tf_coil_wp_turn_insulation=a_tf_coil_wp_turn_insulation, + a_tf_wp_steel=a_tf_wp_steel, + a_tf_coil_inboard_steel=a_tf_coil_inboard_steel, + f_a_tf_coil_inboard_steel=f_a_tf_coil_inboard_steel, + a_tf_coil_inboard_insulation=a_tf_coil_inboard_insulation, + f_a_tf_coil_inboard_insulation=f_a_tf_coil_inboard_insulation, + ) + def croco_voltage(self) -> float: if self.data.tfcoil.quench_model == "linear": self.data.superconducting_tfcoil.time2 = ( diff --git a/tests/unit/models/tfcoil/test_sctfcoil.py b/tests/unit/models/tfcoil/test_sctfcoil.py index b296253b61..fbf441fe2e 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -1153,7 +1153,7 @@ def test_tf_cable_in_conduit_integer_turn_geometry( tfintegerturngeomparam.expected_t_conductor ) - assert cicc_sctfcoil.data.tfcoil.dx_tf_turn_general == pytest.approx( + assert integer_turn_geometry.dx_tf_turn_general == pytest.approx( tfintegerturngeomparam.expected_dx_tf_turn_general ) From 919f709a8bd81647de58ddff7016a6127e157c51 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 22 Jun 2026 10:53:14 +0100 Subject: [PATCH 20/20] Update test values to try and align with previous solution --- process/core/input.py | 11 ----------- .../input_files/spherical_tokamak_eval.IN.DAT | 4 ++++ tests/regression/input_files/st_regression.IN.DAT | 6 ++++++ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index 9ab657301b..e60b1cc74f 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -675,17 +675,6 @@ def __post_init__(self): "superconducting_tfcoil", float, range=(1e-08, 0.0001), - additional_actions=lambda _n, rt, _i, _c: ( - rt <= 1e-6 - or warn( - ( - "the relationship between REBCO layer thickness and current density is not linear." - "REBCO layer thicknesses > 1um should be considered an aggressive extrapolation of" - "current HTS technology and any results must be considered speculative." - ), - stacklevel=1, - ) - ), ), "redun_vacp": InputVariable("costs", float, range=(0.0, 100.0)), "residual_sig_hoop": InputVariable("cs_fatigue", float, range=(0.0, 1000000000.0)), diff --git a/tests/regression/input_files/spherical_tokamak_eval.IN.DAT b/tests/regression/input_files/spherical_tokamak_eval.IN.DAT index d8598bb15f..ab1f63a14e 100644 --- a/tests/regression/input_files/spherical_tokamak_eval.IN.DAT +++ b/tests/regression/input_files/spherical_tokamak_eval.IN.DAT @@ -70,6 +70,10 @@ iohcl = 0 * Switch for existence of central solenoid; i_cs_precomp = 0 * Switch for existence of central solenoid pre-compression structure; i_tf_inside_cs = 0 * Switch for placing the TF coil inside the CS i_tf_turn_type = 2 * CroCo Turn geometry for HTS Tapes +dx_tf_hts_tape_rebco = 1.0e-6 +dx_tf_croco_strand_copper = 2.0e-3 +dx_tf_hts_tape_copper = 2.0e-4 +dx_tf_hts_tape_hastelloy = 1e-5 dr_cs = 0.20016400484967947 * Central solenoid thickness (m) (`iteration variable 16`) i_r_cp_top = 2 * Switch selecting the he parametrization of the outer radius of the top of the CP part of the TF coil dr_fw_plasma_gap_inboard = 0.1 * Gap between plasma and first wall; inboard side (m) (if `i_plasma_wall_gap=1`) diff --git a/tests/regression/input_files/st_regression.IN.DAT b/tests/regression/input_files/st_regression.IN.DAT index 84c8a3c9fc..68cc25a74d 100644 --- a/tests/regression/input_files/st_regression.IN.DAT +++ b/tests/regression/input_files/st_regression.IN.DAT @@ -784,6 +784,12 @@ pseprmax = 40.0 *-------------------------------- *TF Coil* --------------------------------------------------------------------------------------------------------------------------------------------------------------* *‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾* +dx_tf_hts_tape_rebco = 1.0e-6 +dx_tf_croco_strand_copper = 2.0e-3 +dx_tf_hts_tape_copper = 2.0e-4 +dx_tf_hts_tape_hastelloy = 1e-5 + + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ General settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾