From 769a9767f7cfe0e8a7fce3cbef1968f764672e30 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 10:44:26 +0100 Subject: [PATCH 01/21] 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 55a4737f89..b5eebb54ee 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -18,6 +18,7 @@ N_CROCO_STRANDS_TURN, SuperconductorMaterial, SuperconductorModel, + SuperconductorShape, calculate_croco_cable_geometry, ) from process.models.tfcoil import quench @@ -2792,6 +2793,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 @@ -2986,14 +2998,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 bd7557124b9737dafdeaa2a9a4d102dd8527fbd7 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 11:19:54 +0100 Subject: [PATCH 02/21] 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 285555102f..b69993fb9a 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -267,22 +267,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 be73adf239f5ca3859102ebd92f616307cad0354 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 11:33:29 +0100 Subject: [PATCH 03/21] Refactor CROCOSuperconductingTFCoil to streamline superconductor property calculations and remove deprecated models --- process/models/tfcoil/superconducting.py | 320 +++++++++++++---------- 1 file changed, 185 insertions(+), 135 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index b5eebb54ee..05d300d3c7 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3026,86 +3026,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 @@ -4008,44 +3928,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 = 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 - ) - d_sc_tf.j_tf_superconductor_critical = ( - superconductor_critical_properties.j_superconductor_critical - ) - d_sc_tf.f_c_tf_turn_operating_critical = ( - superconductor_critical_properties.f_c_tf_turn_operating_critical - ) - d_sc_tf.j_tf_superconductor = ( - superconductor_critical_properties.j_superconductor - ) - d_sc_tf.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 + ) - d_sc_tf.b_tf_superconductor_critical_zero_temp_strain = ( - superconductor_critical_properties.bc20m - ) - d_sc_tf.temp_tf_superconductor_critical_zero_field_strain = ( - superconductor_critical_properties.tc0m - ) - d_sc_tf.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 ( @@ -4415,33 +4334,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." + ) - d_sc_tf = self.data.superconducting_tfcoil + 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)" + ) - d_sc_tf.cur_tf_turn_croco_strand_critical = j_crit_sc * d_sc_tf.a_tf_croco_strand + # ================================================================= + + # 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_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 - d_sc_tf.conductor_critical_current = ( - d_sc_tf.cur_tf_turn_croco_strand_critical * N_CROCO_STRANDS_TURN + self.data.superconducting_tfcoil.conductor_critical_current = ( + cur_tf_turn_croco_strand_critical * N_CROCO_STRANDS_TURN ) d_sc_tf.tf_coppera_m2 = cur_tf_turn / d_sc_tf.a_tf_turn_croco_cable_space_copper @@ -4451,18 +4497,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 @@ -4470,13 +4520,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=d_sc_tf.cur_tf_turn_croco_strand_critical, + c_turn_cables_critical=cur_tf_turn_croco_strand_critical, ) @staticmethod From 82a45a12f95fc5ccfd4b99238d55dc12264caeee Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 12:03:20 +0100 Subject: [PATCH 04/21] 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 05d300d3c7..a9ba6c02ba 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -4422,22 +4422,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)" - ) # ================================================================= @@ -4466,19 +4450,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 5d4f1b64854d850aa7eec0e84459b50f8cb2459b Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 13:42:41 +0100 Subject: [PATCH 05/21] 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 e92d96ff09..573c143cb8 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -7527,6 +7527,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" @@ -7805,6 +7807,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 20a93374fd..d4e5c9f675 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -814,34 +814,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 5a3db89248d876cbabe11c341c31f62b5222360c Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 14:03:23 +0100 Subject: [PATCH 06/21] 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 a9ba6c02ba..ea1bf28b43 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -890,6 +890,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 e5f5ad9f323021f21e3930f2c824a19c2b6e7ff2 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:04:10 +0100 Subject: [PATCH 07/21] Add copper area calculations and update related attributes in CROCOSuperconductingTFCoil --- .../superconducting_tf_coil_variables.py | 11 +++- process/models/tfcoil/superconducting.py | 65 +++++++++---------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index b69993fb9a..3aa485ecef 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -268,9 +268,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 ea1bf28b43..3bbed8c2fc 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3896,8 +3896,25 @@ def run(self, output: bool = False): d_sc_tf.a_tf_croco_strand_copper_total * N_CROCO_STRANDS_TURN + d_sc_tf.a_tf_turn_croco_copper_bar ) - d_sc_tf.conductor_copper_fraction = ( - d_sc_tf.a_tf_turn_croco_cable_space_copper / d_sc_tf.conductor_area + + self.data.superconducting_tfcoil.a_tf_turn_copper_total = ( + self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper + ) + + 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. @@ -3945,6 +3962,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 = ( @@ -4346,6 +4364,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 @@ -4477,10 +4496,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 = ( @@ -4717,27 +4733,6 @@ def output_croco_info(self) -> None: d_sc_tf.a_tf_croco_strand_solder, "OP ", ) - po.ovarre( - self.outfile, - "Total: area of CroCo strand (m²) ", - "(a_tf_croco_strand)", - d_sc_tf.a_tf_croco_strand, - "OP ", - ) - if ( - abs( - d_sc_tf.a_tf_croco_strand - - ( - d_sc_tf.a_tf_croco_strand_rebco - + d_sc_tf.a_tf_croco_strand_copper_total - + d_sc_tf.a_tf_croco_strand_hastelloy - + d_sc_tf.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") @@ -4770,8 +4765,8 @@ def output_croco_info(self) -> None: po.ovarre( self.outfile, "Area of conductor (m²)", - "(area)", - d_sc_tf.conductor_area, + "(conductor_area)", + self.data.superconducting_tfcoil.conductor_area, "OP ", ) po.ovarre( @@ -4784,22 +4779,22 @@ def output_croco_info(self) -> None: po.ovarre( self.outfile, "Area of central copper bar (m²)", - "(copper_bar_area)", - d_sc_tf.a_tf_turn_croco_copper_bar, + "(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)", - d_sc_tf.a_tf_turn_croco_cable_space_copper, + "(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)", - d_sc_tf.a_tf_turn_croco_hastelloy, + "(a_tf_turn_croco_hastelloy)", + self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy, "OP ", ) po.ovarre( From b51acb20eb56bc362f1ac19dc6ac50f69e79bdac Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:15:25 +0100 Subject: [PATCH 08/21] 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, 9 insertions(+), 22 deletions(-) diff --git a/process/data_structure/superconducting_tf_coil_variables.py b/process/data_structure/superconducting_tf_coil_variables.py index 3aa485ecef..ad69d229f3 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -259,14 +259,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²)""" @@ -280,7 +275,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 3bbed8c2fc..d31fd53f23 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3915,14 +3915,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 # noqa: E501 - d_sc_tf.conductor_helium_area = np.pi / 2.0 * d_sc_tf.dia_tf_turn_croco_cable**2 - d_sc_tf.conductor_helium_fraction = ( - d_sc_tf.conductor_helium_area / d_sc_tf.conductor_area - ) + ) / self.data.tfcoil.a_tf_turn_cable_space_no_void d_sc_tf.a_tf_turn_croco_hastelloy = ( d_sc_tf.a_tf_croco_strand_hastelloy * N_CROCO_STRANDS_TURN @@ -3941,8 +3934,9 @@ def run(self, output: bool = False): d_sc_tf.conductor_rebco_area = ( d_sc_tf.a_tf_croco_strand_rebco * N_CROCO_STRANDS_TURN ) - d_sc_tf.conductor_rebco_fraction = ( - d_sc_tf.conductor_rebco_area / d_sc_tf.conductor_area + 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 @@ -4811,13 +4805,6 @@ def output_croco_info(self) -> None: d_sc_tf.conductor_jacket_area, "OP ", ) - po.ovarre( - self.outfile, - "Helium area of conductor (m²)", - "(helium_area)", - d_sc_tf.conductor_helium_area, - "OP ", - ) po.ovarre( self.outfile, From c552f9cf7a631344c9a760a05637160358043dd1 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:36:42 +0100 Subject: [PATCH 09/21] 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 d31fd53f23..8ef7ad7960 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3783,15 +3783,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 @@ -3897,6 +3888,12 @@ def run(self, output: bool = False): + d_sc_tf.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 490deca68bd2e1c4536e5a6b7ca64f15de576b2b Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:46:28 +0100 Subject: [PATCH 10/21] 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 | 138 ++++++++++++++------- tests/unit/models/tfcoil/test_sctfcoil.py | 20 +-- 4 files changed, 106 insertions(+), 58 deletions(-) diff --git a/process/core/io/obsolete_vars.py b/process/core/io/obsolete_vars.py index 2b34765c7e..7877a6bb48 100644 --- a/process/core/io/obsolete_vars.py +++ b/process/core/io/obsolete_vars.py @@ -49,7 +49,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 e15d317a3b..9091b3f6fb 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 8ef7ad7960..9c7dc72273 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -610,14 +610,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)", d_sc_tf.dx_tf_turn_cable_space_average, "OP ", @@ -2195,7 +2195,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 @@ -2216,7 +2216,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 @@ -2269,10 +2269,12 @@ def run(self, output: bool = False): self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general self.data.tfcoil.c_tf_turn = avg_turn_geometry.c_tf_turn self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general - d_sc_tf.dr_tf_turn = avg_turn_geometry.dr_tf_turn - d_sc_tf.dx_tf_turn = avg_turn_geometry.dx_tf_turn - self.data.tfcoil.t_conductor = avg_turn_geometry.t_conductor - d_sc_tf.radius_tf_turn_cable_space_corners = ( + 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.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 ) d_sc_tf.dx_tf_turn_cable_space_average = ( @@ -2314,12 +2316,22 @@ 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 - d_sc_tf.t_conductor_radial = int_turn_geometry.t_conductor_radial - d_sc_tf.t_conductor_toroidal = int_turn_geometry.t_conductor_toroidal - self.data.tfcoil.t_conductor = int_turn_geometry.t_conductor - d_sc_tf.dr_tf_turn_cable_space = int_turn_geometry.dr_tf_turn_cable_space - d_sc_tf.dx_tf_turn_cable_space = int_turn_geometry.dx_tf_turn_cable_space - d_sc_tf.dx_tf_turn_cable_space_average = ( + self.data.superconducting_tfcoil.t_conductor_radial = ( + int_turn_geometry.t_conductor_radial + ) + self.data.superconducting_tfcoil.t_conductor_toroidal = ( + int_turn_geometry.t_conductor_toroidal + ) + 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 + ) + self.data.superconducting_tfcoil.dx_tf_turn_cable_space = ( + int_turn_geometry.dx_tf_turn_cable_space + ) + self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = ( int_turn_geometry.dx_tf_turn_cable_space_average ) @@ -3260,7 +3272,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 @@ -3268,13 +3280,15 @@ 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 # Radius of rounded corners of cable space inside conduit [m] 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] @@ -3300,7 +3314,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, @@ -3317,7 +3331,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, @@ -3328,7 +3344,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, @@ -3421,7 +3437,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 @@ -3497,7 +3515,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, @@ -3694,7 +3712,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 @@ -3762,10 +3780,12 @@ def run(self, output: bool = False): self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general self.data.tfcoil.c_tf_turn = avg_turn_geometry.c_tf_turn self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general - d_sc_tf.dr_tf_turn = avg_turn_geometry.dr_tf_turn - d_sc_tf.dx_tf_turn = avg_turn_geometry.dx_tf_turn - self.data.tfcoil.t_conductor = avg_turn_geometry.t_conductor - d_sc_tf.dx_tf_turn_cable_space_average = ( + 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.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 ) @@ -3825,8 +3845,8 @@ def run(self, output: bool = False): / self.data.tfcoil.a_tf_inboard_total ) - croco_cable_space_geometry = self.tf_turn_croco_cable_space_properties( - t_conductor=self.data.tfcoil.t_conductor, + 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, ) @@ -4315,7 +4335,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 @@ -4323,13 +4343,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 - self.data.tfcoil.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=self.data.tfcoil.a_tf_turn_cable_space_no_void, @@ -4340,7 +4368,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, ) @@ -4535,25 +4563,43 @@ 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). Returns ------- - : - CroCo cable space geometry + + 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 = 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 @@ -4566,7 +4612,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 @@ -4749,8 +4797,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 ca7a56e990..589de60809 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -988,7 +988,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 @@ -1054,7 +1054,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, @@ -1088,7 +1088,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, @@ -1154,7 +1154,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 ) @@ -1214,7 +1214,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 @@ -1264,7 +1264,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, @@ -1289,7 +1289,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, @@ -1314,7 +1314,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, @@ -1339,7 +1339,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, @@ -1397,7 +1397,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 f1578591e1239012a65e28f7ee4d1ff044834ad5 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 16:50:02 +0100 Subject: [PATCH 11/21] 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 ad69d229f3..cb9dbd5817 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -126,11 +126,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 9c7dc72273..9953e384d2 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -571,15 +571,15 @@ def output_general_superconducting_tf_info(self) -> None: po.ovarre( self.outfile, "Radial width of conductor (m)", - "(t_conductor_radial)", - d_sc_tf.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)", - d_sc_tf.t_conductor_toroidal, + "(dx_tf_turn_conduit_full_toroidal)", + self.data.superconducting_tfcoil.dx_tf_turn_conduit_full_toroidal, "OP ", ) po.ovarre( @@ -2214,8 +2214,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 @@ -2316,11 +2316,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 @@ -3435,15 +3435,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 ) @@ -3497,7 +3499,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²] @@ -3513,8 +3516,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 589de60809..8f1be0cc3a 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -996,9 +996,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 @@ -1058,8 +1058,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, @@ -1092,8 +1092,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, @@ -1162,11 +1162,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 78d4af5314e0448ace2f6aa0a404bb1ff417c805 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 12 Jun 2026 17:10:18 +0100 Subject: [PATCH 12/21] 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 9091b3f6fb..9cec919c1b 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 9953e384d2..95544fc560 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -709,8 +709,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( @@ -1986,11 +1986,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` + @@ -3630,48 +3635,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.ovarre( - 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.ovarre( - self.outfile, - "minimum TF conductor temperature margin (K)", - "(temp_tf_superconductor_margin_min)", - self.data.tfcoil.temp_tf_superconductor_margin_min, - ) - po.ovarre( - self.outfile, - "TF conductor temperature margin (K)", - "(temp_tf_superconductor_margin)", - self.data.tfcoil.temp_tf_superconductor_margin, - ) po.ovarre( self.outfile, From df3a01b270c552e3753b82a7483ce7c1efef79e0 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 13:21:08 +0100 Subject: [PATCH 13/21] 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 95544fc560..08d88b4b8f 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3944,7 +3944,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, @@ -4354,7 +4353,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, @@ -4411,8 +4409,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: @@ -4474,12 +4470,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 e2b04aa2e9..29ab2a1bae 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 78f4028107..37f34ed113 100644 --- a/tests/regression/input_files/st_regression.IN.DAT +++ b/tests/regression/input_files/st_regression.IN.DAT @@ -789,7 +789,10 @@ p_plasma_separatrix_rmajor_max_mw = 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 a5f6d004d24ed49a0f7d8d4c6806b13956f584a9 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 13:34:03 +0100 Subject: [PATCH 14/21] 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 08d88b4b8f..df0a7f3b10 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -3973,6 +3973,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 4fe38e1255cbde92df44714377bd43661126e8ba Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 14:17:14 +0100 Subject: [PATCH 15/21] 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 7877a6bb48..e096c85032 100644 --- a/process/core/io/obsolete_vars.py +++ b/process/core/io/obsolete_vars.py @@ -473,6 +473,7 @@ "i_cs_stress": None, "f_nd_alpha_electron": "f_nd_alpha_thermal_electron", "cost_model": "i_cost_model", + "t_conductor": "dx_tf_turn_conduit_full_average", } OBS_VARS_HELP = { From 8a9bd72234a8b7708153af8973ecd1fec3eac008 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 14:21:52 +0100 Subject: [PATCH 16/21] 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 df0a7f3b10..e595e8ad2f 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -2809,13 +2809,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 5a7bce8e779a58ce5b482d89845084be1c76d8a3 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 15 Jun 2026 18:31:36 +0100 Subject: [PATCH 17/21] Refactor code structure for improved readability and maintainability --- process/core/input.py | 4 +- .../superconducting_tf_coil_variables.py | 19 +- process/models/tfcoil/superconducting.py | 219 +++++------------- 3 files changed, 66 insertions(+), 176 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index 1d7c132b6a..8f5d7512c4 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -297,7 +297,9 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]: "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 cb9dbd5817..f46559a045 100644 --- a/process/data_structure/superconducting_tf_coil_variables.py +++ b/process/data_structure/superconducting_tf_coil_variables.py @@ -267,33 +267,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 e595e8ad2f..6735b003a4 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. @@ -111,7 +111,7 @@ class TFWPGeometry: """WP ground insulation cross-sectional area [m²]""" -@dataclass +@dataclass(slots=True) class TFSuperconductorLimits: """Dataclass holding superconducting TF coil limits""" @@ -641,12 +641,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, "----------------------------") @@ -2188,9 +2209,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 @@ -2201,30 +2222,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): @@ -3562,26 +3582,8 @@ def output_cable_in_conduit_cable_info(self) -> None: "(len_tf_superconductor_total)", d_sc_tf.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)", - d_sc_tf.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", @@ -3669,33 +3671,20 @@ def output_cable_in_conduit_cable_info(self) -> None: ) -@dataclass -class CROCOAveragedTurnGeometry: - """Dataclass holding CroCo averaged turn geometry parameters""" - - 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: - """Dataclass holding CroCo cable space geometry parameters""" + """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): @@ -3772,6 +3761,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 @@ -3829,10 +3820,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 - d_sc_tf.conductor_area = croco_cable_space_geometry.conductor_area - d_sc_tf.conductor_jacket_area = croco_cable_space_geometry.conductor_jacket_area - d_sc_tf.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 = calculate_croco_cable_geometry( @@ -3906,24 +3895,6 @@ def run(self, output: bool = False): d_sc_tf.a_tf_turn_croco_hastelloy = ( d_sc_tf.a_tf_croco_strand_hastelloy * N_CROCO_STRANDS_TURN ) - d_sc_tf.conductor_hastelloy_fraction = ( - d_sc_tf.a_tf_turn_croco_hastelloy / d_sc_tf.conductor_area - ) - - d_sc_tf.conductor_solder_area = ( - d_sc_tf.a_tf_croco_strand_solder * N_CROCO_STRANDS_TURN - ) - d_sc_tf.conductor_solder_fraction = ( - d_sc_tf.conductor_solder_area / d_sc_tf.conductor_area - ) - - d_sc_tf.conductor_rebco_area = ( - d_sc_tf.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 / ( @@ -4494,20 +4465,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 - ) - - d_sc_tf.tf_coppera_m2 = cur_tf_turn / d_sc_tf.a_tf_turn_croco_cable_space_copper - - cur_critical = d_sc_tf.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 @@ -4553,26 +4518,7 @@ 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) @@ -4583,28 +4529,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: @@ -4757,13 +4700,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( @@ -4777,20 +4713,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)", - d_sc_tf.conductor_rebco_area, - "OP ", - ) po.ovarre( self.outfile, "Area of central copper bar (m²)", @@ -4812,20 +4734,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)", - d_sc_tf.conductor_solder_area, - "OP ", - ) - po.ovarre( - self.outfile, - "Jacket area of conductor (m²)", - "(jacket_area)", - d_sc_tf.conductor_jacket_area, - "OP ", - ) po.ovarre( self.outfile, @@ -4834,13 +4742,6 @@ def output_croco_info(self) -> None: d_sc_tf.cur_tf_turn_croco_strand_critical, "OP ", ) - po.ovarre( - self.outfile, - "Critical current of conductor (A) ", - "(conductor_critical_current)", - d_sc_tf.conductor_critical_current, - "OP ", - ) @staticmethod From 30d2981a4a80d9c35eacc950ae0107d614470cd8 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 16 Jun 2026 10:30:48 +0100 Subject: [PATCH 18/21] Enhance CICC and CroCo TF coil area calculations and add new data structure for area fractions --- process/models/tfcoil/superconducting.py | 459 ++++++++++++++-------- tests/unit/models/tfcoil/test_sctfcoil.py | 2 +- 2 files changed, 298 insertions(+), 163 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 6735b003a4..61d3f912a8 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -476,9 +476,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, ) @@ -522,9 +561,9 @@ def output_general_superconducting_tf_info(self) -> None: TFWPIntegerTurnType(self.data.tfcoil.i_tf_turns_integer) == TFWPIntegerTurnType.NON_INTEGER ): - 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, @@ -644,7 +683,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, ) @@ -661,6 +700,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, @@ -2225,6 +2270,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.""" @@ -2359,6 +2419,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 # --------------------------------------------------- @@ -2380,65 +2447,39 @@ def run(self, output: bool = False): n_tf_turn_superconducting_cables=d_sc_tf.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 - ) - - # 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_areas_fractions.a_tf_coil_wp_turn_insulation ) - - # Inboard coil steel area [m2] - d_sc_tf.a_tf_coil_inboard_steel = ( - self.data.tfcoil.a_tf_coil_inboard_case + self.data.tfcoil.a_tf_wp_steel + self.data.tfcoil.a_tf_wp_steel = inboard_areas_fractions.a_tf_wp_steel + self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = ( + inboard_areas_fractions.a_tf_coil_inboard_steel ) - - # Inboard coil steel fraction [-] - d_sc_tf.f_a_tf_coil_inboard_steel = ( - self.data.tfcoil.n_tf_coils - * d_sc_tf.a_tf_coil_inboard_steel - / self.data.tfcoil.a_tf_inboard_total + self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = ( + inboard_areas_fractions.f_a_tf_coil_inboard_steel ) - - # Inboard coil insulation cross-section [m2] - d_sc_tf.a_tf_coil_inboard_insulation = ( - self.data.tfcoil.a_tf_coil_wp_turn_insulation - + d_sc_tf.a_tf_wp_ground_insulation + self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = ( + inboard_areas_fractions.a_tf_coil_inboard_insulation ) - - # Inboard coil insulation fraction [-] - d_sc_tf.f_a_tf_coil_inboard_insulation = ( - self.data.tfcoil.n_tf_coils - * d_sc_tf.a_tf_coil_inboard_insulation - / self.data.tfcoil.a_tf_inboard_total + self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = ( + inboard_areas_fractions.f_a_tf_coil_inboard_insulation ) # Negative areas or fractions error reporting @@ -3444,7 +3485,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) @@ -3476,7 +3517,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 @@ -3492,9 +3533,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: @@ -3540,10 +3580,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 @@ -3584,50 +3700,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)", - d_sc_tf.a_tf_coil_inboard_insulation, - ) - po.ovarre( - self.outfile, - "Total steel area in inboard TF coil (turn and case)", - "(a_tf_coil_inboard_steel)", - d_sc_tf.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", @@ -3641,6 +3713,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.ovarre( self.outfile, "Elastic properties behavior", @@ -3755,56 +3829,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²] - d_sc_tf.a_tf_coil_inboard_steel = ( - self.data.tfcoil.a_tf_coil_inboard_case + self.data.tfcoil.a_tf_wp_steel - ) - - # Inboard coil steel fraction [-] - d_sc_tf.f_a_tf_coil_inboard_steel = ( - self.data.tfcoil.n_tf_coils - * d_sc_tf.a_tf_coil_inboard_steel - / self.data.tfcoil.a_tf_inboard_total - ) - - # Inboard coil insulation cross-section [m²] - d_sc_tf.a_tf_coil_inboard_insulation = ( - self.data.tfcoil.a_tf_coil_wp_turn_insulation - + d_sc_tf.a_tf_wp_ground_insulation - ) - - # Inboard coil insulation fraction [-] - d_sc_tf.f_a_tf_coil_inboard_insulation = ( - self.data.tfcoil.n_tf_coils - * d_sc_tf.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, @@ -3853,11 +3877,57 @@ def run(self, output: bool = False): croco_cable_geometry.dx_croco_strand_tape_stack ) - d_sc_tf.a_tf_croco_strand_copper_total = d_sc_tf.a_tf_croco_strand_copper_total - d_sc_tf.a_tf_croco_strand_hastelloy = d_sc_tf.a_tf_croco_strand_hastelloy - d_sc_tf.a_tf_croco_strand_solder = d_sc_tf.a_tf_croco_strand_solder - d_sc_tf.a_tf_croco_strand_rebco = d_sc_tf.a_tf_croco_strand_rebco - d_sc_tf.a_tf_croco_strand = d_sc_tf.a_tf_croco_strand + self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total = ( + 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_hastelloy + ) + self.data.superconducting_tfcoil.a_tf_croco_strand_solder = ( + self.data.superconducting_tfcoil.a_tf_croco_strand_solder + ) + self.data.superconducting_tfcoil.a_tf_croco_strand_rebco = ( + self.data.superconducting_tfcoil.a_tf_croco_strand_rebco + ) + self.data.superconducting_tfcoil.a_tf_croco_strand = ( + 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 d_sc_tf.a_tf_turn_croco_copper_bar = d_sc_tf.a_tf_croco_strand @@ -3933,9 +4003,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 @@ -4550,6 +4620,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: """Calculates CROCO voltage""" d_sc_tf = self.data.superconducting_tfcoil diff --git a/tests/unit/models/tfcoil/test_sctfcoil.py b/tests/unit/models/tfcoil/test_sctfcoil.py index 8f1be0cc3a..250be182e2 100644 --- a/tests/unit/models/tfcoil/test_sctfcoil.py +++ b/tests/unit/models/tfcoil/test_sctfcoil.py @@ -1158,7 +1158,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 b1b17ca7bd88886adb46485c63ed1fec7be70499 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 22 Jun 2026 10:53:14 +0100 Subject: [PATCH 19/21] Update test values to try and align with previous solution --- process/core/input.py | 14 -------------- .../input_files/spherical_tokamak_eval.IN.DAT | 4 ++++ tests/regression/input_files/st_regression.IN.DAT | 6 ++++++ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index 8f5d7512c4..580fcb7392 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -710,20 +710,6 @@ def bounds(self) -> tuple[NumberType | None, NumberType | None]: "superconducting_tfcoil", float, range=(1e-08, 0.0001), - additional_actions=lambda _n, rt, *_: ( - rt <= 1e-6 - or logger.warning( - ( - "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 29ab2a1bae..2bed0aa45a 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 37f34ed113..c8f51637b6 100644 --- a/tests/regression/input_files/st_regression.IN.DAT +++ b/tests/regression/input_files/st_regression.IN.DAT @@ -784,6 +784,12 @@ p_plasma_separatrix_rmajor_max_mw = 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ From f72950741a1622e366b8531f6afe19d10c23823b Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Thu, 6 Aug 2026 13:37:30 +0100 Subject: [PATCH 20/21] Fix some ruff errors and some merge mistakes --- process/models/tfcoil/superconducting.py | 210 ++++++++++------------- 1 file changed, 94 insertions(+), 116 deletions(-) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 61d3f912a8..9872820052 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -487,13 +487,13 @@ def output_general_superconducting_tf_info(self) -> None: 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, + d_sc_tf.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, + d_sc_tf.a_tf_coil_inboard_steel, ) po.ovarre( self.outfile, @@ -611,14 +611,14 @@ def output_general_superconducting_tf_info(self) -> None: self.outfile, "Radial width of conductor (m)", "(dr_tf_turn_conduit_full)", - self.data.superconducting_tfcoil.dr_tf_turn_conduit_full, + d_sc_tf.dr_tf_turn_conduit_full, "OP ", ) po.ovarre( self.outfile, "Toroidal width of conductor (m)", "(dx_tf_turn_conduit_full_toroidal)", - self.data.superconducting_tfcoil.dx_tf_turn_conduit_full_toroidal, + d_sc_tf.dx_tf_turn_conduit_full_toroidal, "OP ", ) po.ovarre( @@ -698,7 +698,7 @@ def output_general_superconducting_tf_info(self) -> None: 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, + d_sc_tf.a_tf_turn_cable_space_effective, ) po.ovarre( self.outfile, @@ -2354,12 +2354,12 @@ def run(self, output: bool = False): self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general self.data.tfcoil.c_tf_turn = avg_turn_geometry.c_tf_turn 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 + d_sc_tf.dr_tf_turn = avg_turn_geometry.dr_tf_turn + d_sc_tf.dx_tf_turn = avg_turn_geometry.dx_tf_turn 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 = ( + d_sc_tf.radius_tf_turn_cable_space_corners = ( avg_turn_geometry.radius_tf_turn_cable_space_corners ) d_sc_tf.dx_tf_turn_cable_space_average = ( @@ -2401,28 +2401,22 @@ 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.dr_tf_turn_conduit_full = ( - int_turn_geometry.dr_tf_turn_conduit_full - ) - self.data.superconducting_tfcoil.dx_tf_turn_conduit_full_toroidal = ( + d_sc_tf.dr_tf_turn_conduit_full = int_turn_geometry.dr_tf_turn_conduit_full + d_sc_tf.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 ) - self.data.superconducting_tfcoil.dr_tf_turn_cable_space = ( - int_turn_geometry.dr_tf_turn_cable_space - ) - self.data.superconducting_tfcoil.dx_tf_turn_cable_space = ( - int_turn_geometry.dx_tf_turn_cable_space - ) - self.data.superconducting_tfcoil.dx_tf_turn_cable_space_average = ( + d_sc_tf.dr_tf_turn_cable_space = int_turn_geometry.dr_tf_turn_cable_space + d_sc_tf.dx_tf_turn_cable_space = int_turn_geometry.dx_tf_turn_cable_space + d_sc_tf.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 = ( + d_sc_tf.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 = ( + d_sc_tf.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 @@ -2457,7 +2451,7 @@ def run(self, output: bool = False): 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, + a_tf_wp_ground_insulation=d_sc_tf.a_tf_wp_ground_insulation, ) self.data.tfcoil.a_tf_wp_coolant_channels = ( @@ -2469,16 +2463,14 @@ def run(self, output: bool = False): inboard_areas_fractions.a_tf_coil_wp_turn_insulation ) self.data.tfcoil.a_tf_wp_steel = inboard_areas_fractions.a_tf_wp_steel - self.data.superconducting_tfcoil.a_tf_coil_inboard_steel = ( - inboard_areas_fractions.a_tf_coil_inboard_steel - ) - self.data.superconducting_tfcoil.f_a_tf_coil_inboard_steel = ( + d_sc_tf.a_tf_coil_inboard_steel = inboard_areas_fractions.a_tf_coil_inboard_steel + d_sc_tf.f_a_tf_coil_inboard_steel = ( inboard_areas_fractions.f_a_tf_coil_inboard_steel ) - self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = ( + d_sc_tf.a_tf_coil_inboard_insulation = ( inboard_areas_fractions.a_tf_coil_inboard_insulation ) - self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = ( + d_sc_tf.f_a_tf_coil_inboard_insulation = ( inboard_areas_fractions.f_a_tf_coil_inboard_insulation ) @@ -3812,12 +3804,12 @@ def run(self, output: bool = False): self.data.tfcoil.dx_tf_turn_general = avg_turn_geometry.dx_tf_turn_general self.data.tfcoil.c_tf_turn = avg_turn_geometry.c_tf_turn 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 + d_sc_tf.dr_tf_turn = avg_turn_geometry.dr_tf_turn + d_sc_tf.dx_tf_turn = avg_turn_geometry.dx_tf_turn 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 = ( + d_sc_tf.dx_tf_turn_cable_space_average = ( avg_turn_geometry.dx_tf_turn_cable_space_average ) @@ -3829,7 +3821,7 @@ def run(self, output: bool = False): "Integer turn geometry not implemented for CroCo conductor." ) - croco_cable_space_geometry: CroCoCableSpaceGeometry = self.tf_turn_croco_cable_space_properties( + croco_cable_space_geometry = 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, ) @@ -3844,7 +3836,7 @@ 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.f_a_tf_turn_cable_space_cooling = ( + d_sc_tf.f_a_tf_turn_cable_space_cooling = ( croco_cable_space_geometry.f_a_tf_turn_cable_space_cooling ) @@ -3877,21 +3869,11 @@ def run(self, output: bool = False): croco_cable_geometry.dx_croco_strand_tape_stack ) - self.data.superconducting_tfcoil.a_tf_croco_strand_copper_total = ( - 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_hastelloy - ) - self.data.superconducting_tfcoil.a_tf_croco_strand_solder = ( - self.data.superconducting_tfcoil.a_tf_croco_strand_solder - ) - self.data.superconducting_tfcoil.a_tf_croco_strand_rebco = ( - self.data.superconducting_tfcoil.a_tf_croco_strand_rebco - ) - self.data.superconducting_tfcoil.a_tf_croco_strand = ( - self.data.superconducting_tfcoil.a_tf_croco_strand - ) + d_sc_tf.a_tf_croco_strand_copper_total = d_sc_tf.a_tf_croco_strand_copper_total + d_sc_tf.a_tf_croco_strand_hastelloy = d_sc_tf.a_tf_croco_strand_hastelloy + d_sc_tf.a_tf_croco_strand_solder = d_sc_tf.a_tf_croco_strand_solder + d_sc_tf.a_tf_croco_strand_rebco = d_sc_tf.a_tf_croco_strand_rebco + d_sc_tf.a_tf_croco_strand = d_sc_tf.a_tf_croco_strand self.data.tfcoil.f_a_tf_turn_cable_space_extra_void = 0.0 @@ -3904,8 +3886,8 @@ def run(self, output: bool = False): 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, + a_tf_wp_ground_insulation=d_sc_tf.a_tf_wp_ground_insulation, + a_tf_croco_strand=d_sc_tf.a_tf_croco_strand, ) self.data.tfcoil.a_tf_wp_coolant_channels = ( inbaord_areas_fractions.a_tf_wp_coolant_channels @@ -3916,16 +3898,14 @@ def run(self, output: bool = False): 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 = ( + d_sc_tf.a_tf_coil_inboard_steel = inbaord_areas_fractions.a_tf_coil_inboard_steel + d_sc_tf.f_a_tf_coil_inboard_steel = ( inbaord_areas_fractions.f_a_tf_coil_inboard_steel ) - self.data.superconducting_tfcoil.a_tf_coil_inboard_insulation = ( + d_sc_tf.a_tf_coil_inboard_insulation = ( inbaord_areas_fractions.a_tf_coil_inboard_insulation ) - self.data.superconducting_tfcoil.f_a_tf_coil_inboard_insulation = ( + d_sc_tf.f_a_tf_coil_inboard_insulation = ( inbaord_areas_fractions.f_a_tf_coil_inboard_insulation ) @@ -3939,26 +3919,20 @@ def run(self, output: bool = False): # 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 + N_CROCO_STRANDS_TURN * d_sc_tf.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 - ) + d_sc_tf.a_tf_turn_copper_total = d_sc_tf.a_tf_turn_croco_cable_space_copper - 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 + d_sc_tf.f_a_tf_turn_copper = ( + d_sc_tf.a_tf_turn_croco_cable_space_copper / self.data.tfcoil.a_tf_turn ) - self.data.superconducting_tfcoil.f_a_tf_turn_cable_space_cooling = ( + d_sc_tf.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 + (N_CROCO_STRANDS_TURN * d_sc_tf.a_tf_croco_strand) + - d_sc_tf.a_tf_turn_croco_copper_bar ) ) / self.data.tfcoil.a_tf_turn_cable_space_no_void @@ -3973,55 +3947,59 @@ def run(self, output: bool = False): * self.data.tfcoil.n_tf_coil_turns ) - 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, - 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, - a_tf_croco_strand=self.data.superconducting_tfcoil.a_tf_croco_strand, + 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, + i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat, + dr_tf_hts_tape=d_sc_tf.dr_tf_hts_tape, + dx_tf_hts_tape_rebco=d_sc_tf.dx_tf_hts_tape_rebco, + dx_tf_hts_tape_total=d_sc_tf.dx_tf_hts_tape_total, + a_tf_croco_strand=d_sc_tf.a_tf_croco_strand, + ) ) self.data.tfcoil.j_tf_wp_critical = ( superconductor_critical_properties.j_tf_wp_critical ) - self.data.superconducting_tfcoil.j_tf_superconductor_critical = ( + d_sc_tf.j_tf_superconductor_critical = ( superconductor_critical_properties.j_superconductor_critical ) - self.data.superconducting_tfcoil.f_c_tf_turn_operating_critical = ( + d_sc_tf.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 + d_sc_tf.j_tf_superconductor = superconductor_critical_properties.j_superconductor + d_sc_tf.j_tf_coil_turn = superconductor_critical_properties.j_tf_coil_turn + + d_sc_tf.b_tf_superconductor_critical_zero_temp_strain = ( + superconductor_critical_properties.bc20m + ) + d_sc_tf.temp_tf_superconductor_critical_zero_field_strain = ( + superconductor_critical_properties.tc0m ) - self.data.superconducting_tfcoil.j_tf_coil_turn = ( - superconductor_critical_properties.j_tf_coil_turn + d_sc_tf.cur_tf_turn_croco_strand_critical = d_sc_tf.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.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 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.temp_tf_superconductor_margin = ( + self.calculate_superconductor_temperature_margin( + i_tf_superconductor=self.data.tfcoil.i_tf_sc_mat, + j_superconductor=d_sc_tf.j_tf_superconductor, + b_tf_inboard_peak=self.data.tfcoil.b_tf_inboard_peak_with_ripple, + strain=strain, + bc20m=d_sc_tf.b_tf_superconductor_critical_zero_temp_strain, + tc0m=d_sc_tf.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 = ( @@ -4371,10 +4349,6 @@ def tf_croco_averaged_turn_geometry( # Area of inter-turn insulation: single turn [m²] 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 = ( dx_tf_turn_conduit_full_average - 2.0e0 * dx_tf_turn_steel @@ -4382,7 +4356,8 @@ def tf_croco_averaged_turn_geometry( # Cross-sectional area of conduit jacket per turn [m²] a_tf_turn_steel = ( - dx_tf_turn_conduit_full_average**2 - a_tf_turn_cable_space_no_void + dx_tf_turn_conduit_full_average**2 + - self.data.tfcoil.a_tf_turn_cable_space_no_void ) return CROCOAveragedTurnGeometry( @@ -4422,8 +4397,6 @@ def tf_croco_superconductor_properties( Operating current per turn (A) temp_tf_peak : 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 : @@ -4436,12 +4409,17 @@ def tf_croco_superconductor_properties( Returns ------- TFSuperconductorLimits - A dataclass containing the calculated superconducting properties of the TF coil, including: + 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²). + - 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). @@ -4852,21 +4830,21 @@ def output_croco_info(self) -> None: self.outfile, "Area of central copper bar (m²)", "(a_tf_turn_croco_copper_bar)", - self.data.superconducting_tfcoil.a_tf_turn_croco_copper_bar, + d_sc_tf.a_tf_turn_croco_copper_bar, "OP ", ) po.ovarre( self.outfile, "Total copper area of conductor, total (m²)", "(a_tf_turn_croco_cable_space_copper)", - self.data.superconducting_tfcoil.a_tf_turn_croco_cable_space_copper, + d_sc_tf.a_tf_turn_croco_cable_space_copper, "OP ", ) po.ovarre( self.outfile, "Hastelloy area of conductor (m²)", "(a_tf_turn_croco_hastelloy)", - self.data.superconducting_tfcoil.a_tf_turn_croco_hastelloy, + d_sc_tf.a_tf_turn_croco_hastelloy, "OP ", ) From c394af723bc7cc5d6131f46f01cdf6f2ac0cc319 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Thu, 6 Aug 2026 14:48:43 +0100 Subject: [PATCH 21/21] Fix line too long --- process/models/superconductors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/process/models/superconductors.py b/process/models/superconductors.py index d4e5c9f675..2590fd9b4c 100644 --- a/process/models/superconductors.py +++ b/process/models/superconductors.py @@ -835,8 +835,8 @@ def hijc_rebco( * (b_conductor / b_critical - 1) ** q ) - # 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,! + # 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.