From 363ee4d2678448b79ca164df358271a7a7581ff6 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 15 Jul 2025 09:31:00 +0100 Subject: [PATCH 01/13] Refactor TF coil power conversion parameters and update variable names for clarity --- process/power.py | 168 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 115 insertions(+), 53 deletions(-) diff --git a/process/power.py b/process/power.py index 936d1de535..b07cc8cd2c 100644 --- a/process/power.py +++ b/process/power.py @@ -1928,11 +1928,13 @@ def tfpwcall(self, output: bool): the power conversion requirements for superconducting TF coils. None """ - ettfmj = ( + e_tf_coil_magnetic_stored_mj = ( + ( tfcoil_variables.e_tf_magnetic_stored_total_gj / tfcoil_variables.n_tf_coils * 1.0e3 ) + ) # TF coil current (kA) @@ -1950,81 +1952,115 @@ def tfpwcall(self, output: bool): physics_variables.rmajor, tfcoil_variables.n_tf_coils, tfcoil_variables.v_tf_coil_dump_quench_kv, - ettfmj, + e_tf_coil_magnetic_stored_mj, tfcoil_variables.res_tf_leg, ) def tfcpwr( - self, output: bool, itfka, rmajor, ntfc, v_tf_coil_dump_quench_kv, ettfmj, rptfc - ): + self, + output: bool, + itfka: float, + rmajor: float, + n_tf_coils: int, + vtfskv: float, + e_tf_coil_magnetic_stored_mj: float, + rptfc: float, + ) -> tuple[float, float, float, float, float]: """ - Calculates the TF coil power conversion system parameters - for superconducting coils - author: P J Knight, CCFE, Culham Science Centre - author: P C Shipe, ORNL - This routine calculates the TF power conversion system - parameters: floor space, power supplies, bussing, - coil protection equipment, and the associated controls - and instrumentation. It was originally written by G. Gorker, - FEDC/ORNL, April 1987, modified by J. Galambos in 1991 to - run in TETRA, and included in PROCESS in 1992 by P. C. Shipe. - None + Calculates the TF coil power conversion system parameters for superconducting coils. + + :param output: If True, outputs results to the output file. + :type output: bool + :param itfka: TF coil current (kA). + :type itfka: float + :param rmajor: Major radius of the device (m). + :type rmajor: float + :param n_tf_coils: Number of TF coils. + :type n_tf_coils: int + :param vtfskv: Voltage across a TF coil during quench (kV). + :type vtfskv: float + :param e_tf_coil_magnetic_stored_mj: Stored energy per TF coil (MJ). + :type e_tf_coil_magnetic_stored_mj: float + :param rptfc: Resistance per TF coil (ohm). + :type rptfc: float + + :returns: Tuple containing: + - tfckw (float): DC power supply rating (kW) + - len_tf_bus (float): Total length of TF coil bussing (m) + - drarea (float): Dump resistor floor area (m2) + - tfcbv (float): TF coil power conversion building volume (m3) + - p_tf_electric_supplies_mw (float): Total steady state AC power demand (MW) + + :notes: + - This routine calculates the TF power conversion system parameters: floor space, power supplies, + bussing, coil protection equipment, and the associated controls and instrumentation. + Originally written by G. Gorker, FEDC/ORNL, April 1987, modified by J. Galambos in 1991 to run in TETRA, + and included in PROCESS in 1992 by P. C. Shipe. + + - This routine was originally called tfcpwr() in the ETR/ITER Systems Code + + :references: + - R. L. Reid, “ETR/ITER Systems Code,” Oak Ridge National Laboratory, ORNL-FEDC-87-7, April 1988. + Available: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjX9Ozasb6OAxX1U0EAHV-3C + 0QQFnoECBYQAQ&url=https%3A%2F%2Fengineering.purdue.edu%2FCMUXE%2FPublications%2FAHR%2FR88ORNL-FEDC-87-7.pdf& + usg=AOvVaw1-LdCefwqI0hJumpHvfTlX&opi=89978449 + ‌ """ - ncpbkr = 1.0e0 # number of TF coils per circuit breaker - djmka = 0.125e0 # design current density of TF bus, kA/cm2 + N_TF_COIL_BREAKERS = 1.0e0 # number of TF coils per circuit breaker + j_tf_bus_design_ka_cm = 0.125e0 # design current density of TF bus, kA/cm2 rtfps = 1.05e0 # rating factor for TF coil power supplies fspc1 = 0.15e0 # floor space coefficient for power supplies fspc2 = 0.8e0 # floor space coefficient for circuit breakers fspc3 = 0.4e0 # floor space coefficient for load centres if rptfc == 0.0e0: - tchghr = 4.0e0 # charge time of the coils, hours + T_TF_CHARGE_HOURS = 4.0e0 # charge time of the coils, hours nsptfc = 1.0e0 # superconducting (1.0 = superconducting, 0.0 = resistive) else: - tchghr = 0.16667e0 # charge time of the coils, hours + T_TF_CHARGE_HOURS = 0.16667e0 # charge time of the coils, hours nsptfc = 0.0e0 # resistive (1.0 = superconducting, 0.0 = resistive) # Total steady state TF coil AC power demand (summed later) p_tf_electric_supplies_mw = 0.0e0 # Stored energy of all TF coils, MJ - ettfc = ntfc * ettfmj + e_tf_magnetic_stored_mj = n_tf_coils * e_tf_coil_magnetic_stored_mj # Inductance of all TF coils, Henries - ltfth = 2.0e0 * ettfc / itfka**2 + ind_tf_total = 2.0e0 * e_tf_magnetic_stored_mj / itfka**2 # Number of circuit breakers - ntfbkr = ntfc / ncpbkr + n_tf_breakers = n_tf_coils / N_TF_COIL_BREAKERS # Inductance per TF coil, Henries - lptfcs = ltfth / ntfc + ind_tf_coil = ind_tf_total / n_tf_coils # Aluminium bus section area, sq cm - albusa = itfka / djmka + albusa = itfka / j_tf_bus_design_ka_cm # Total TF system bus length, m len_tf_bus = ( 8.0e0 * np.pi * rmajor - + (1.0e0 + ntfbkr) * (12.0e0 * rmajor + 80.0e0) - + 0.2e0 * itfka * np.sqrt(ntfc * rptfc * 1000.0e0) + + (1.0e0 + n_tf_breakers) * (12.0e0 * rmajor + 80.0e0) + + 0.2e0 * itfka * np.sqrt(n_tf_coils * rptfc * 1000.0e0) ) # Aluminium bus weight, tonnes - albuswt = 2.7e0 * albusa * len_tf_bus / 1.0e4 + m_tf_bus_aluminium_tonnes = 2.7e0 * albusa * len_tf_bus / 1.0e4 # Total resistance of TF bus, ohms - # rtfbus = 2.62e-4 * len_tf_bus / albusa - rtfbus = tfcoil_variables.rho_tf_bus * len_tf_bus / (albusa / 10000) + # res_tf_bus = 2.62e-4 * len_tf_bus / albusa + res_tf_bus = tfcoil_variables.rho_tf_bus * len_tf_bus / (albusa / 10000) # Total voltage drop across TF bus, volts - vtfbus = 1000.0e0 * itfka * rtfbus + v_tf_bus = 1000.0e0 * itfka * res_tf_bus # Total resistance of the TF coils, ohms - rcoils = ntfc * rptfc + rcoils = n_tf_coils * rptfc # Total impedance, ohms - ztotal = rtfbus + rcoils + ltfth / (3600.0e0 * tchghr) + ztotal = res_tf_bus + rcoils + ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) # Charging voltage for the TF coils, volts tfcv = 1000.0e0 * itfka * ztotal @@ -2054,32 +2090,36 @@ def tfcpwr( tfackw = tfckw / 0.9e0 # Resistance of dump resistor, ohms - r1dump = nsptfc * v_tf_coil_dump_quench_kv * ncpbkr / itfka + r1dump = nsptfc * v_tf_coil_dump_quench_kv * N_TF_COIL_BREAKERS / itfka # Time constant, s - ttfsec = lptfcs * ncpbkr / (r1dump * nsptfc + rptfc * (1.0e0 - nsptfc)) + ttfsec = ( + ind_tf_coil + * N_TF_COIL_BREAKERS + / (r1dump * nsptfc + rptfc * (1.0e0 - nsptfc)) + ) # Number of dump resistors - ndumpr = ntfbkr * 4.0e0 + n_tf_dump_resistors = n_tf_breakers * 4.0e0 # Peak power to a dump resistor during quench, MW r1ppmw = nsptfc * r1dump * (itfka / 2.0e0) ** 2 # Energy to dump resistor during quench, MJ - r1emj = nsptfc * ettfc / (ndumpr + 0.0001e0) + r1emj = nsptfc * e_tf_magnetic_stored_mj / (n_tf_dump_resistors + 0.0001e0) # Total TF coil peak resistive power demand, MVA - rpower = (ntfc * rptfc + rtfbus) * itfka**2 + rpower = (n_tf_coils * rptfc + res_tf_bus) * itfka**2 # Total TF coil peak inductive power demand, MVA - xpower = ltfth / (3600.0e0 * tchghr) * itfka**2 + xpower = ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) * itfka**2 # Building space: # Power modules floor space, m2 part1 = fspc1 * ntfpm * tfpmkw**0.667e0 # Circuit breakers floor space, m2 - part2 = fspc2 * ntfbkr * (v_tf_coil_dump_quench_kv * itfka) ** 0.667e0 + part2 = fspc2 * n_tf_breakers * (v_tf_coil_dump_quench_kv * itfka) ** 0.667e0 # Load centres floor space, m2 part3 = ( @@ -2090,7 +2130,7 @@ def tfcpwr( tfcfsp = part1 + part2 + part3 # Dump resistor floor area, m2 - drarea = 0.5e0 * ndumpr * (1.0e0 + r1emj) ** 0.667e0 + drarea = 0.5e0 * n_tf_dump_resistors * (1.0e0 + r1emj) ** 0.667e0 # Total TF coil power conversion building volume, m3 tfcbv = 6.0e0 * tfcfsp @@ -2113,7 +2153,7 @@ def tfcpwr( if output: po.oheadr(self.outfile, "Superconducting TF Coil Power Conversion") po.ovarre(self.outfile, "TF coil current (kA)", "(itfka)", itfka, "OP ") - po.ovarre(self.outfile, "Number of TF coils", "(ntfc)", ntfc) + po.ovarre(self.outfile, "Number of TF coils", "(n_tf_coils)", n_tf_coils) po.ovarre( self.outfile, "Voltage across a TF coil during quench (kV)", @@ -2121,12 +2161,17 @@ def tfcpwr( v_tf_coil_dump_quench_kv, "OP ", ) - po.ovarre(self.outfile, "TF coil charge time (hours)", "(tchghr)", tchghr) + po.ovarre( + self.outfile, + "TF coil charge time (hours)", + "(T_TF_CHARGE_HOURS)", + T_TF_CHARGE_HOURS, + ) po.ovarre( self.outfile, "Total inductance of TF coils (H)", - "(ltfth)", - ltfth, + "(ind_tf_total)", + ind_tf_total, "OP ", ) po.ovarre( @@ -2138,10 +2183,20 @@ def tfcpwr( ) # MDK Remove this as it leads to confusion between (a) total inductance/n_tf_coils, or (b) # self-inductance of one single coil - # po.ovarre(outfile,'Inductance per TF coil (H)','(lptfcs)',lptfcs, 'OP ') + # po.ovarre(outfile,'Inductance per TF coil (H)','(ind_tf_coil)',ind_tf_coil, 'OP ') po.ovarre(self.outfile, "TF coil charging voltage (V)", "(tfcv)", tfcv) - po.ovarre(self.outfile, "Number of DC circuit breakers", "(ntfbkr)", ntfbkr) - po.ovarre(self.outfile, "Number of dump resistors", "(ndumpr)", ndumpr) + po.ovarre( + self.outfile, + "Number of DC circuit breakers", + "(n_tf_breakers)", + n_tf_breakers, + ) + po.ovarre( + self.outfile, + "Number of dump resistors", + "(n_tf_dump_resistors)", + n_tf_dump_resistors, + ) po.ovarre( self.outfile, "Resistance per dump resistor (ohm)", @@ -2181,7 +2236,10 @@ def tfcpwr( self.outfile, "TF coil inductive power (MVA)", "(xpower)", xpower, "OP " ) po.ovarre( - self.outfile, "Aluminium bus current density (kA/cm2)", "(djmka)", djmka + self.outfile, + "Aluminium bus current density (kA/cm2)", + "(j_tf_bus_design_ka_cm)", + j_tf_bus_design_ka_cm, ) po.ovarre( self.outfile, @@ -2200,20 +2258,24 @@ def tfcpwr( po.ovarre( self.outfile, "Aluminium bus weight (tonnes)", - "(albuswt)", - albuswt, + "(m_tf_bus_aluminium_tonnes)", + m_tf_bus_aluminium_tonnes, "OP ", ) po.ovarre( self.outfile, "Total TF coil bus resistance (ohm)", - "(rtfbus)", - rtfbus, + "(res_tf_bus)", + res_tf_bus, "OP ", ) po.ovarre( - self.outfile, "TF coil bus voltage drop (V)", "(vtfbus)", vtfbus, "OP " + self.outfile, + "TF coil bus voltage drop (V)", + "(v_tf_bus)", + v_tf_bus, + "OP ", ) po.ovarre( self.outfile, "Dump resistor floor area (m2)", "(drarea)", drarea, "OP " From 9f2174a2d48edd61ff09223185a52288cb1f7f4e Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 10:25:52 +0100 Subject: [PATCH 02/13] Refactor TF coil power calculation by removing redundant variable and updating parameter names for clarity --- process/power.py | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/process/power.py b/process/power.py index b07cc8cd2c..87495f5813 100644 --- a/process/power.py +++ b/process/power.py @@ -1928,14 +1928,6 @@ def tfpwcall(self, output: bool): the power conversion requirements for superconducting TF coils. None """ - e_tf_coil_magnetic_stored_mj = ( - ( - tfcoil_variables.e_tf_magnetic_stored_total_gj - / tfcoil_variables.n_tf_coils - * 1.0e3 - ) - ) - # TF coil current (kA) itfka = 1.0e-3 * tfcoil_variables.c_tf_turn @@ -1947,13 +1939,14 @@ def tfpwcall(self, output: bool): buildings_variables.tfcbv, heat_transport_variables.p_tf_electric_supplies_mw, ) = self.tfcpwr( - output, - itfka, - physics_variables.rmajor, - tfcoil_variables.n_tf_coils, - tfcoil_variables.v_tf_coil_dump_quench_kv, - e_tf_coil_magnetic_stored_mj, - tfcoil_variables.res_tf_leg, + output=output, + itfka=itfka, + rmajor=physics_variables.rmajor, + n_tf_coils=tfcoil_variables._tf_coils, + v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, + e_tf_coil_magnetic_stored_mj=tfcoil_variables.e_tf_coil_magnetic_stored + / 1e6, + rptfc=tfcoil_variables.res_tf_leg, ) def tfcpwr( @@ -1962,7 +1955,7 @@ def tfcpwr( itfka: float, rmajor: float, n_tf_coils: int, - vtfskv: float, + v_tf_coil_dump_quench_kv: float, e_tf_coil_magnetic_stored_mj: float, rptfc: float, ) -> tuple[float, float, float, float, float]: @@ -1977,8 +1970,8 @@ def tfcpwr( :type rmajor: float :param n_tf_coils: Number of TF coils. :type n_tf_coils: int - :param vtfskv: Voltage across a TF coil during quench (kV). - :type vtfskv: float + :param v_tf_coil_dump_quench_kv: Voltage across a TF coil during quench (kV). + :type v_tf_coil_dump_quench_kv: float :param e_tf_coil_magnetic_stored_mj: Stored energy per TF coil (MJ). :type e_tf_coil_magnetic_stored_mj: float :param rptfc: Resistance per TF coil (ohm). From cdcaa9caad908295c6bf73b6d4776069a959712b Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 10:37:08 +0100 Subject: [PATCH 03/13] :fire: Refactor TF coil power calculation by integrating tfcpwr directly and removing the tfpwcall method --- process/power.py | 50 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/process/power.py b/process/power.py index 87495f5813..b93f5cbffc 100644 --- a/process/power.py +++ b/process/power.py @@ -1831,7 +1831,22 @@ def tfpwr(self, output: bool): ) else: # Superconducting TF coil option - self.tfpwcall(output) + ( + tfcoil_variables.tfckw, + tfcoil_variables.len_tf_bus, + tfcoil_variables.drarea, + buildings_variables.tfcbv, + heat_transport_variables.p_tf_electric_supplies_mw, + ) = self.tfcpwr( + output=output, + itfka=tfcoil_variables.c_tf_turn / 1e3, + rmajor=physics_variables.rmajor, + n_tf_coils=tfcoil_variables.n_tf_coils, + v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, + e_tf_coil_magnetic_stored_mj=tfcoil_variables.e_tf_coil_magnetic_stored + / 1e6, + rptfc=tfcoil_variables.res_tf_leg, + ) return # Output section @@ -1916,39 +1931,6 @@ def tfpwr(self, output: bool): # Reactive poower has been set to zero. # po.ovarre(outfile,'TF coil reactive power (MW)','(tfreacmw)', tfreacmw) - def tfpwcall(self, output: bool): - """ - Calls the TF coil power conversion routine for - superconducting coils - author: P J Knight, CCFE, Culham Science Centre - author: P C Shipe, ORNL - outfile : input integer : output file unit - iprint : input integer : switch for writing to output (1=yes) - This routine calls routine tfcpwr to calculate - the power conversion requirements for superconducting TF coils. - None - """ - # TF coil current (kA) - - itfka = 1.0e-3 * tfcoil_variables.c_tf_turn - - ( - tfcoil_variables.tfckw, - tfcoil_variables.len_tf_bus, - tfcoil_variables.drarea, - buildings_variables.tfcbv, - heat_transport_variables.p_tf_electric_supplies_mw, - ) = self.tfcpwr( - output=output, - itfka=itfka, - rmajor=physics_variables.rmajor, - n_tf_coils=tfcoil_variables._tf_coils, - v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, - e_tf_coil_magnetic_stored_mj=tfcoil_variables.e_tf_coil_magnetic_stored - / 1e6, - rptfc=tfcoil_variables.res_tf_leg, - ) - def tfcpwr( self, output: bool, From 845e61a5a2187b29a887e1dd91e02084a6baf93a Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 11:35:50 +0100 Subject: [PATCH 04/13] =?UTF-8?q?=F0=9F=94=84=20-=20Renamed=20`tfcpwr`=20f?= =?UTF-8?q?unction=20to=20`superconducting=5Ftf=5Fpower=5Fiter=5F1988`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eng-models/power-requirements.md | 4 +- process/power.py | 40 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/documentation/eng-models/power-requirements.md b/documentation/eng-models/power-requirements.md index bf6468f68c..7802c796a5 100644 --- a/documentation/eng-models/power-requirements.md +++ b/documentation/eng-models/power-requirements.md @@ -9,11 +9,11 @@ The main power flow is controlled by `power.py`. The main class `Power` controls --- -#### Superconducting TF coil power requirements | `tfcpwr()` +#### Superconducting TF coil power requirements | `superconducting_tf_power_iter_1988()` --- -#### TF coil power conversion system parameters | `tfcpwr()` +#### TF coil power conversion system parameters | `superconducting_tf_power_iter_1988()` --- diff --git a/process/power.py b/process/power.py index b93f5cbffc..780470e99c 100644 --- a/process/power.py +++ b/process/power.py @@ -1837,9 +1837,9 @@ def tfpwr(self, output: bool): tfcoil_variables.drarea, buildings_variables.tfcbv, heat_transport_variables.p_tf_electric_supplies_mw, - ) = self.tfcpwr( + ) = self.superconducting_tf_power_iter_1988( output=output, - itfka=tfcoil_variables.c_tf_turn / 1e3, + c_tf_turn_ka=tfcoil_variables.c_tf_turn / 1e3, rmajor=physics_variables.rmajor, n_tf_coils=tfcoil_variables.n_tf_coils, v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, @@ -1931,10 +1931,10 @@ def tfpwr(self, output: bool): # Reactive poower has been set to zero. # po.ovarre(outfile,'TF coil reactive power (MW)','(tfreacmw)', tfreacmw) - def tfcpwr( + def superconducting_tf_power_iter_1988( self, output: bool, - itfka: float, + c_tf_turn_ka: float, rmajor: float, n_tf_coils: int, v_tf_coil_dump_quench_kv: float, @@ -1946,8 +1946,8 @@ def tfcpwr( :param output: If True, outputs results to the output file. :type output: bool - :param itfka: TF coil current (kA). - :type itfka: float + :param c_tf_turn_ka: TF coil current (kA). + :type c_tf_turn_ka: float :param rmajor: Major radius of the device (m). :type rmajor: float :param n_tf_coils: Number of TF coils. @@ -2003,7 +2003,7 @@ def tfcpwr( e_tf_magnetic_stored_mj = n_tf_coils * e_tf_coil_magnetic_stored_mj # Inductance of all TF coils, Henries - ind_tf_total = 2.0e0 * e_tf_magnetic_stored_mj / itfka**2 + ind_tf_total = 2.0e0 * e_tf_magnetic_stored_mj / c_tf_turn_ka**2 # Number of circuit breakers n_tf_breakers = n_tf_coils / N_TF_COIL_BREAKERS @@ -2012,13 +2012,13 @@ def tfcpwr( ind_tf_coil = ind_tf_total / n_tf_coils # Aluminium bus section area, sq cm - albusa = itfka / j_tf_bus_design_ka_cm + albusa = c_tf_turn_ka / j_tf_bus_design_ka_cm # Total TF system bus length, m len_tf_bus = ( 8.0e0 * np.pi * rmajor + (1.0e0 + n_tf_breakers) * (12.0e0 * rmajor + 80.0e0) - + 0.2e0 * itfka * np.sqrt(n_tf_coils * rptfc * 1000.0e0) + + 0.2e0 * c_tf_turn_ka * np.sqrt(n_tf_coils * rptfc * 1000.0e0) ) # Aluminium bus weight, tonnes @@ -2029,7 +2029,7 @@ def tfcpwr( res_tf_bus = tfcoil_variables.rho_tf_bus * len_tf_bus / (albusa / 10000) # Total voltage drop across TF bus, volts - v_tf_bus = 1000.0e0 * itfka * res_tf_bus + v_tf_bus = 1000.0e0 * c_tf_turn_ka * res_tf_bus # Total resistance of the TF coils, ohms rcoils = n_tf_coils * rptfc @@ -2038,10 +2038,10 @@ def tfcpwr( ztotal = res_tf_bus + rcoils + ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) # Charging voltage for the TF coils, volts - tfcv = 1000.0e0 * itfka * ztotal + tfcv = 1000.0e0 * c_tf_turn_ka * ztotal # Number of TF power modules - ntfpm = (itfka * (1.0e0 + nsptfc)) / 5.0e0 + ntfpm = (c_tf_turn_ka * (1.0e0 + nsptfc)) / 5.0e0 # TF coil power module voltage, volts tfpmv = rtfps * tfcv / (1.0e0 + nsptfc) @@ -2050,10 +2050,10 @@ def tfcpwr( tfpsv = rtfps * tfcv # Power supply current, kA - tfpska = rtfps * itfka + tfpska = rtfps * c_tf_turn_ka # TF power module current, kA - tfpmka = rtfps * itfka / (ntfpm / (1.0e0 + nsptfc)) + tfpmka = rtfps * c_tf_turn_ka / (ntfpm / (1.0e0 + nsptfc)) # TF power module power, kW tfpmkw = tfpmv * tfpmka @@ -2065,7 +2065,7 @@ def tfcpwr( tfackw = tfckw / 0.9e0 # Resistance of dump resistor, ohms - r1dump = nsptfc * v_tf_coil_dump_quench_kv * N_TF_COIL_BREAKERS / itfka + r1dump = nsptfc * v_tf_coil_dump_quench_kv * N_TF_COIL_BREAKERS / c_tf_turn_ka # Time constant, s ttfsec = ( @@ -2078,23 +2078,23 @@ def tfcpwr( n_tf_dump_resistors = n_tf_breakers * 4.0e0 # Peak power to a dump resistor during quench, MW - r1ppmw = nsptfc * r1dump * (itfka / 2.0e0) ** 2 + r1ppmw = nsptfc * r1dump * (c_tf_turn_ka / 2.0e0) ** 2 # Energy to dump resistor during quench, MJ r1emj = nsptfc * e_tf_magnetic_stored_mj / (n_tf_dump_resistors + 0.0001e0) # Total TF coil peak resistive power demand, MVA - rpower = (n_tf_coils * rptfc + res_tf_bus) * itfka**2 + rpower = (n_tf_coils * rptfc + res_tf_bus) * c_tf_turn_ka**2 # Total TF coil peak inductive power demand, MVA - xpower = ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) * itfka**2 + xpower = ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) * c_tf_turn_ka**2 # Building space: # Power modules floor space, m2 part1 = fspc1 * ntfpm * tfpmkw**0.667e0 # Circuit breakers floor space, m2 - part2 = fspc2 * n_tf_breakers * (v_tf_coil_dump_quench_kv * itfka) ** 0.667e0 + part2 = fspc2 * n_tf_breakers * (v_tf_coil_dump_quench_kv * c_tf_turn_ka) ** 0.667e0 # Load centres floor space, m2 part3 = ( @@ -2127,7 +2127,7 @@ def tfcpwr( # Output section if output: po.oheadr(self.outfile, "Superconducting TF Coil Power Conversion") - po.ovarre(self.outfile, "TF coil current (kA)", "(itfka)", itfka, "OP ") + po.ovarre(self.outfile, "TF coil current (kA)", "(c_tf_turn_ka)", c_tf_turn_ka, "OP ") po.ovarre(self.outfile, "Number of TF coils", "(n_tf_coils)", n_tf_coils) po.ovarre( self.outfile, From 87f070f35e2fb657b212aabf6f2139ab16a014f8 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 15:50:33 +0100 Subject: [PATCH 05/13] :fire: Remove redundant resistive `rptfc` --- .../eng-models/power-requirements.md | 59 ++++++------------- process/power.py | 20 ++----- 2 files changed, 24 insertions(+), 55 deletions(-) diff --git a/documentation/eng-models/power-requirements.md b/documentation/eng-models/power-requirements.md index 7802c796a5..7a7d9fac5b 100644 --- a/documentation/eng-models/power-requirements.md +++ b/documentation/eng-models/power-requirements.md @@ -11,6 +11,24 @@ The main power flow is controlled by `power.py`. The main class `Power` controls #### Superconducting TF coil power requirements | `superconducting_tf_power_iter_1988()` + +Some details of the auxiliary systems are as follows. + +`tfcpwr` calculates the TF coil power conversion system parameters. Only the steady-state power consumption for a superconducting TFC system is described here. + +The TF current is carried from the power supplies to the reactor by room-temperature aluminium busbars, organised in $N_{circuit}$ circuits. The total length of the busbars is (somehwat arbitrarily) given by + +$$ +L_bus = 8 \pi R_0 + (1 + N_{circuit}) (12 R_0 + 80) +$$ + +The resistivity of the busbar is 2.62e-8 ohm.m (0.0262 ohm.mm²/m) (hard-coded). + +"TF coil resistive power" (`rpower`) includes the dissipation of the cryogenic current leads (assumed to be resistive). + +The AC power required is determined by the efficiency of the coil power supply: `etatf` (default = 90%). + + --- #### TF coil power conversion system parameters | `superconducting_tf_power_iter_1988()` @@ -311,44 +329,3 @@ The correlation of efficiency with temperature is derived from results of cycle ### Cryogenic power requirements | `cryo()` ---- - - - - - -Figure 1 shows a simplified description of the power flow. - -
-
- Overall power flow -

-
Figure 1: Power flows -
-
-
-
- -Some details of the auxiliary systems are as follows. - -`tfcpwr` calculates the TF coil power conversion system parameters. Only the steady-state power consumption for a superconducting TFC system is described here. - -The TF current is carried from the power supplies to the reactor by room-temperature aluminium busbars, organised in $N_{circuit}$ circuits. The total length of the busbars is (somehwat arbitrarily) given by - -$$ -L_bus = 8 \pi R_0 + (1 + N_{circuit}) (12 R_0 + 80) -$$ - -The resistivity of the busbar is 2.62e-8 ohm.m (0.0262 ohm.mm²/m) (hard-coded). - -"TF coil resistive power" (`rpower`) includes the dissipation of the cryogenic current leads (assumed to be resistive). - -The AC power required is determined by the efficiency of the coil power supply: `etatf` (default = 90%). - - - - - - diff --git a/process/power.py b/process/power.py index 780470e99c..72620e11e4 100644 --- a/process/power.py +++ b/process/power.py @@ -1845,7 +1845,6 @@ def tfpwr(self, output: bool): v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, e_tf_coil_magnetic_stored_mj=tfcoil_variables.e_tf_coil_magnetic_stored / 1e6, - rptfc=tfcoil_variables.res_tf_leg, ) return @@ -1939,7 +1938,6 @@ def superconducting_tf_power_iter_1988( n_tf_coils: int, v_tf_coil_dump_quench_kv: float, e_tf_coil_magnetic_stored_mj: float, - rptfc: float, ) -> tuple[float, float, float, float, float]: """ Calculates the TF coil power conversion system parameters for superconducting coils. @@ -1956,8 +1954,6 @@ def superconducting_tf_power_iter_1988( :type v_tf_coil_dump_quench_kv: float :param e_tf_coil_magnetic_stored_mj: Stored energy per TF coil (MJ). :type e_tf_coil_magnetic_stored_mj: float - :param rptfc: Resistance per TF coil (ohm). - :type rptfc: float :returns: Tuple containing: - tfckw (float): DC power supply rating (kW) @@ -1989,12 +1985,9 @@ def superconducting_tf_power_iter_1988( fspc2 = 0.8e0 # floor space coefficient for circuit breakers fspc3 = 0.4e0 # floor space coefficient for load centres - if rptfc == 0.0e0: - T_TF_CHARGE_HOURS = 4.0e0 # charge time of the coils, hours - nsptfc = 1.0e0 # superconducting (1.0 = superconducting, 0.0 = resistive) - else: - T_TF_CHARGE_HOURS = 0.16667e0 # charge time of the coils, hours - nsptfc = 0.0e0 # resistive (1.0 = superconducting, 0.0 = resistive) + + T_TF_CHARGE_HOURS = 4.0e0 # charge time of the coils, hours + nsptfc = 1.0e0 # superconducting (1.0 = superconducting, 0.0 = resistive) # Total steady state TF coil AC power demand (summed later) p_tf_electric_supplies_mw = 0.0e0 @@ -2018,7 +2011,6 @@ def superconducting_tf_power_iter_1988( len_tf_bus = ( 8.0e0 * np.pi * rmajor + (1.0e0 + n_tf_breakers) * (12.0e0 * rmajor + 80.0e0) - + 0.2e0 * c_tf_turn_ka * np.sqrt(n_tf_coils * rptfc * 1000.0e0) ) # Aluminium bus weight, tonnes @@ -2032,7 +2024,7 @@ def superconducting_tf_power_iter_1988( v_tf_bus = 1000.0e0 * c_tf_turn_ka * res_tf_bus # Total resistance of the TF coils, ohms - rcoils = n_tf_coils * rptfc + rcoils = 0.0 # Total impedance, ohms ztotal = res_tf_bus + rcoils + ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) @@ -2071,7 +2063,7 @@ def superconducting_tf_power_iter_1988( ttfsec = ( ind_tf_coil * N_TF_COIL_BREAKERS - / (r1dump * nsptfc + rptfc * (1.0e0 - nsptfc)) + / (r1dump * nsptfc + 0.0 * (1.0e0 - nsptfc)) ) # Number of dump resistors @@ -2084,7 +2076,7 @@ def superconducting_tf_power_iter_1988( r1emj = nsptfc * e_tf_magnetic_stored_mj / (n_tf_dump_resistors + 0.0001e0) # Total TF coil peak resistive power demand, MVA - rpower = (n_tf_coils * rptfc + res_tf_bus) * c_tf_turn_ka**2 + rpower = (n_tf_coils * 0.0 + res_tf_bus) * c_tf_turn_ka**2 # Total TF coil peak inductive power demand, MVA xpower = ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) * c_tf_turn_ka**2 From 63c61a191f67f7cce641dc66584f502864c98558 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 15:54:50 +0100 Subject: [PATCH 06/13] :recycle: Refactor TF coil power calculation using the total stored magnetic energy --- process/power.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/process/power.py b/process/power.py index 72620e11e4..24d1a6c7d2 100644 --- a/process/power.py +++ b/process/power.py @@ -1843,7 +1843,7 @@ def tfpwr(self, output: bool): rmajor=physics_variables.rmajor, n_tf_coils=tfcoil_variables.n_tf_coils, v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, - e_tf_coil_magnetic_stored_mj=tfcoil_variables.e_tf_coil_magnetic_stored + e_tf_magnetic_stored_total_mj=superconducting_tf_coil_variables.e_tf_magnetic_stored_total / 1e6, ) return @@ -1937,7 +1937,7 @@ def superconducting_tf_power_iter_1988( rmajor: float, n_tf_coils: int, v_tf_coil_dump_quench_kv: float, - e_tf_coil_magnetic_stored_mj: float, + e_tf_magnetic_stored_total_mj: float, ) -> tuple[float, float, float, float, float]: """ Calculates the TF coil power conversion system parameters for superconducting coils. @@ -1952,8 +1952,8 @@ def superconducting_tf_power_iter_1988( :type n_tf_coils: int :param v_tf_coil_dump_quench_kv: Voltage across a TF coil during quench (kV). :type v_tf_coil_dump_quench_kv: float - :param e_tf_coil_magnetic_stored_mj: Stored energy per TF coil (MJ). - :type e_tf_coil_magnetic_stored_mj: float + :param e_tf_magnetic_stored_total_mj: Total stored energy in TF coils (MJ). + :type e_tf_magnetic_stored_total_mj: float :returns: Tuple containing: - tfckw (float): DC power supply rating (kW) @@ -1985,18 +1985,14 @@ def superconducting_tf_power_iter_1988( fspc2 = 0.8e0 # floor space coefficient for circuit breakers fspc3 = 0.4e0 # floor space coefficient for load centres - T_TF_CHARGE_HOURS = 4.0e0 # charge time of the coils, hours nsptfc = 1.0e0 # superconducting (1.0 = superconducting, 0.0 = resistive) # Total steady state TF coil AC power demand (summed later) p_tf_electric_supplies_mw = 0.0e0 - # Stored energy of all TF coils, MJ - e_tf_magnetic_stored_mj = n_tf_coils * e_tf_coil_magnetic_stored_mj - # Inductance of all TF coils, Henries - ind_tf_total = 2.0e0 * e_tf_magnetic_stored_mj / c_tf_turn_ka**2 + ind_tf_total = 2.0e0 * e_tf_magnetic_stored_total_mj / c_tf_turn_ka**2 # Number of circuit breakers n_tf_breakers = n_tf_coils / N_TF_COIL_BREAKERS @@ -2008,9 +2004,8 @@ def superconducting_tf_power_iter_1988( albusa = c_tf_turn_ka / j_tf_bus_design_ka_cm # Total TF system bus length, m - len_tf_bus = ( - 8.0e0 * np.pi * rmajor - + (1.0e0 + n_tf_breakers) * (12.0e0 * rmajor + 80.0e0) + len_tf_bus = 8.0e0 * np.pi * rmajor + (1.0e0 + n_tf_breakers) * ( + 12.0e0 * rmajor + 80.0e0 ) # Aluminium bus weight, tonnes @@ -2086,7 +2081,9 @@ def superconducting_tf_power_iter_1988( part1 = fspc1 * ntfpm * tfpmkw**0.667e0 # Circuit breakers floor space, m2 - part2 = fspc2 * n_tf_breakers * (v_tf_coil_dump_quench_kv * c_tf_turn_ka) ** 0.667e0 + part2 = ( + fspc2 * n_tf_breakers * (v_tf_coil_dump_quench_kv * c_tf_turn_ka) ** 0.667e0 + ) # Load centres floor space, m2 part3 = ( @@ -2119,7 +2116,13 @@ def superconducting_tf_power_iter_1988( # Output section if output: po.oheadr(self.outfile, "Superconducting TF Coil Power Conversion") - po.ovarre(self.outfile, "TF coil current (kA)", "(c_tf_turn_ka)", c_tf_turn_ka, "OP ") + po.ovarre( + self.outfile, + "TF coil current (kA)", + "(c_tf_turn_ka)", + c_tf_turn_ka, + "OP ", + ) po.ovarre(self.outfile, "Number of TF coils", "(n_tf_coils)", n_tf_coils) po.ovarre( self.outfile, From 65c0ec878a327a9fe56d8ecb881328228baa25ba Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 16:00:23 +0100 Subject: [PATCH 07/13] :memo: Add TF electric power consumption formula to documentation --- documentation/eng-models/power-requirements.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/documentation/eng-models/power-requirements.md b/documentation/eng-models/power-requirements.md index 7a7d9fac5b..90d9e20bdc 100644 --- a/documentation/eng-models/power-requirements.md +++ b/documentation/eng-models/power-requirements.md @@ -5,6 +5,13 @@ The main power flow is controlled by `power.py`. The main class `Power` controls ### TF Coils +Generall the newt power consumption of one magnet in $\text{VA}$ is given by: + +$$ +P_{\text{TF,electric}} = \left(R_{\text{TF,coil}}+R_{\text{joints}}+R_{\text{feeder}}\right) \times I_{\text{TF,coil}}^2 +\\ +\left(L_{\text{TF,coil-self}}+L_{\text{feeder}}\right)\frac{dI}{dt} +$$ + #### Resistive TF coil power requirements | `tfpwr()` --- From 54972ccf54e3e4d12d9f1016ba75deb14d7a849a Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 16:20:19 +0100 Subject: [PATCH 08/13] :sparkle: Add total inductance variable for TF coils and initialize in setup --- process/data_structure/tfcoil_variables.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/process/data_structure/tfcoil_variables.py b/process/data_structure/tfcoil_variables.py index d1d56ed36f..32481c47fe 100644 --- a/process/data_structure/tfcoil_variables.py +++ b/process/data_structure/tfcoil_variables.py @@ -666,6 +666,9 @@ ind_tf_coil: float = None """TF coil inductance (H)""" +ind_tf_total: float = None +"""Total inductance of all TF coils (H)""" + dx_tf_wp_insertion_gap: float = None """TF coil WP insertion gap (m)""" @@ -1211,6 +1214,7 @@ def init_tfcoil_variables(): global tfcryoarea global tficrn global ind_tf_coil + global ind_tf_total global dx_tf_wp_insertion_gap global p_tf_leg_resistive_mw global rho_cp @@ -1447,6 +1451,7 @@ def init_tfcoil_variables(): tfcryoarea = 0.0 tficrn = 0.0 ind_tf_coil = 0.0 + ind_tf_total = 0.0 dx_tf_wp_insertion_gap = 0.01 p_tf_leg_resistive_mw = 0.0 rho_cp = 0.0 From ec4059ebc1f2a35522ad7a998088feeb97fe040f Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 2 Sep 2025 16:31:53 +0100 Subject: [PATCH 09/13] :recycle: Update TF coil self-inductance calculation to return total inductance and adjust related tests --- process/power.py | 5 ++- process/resistive_tf_coil.py | 23 ++++++++------ process/superconducting_tf_coil.py | 23 ++++++++------ process/tf_coil.py | 14 ++++++--- tests/unit/test_tfcoil.py | 50 +++++++++++++++++++++++------- 5 files changed, 78 insertions(+), 37 deletions(-) diff --git a/process/power.py b/process/power.py index 24d1a6c7d2..fcd7ee4878 100644 --- a/process/power.py +++ b/process/power.py @@ -20,6 +20,7 @@ power_variables, primary_pumping_variables, structure_variables, + superconducting_tf_coil_variables, tfcoil_variables, times_variables, ) @@ -2068,7 +2069,9 @@ def superconducting_tf_power_iter_1988( r1ppmw = nsptfc * r1dump * (c_tf_turn_ka / 2.0e0) ** 2 # Energy to dump resistor during quench, MJ - r1emj = nsptfc * e_tf_magnetic_stored_mj / (n_tf_dump_resistors + 0.0001e0) + r1emj = ( + nsptfc * e_tf_magnetic_stored_total_mj / (n_tf_dump_resistors + 0.0001e0) + ) # Total TF coil peak resistive power demand, MVA rpower = (n_tf_coils * 0.0 + res_tf_bus) * c_tf_turn_ka**2 diff --git a/process/resistive_tf_coil.py b/process/resistive_tf_coil.py index cf51f19949..b75c6d0fa4 100644 --- a/process/resistive_tf_coil.py +++ b/process/resistive_tf_coil.py @@ -33,16 +33,19 @@ def run(self, output: bool): self.res_tf_internal_geom() self.tf_res_heating() - tfcoil_variables.ind_tf_coil = self.tf_coil_self_inductance( - dr_tf_inboard=build_variables.dr_tf_inboard, - r_tf_arc=tfcoil_variables.r_tf_arc, - z_tf_arc=tfcoil_variables.z_tf_arc, - itart=physics_variables.itart, - i_tf_shape=tfcoil_variables.i_tf_shape, - z_tf_inside_half=build_variables.z_tf_inside_half, - dr_tf_outboard=build_variables.dr_tf_outboard, - r_tf_outboard_mid=build_variables.r_tf_outboard_mid, - r_tf_inboard_mid=build_variables.r_tf_inboard_mid, + tfcoil_variables.ind_tf_coil, tfcoil_variables.ind_tf_total = ( + self.tf_coil_self_inductance( + dr_tf_inboard=build_variables.dr_tf_inboard, + r_tf_arc=tfcoil_variables.r_tf_arc, + z_tf_arc=tfcoil_variables.z_tf_arc, + itart=physics_variables.itart, + i_tf_shape=tfcoil_variables.i_tf_shape, + z_tf_inside_half=build_variables.z_tf_inside_half, + dr_tf_outboard=build_variables.dr_tf_outboard, + r_tf_outboard_mid=build_variables.r_tf_outboard_mid, + r_tf_inboard_mid=build_variables.r_tf_inboard_mid, + n_tf_coils=tfcoil_variables.n_tf_coils, + ) ) ( diff --git a/process/superconducting_tf_coil.py b/process/superconducting_tf_coil.py index 0d4fbe3794..61f0991556 100644 --- a/process/superconducting_tf_coil.py +++ b/process/superconducting_tf_coil.py @@ -57,16 +57,19 @@ def run(self, output: bool): tfcoil_variables.i_tf_turns_integer, ) - tfcoil_variables.ind_tf_coil = self.tf_coil_self_inductance( - dr_tf_inboard=build_variables.dr_tf_inboard, - r_tf_arc=tfcoil_variables.r_tf_arc, - z_tf_arc=tfcoil_variables.z_tf_arc, - itart=physics_variables.itart, - i_tf_shape=tfcoil_variables.i_tf_shape, - z_tf_inside_half=build_variables.z_tf_inside_half, - dr_tf_outboard=build_variables.dr_tf_outboard, - r_tf_outboard_mid=build_variables.r_tf_outboard_mid, - r_tf_inboard_mid=build_variables.r_tf_inboard_mid, + tfcoil_variables.ind_tf_coil, tfcoil_variables.ind_tf_total = ( + self.tf_coil_self_inductance( + dr_tf_inboard=build_variables.dr_tf_inboard, + r_tf_arc=tfcoil_variables.r_tf_arc, + z_tf_arc=tfcoil_variables.z_tf_arc, + itart=physics_variables.itart, + i_tf_shape=tfcoil_variables.i_tf_shape, + z_tf_inside_half=build_variables.z_tf_inside_half, + dr_tf_outboard=build_variables.dr_tf_outboard, + r_tf_outboard_mid=build_variables.r_tf_outboard_mid, + r_tf_inboard_mid=build_variables.r_tf_inboard_mid, + n_tf_coils=tfcoil_variables.n_tf_coils, + ) ) ( diff --git a/process/tf_coil.py b/process/tf_coil.py index 9927b2e541..11a0975bc6 100644 --- a/process/tf_coil.py +++ b/process/tf_coil.py @@ -2986,7 +2986,8 @@ def tf_coil_self_inductance( dr_tf_outboard: float, r_tf_outboard_mid: float, r_tf_inboard_mid: float, - ) -> float: + n_tf_coils: int, + ) -> tuple[float, float]: """ Calculates the self-inductance of a TF coil. @@ -3012,9 +3013,12 @@ def tf_coil_self_inductance( :type r_tf_outboard_mid: float :param r_tf_inboard_mid: Mid-plane radius of the inboard leg of the TF coil [m]. :type r_tf_inboard_mid: float + :param n_tf_coils: Number of TF coils. + :type n_tf_coils: int + + :returns: Self-inductance of the TF coil [H], Total inductance of all TF coils [H]. + :rtype: float, float - :returns: Self-inductance of the TF coil [H]. - :rtype: float :notes: For the D-shaped coil (i_tf_shape == 1) in a standard (non-TART) configuration @@ -3098,7 +3102,9 @@ def tf_coil_self_inductance( * np.log(r_tf_outboard_mid / r_tf_inboard_mid) ) - return ind_tf_coil + ind_tf_total = ind_tf_coil * n_tf_coils + + return ind_tf_coil, ind_tf_total def generic_tf_coil_area_and_masses(self): """Subroutine to calculate the TF coil areas and masses""" diff --git a/tests/unit/test_tfcoil.py b/tests/unit/test_tfcoil.py index 41e79f2482..22368b489e 100644 --- a/tests/unit/test_tfcoil.py +++ b/tests/unit/test_tfcoil.py @@ -607,17 +607,33 @@ def test_tf_field_and_force(tffieldandforceparam, tfcoil): class TfcindParam(NamedTuple): - z_tf_arc: Any - r_tf_arc: Any - ind_tf_coil: Any - dr_tf_inboard: Any - itart: Any - i_tf_shape: Any - z_tf_inside_half: Any - dr_tf_outboard: Any - r_tf_outboard_mid: Any - r_tf_inboard_mid: Any - expected_ind_tf_coil: Any + z_tf_arc: Any = None + + r_tf_arc: Any = None + + ind_tf_coil: Any = None + + dr_tf_inboard: Any = None + + itart: Any = None + + i_tf_shape: Any = None + + z_tf_inside_half: Any = None + + dr_tf_outboard: Any = None + + r_tf_outboard_mid: Any = None + + r_tf_inboard_mid: Any = None + + n_tf_coils: Any = None + + expected_yarc: Any = None + + expected_ind_tf_coil: Any = None + + expected_ind_tf_total: Any = None @pytest.mark.parametrize( @@ -655,7 +671,9 @@ class TfcindParam(NamedTuple): dr_tf_outboard=0.0, r_tf_outboard_mid=0.0, r_tf_inboard_mid=0.0, + n_tf_coils=16, expected_ind_tf_coil=5.4453892599192845e-06, + expected_ind_tf_total=8.7126228958708553e-05, ), TfcindParam( z_tf_arc=np.array( @@ -687,14 +705,19 @@ class TfcindParam(NamedTuple): dr_tf_outboard=0.0, r_tf_outboard_mid=0.0, r_tf_inboard_mid=0.0, + n_tf_coils=16, expected_ind_tf_coil=5.4524893280368181e-06, + expected_ind_tf_total=8.7239821240593091e-05, ), TfcindParam( dr_tf_inboard=1.208, itart=0, i_tf_shape=0, + expected_ind_tf_coil=6.26806810007207e-06, + expected_ind_tf_total=0.00010028908960115312, z_tf_inside_half=9.0730900215620327, dr_tf_outboard=1.208, + n_tf_coils=16, r_tf_outboard_mid=16.519405859443332, r_tf_inboard_mid=3.5979411851091103, # following 3 params are not used by needed for numba to be happy @@ -720,7 +743,7 @@ def test_tf_coil_self_inductance(tfcindparam, monkeypatch, tfcoil): monkeypatch.setattr(tfcoil_variables, "ind_tf_coil", tfcindparam.ind_tf_coil) - ind_tf_coil = tfcoil.tf_coil_self_inductance( + ind_tf_coil, ind_tf_total = tfcoil.tf_coil_self_inductance( dr_tf_inboard=tfcindparam.dr_tf_inboard, r_tf_arc=tfcindparam.r_tf_arc, z_tf_arc=tfcindparam.z_tf_arc, @@ -730,10 +753,13 @@ def test_tf_coil_self_inductance(tfcindparam, monkeypatch, tfcoil): dr_tf_outboard=tfcindparam.dr_tf_outboard, r_tf_outboard_mid=tfcindparam.r_tf_outboard_mid, r_tf_inboard_mid=tfcindparam.r_tf_inboard_mid, + n_tf_coils=tfcindparam.n_tf_coils, ) assert ind_tf_coil == pytest.approx(tfcindparam.expected_ind_tf_coil) + assert ind_tf_total == pytest.approx(tfcindparam.expected_ind_tf_total) + class TfCoilAreaAndMassesParam(NamedTuple): r_tf_outboard_mid: Any = None From feadc5c59c83dbee71f2438a3b954d89dfaaede3 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Wed, 3 Sep 2025 09:14:51 +0100 Subject: [PATCH 10/13] =?UTF-8?q?=F0=9F=94=84=20-=20Add=20TF=20coil=20char?= =?UTF-8?q?ging=20time=20variable=20and=20update=20power=20calculations=20?= =?UTF-8?q?with=20inductance=20parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- process/data_structure/tfcoil_variables.py | 5 ++++ process/power.py | 27 +++++++++++----------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/process/data_structure/tfcoil_variables.py b/process/data_structure/tfcoil_variables.py index 32481c47fe..17bdbbc7e7 100644 --- a/process/data_structure/tfcoil_variables.py +++ b/process/data_structure/tfcoil_variables.py @@ -669,6 +669,9 @@ ind_tf_total: float = None """Total inductance of all TF coils (H)""" +t_tf_charge: float = None +"""TF coil charging time (s)""" + dx_tf_wp_insertion_gap: float = None """TF coil WP insertion gap (m)""" @@ -1215,6 +1218,7 @@ def init_tfcoil_variables(): global tficrn global ind_tf_coil global ind_tf_total + global t_tf_charge global dx_tf_wp_insertion_gap global p_tf_leg_resistive_mw global rho_cp @@ -1452,6 +1456,7 @@ def init_tfcoil_variables(): tficrn = 0.0 ind_tf_coil = 0.0 ind_tf_total = 0.0 + t_tf_charge = 0.0 dx_tf_wp_insertion_gap = 0.01 p_tf_leg_resistive_mw = 0.0 rho_cp = 0.0 diff --git a/process/power.py b/process/power.py index fcd7ee4878..950e743b8e 100644 --- a/process/power.py +++ b/process/power.py @@ -1846,6 +1846,8 @@ def tfpwr(self, output: bool): v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, e_tf_magnetic_stored_total_mj=superconducting_tf_coil_variables.e_tf_magnetic_stored_total / 1e6, + ind_tf_total=superconducting_tf_coil_variables.ind_tf_total, + ind_tf_coil=superconducting_tf_coil_variables.ind_tf_coil, ) return @@ -1939,6 +1941,8 @@ def superconducting_tf_power_iter_1988( n_tf_coils: int, v_tf_coil_dump_quench_kv: float, e_tf_magnetic_stored_total_mj: float, + ind_tf_total: float, + ind_tf_coil: float ) -> tuple[float, float, float, float, float]: """ Calculates the TF coil power conversion system parameters for superconducting coils. @@ -1955,6 +1959,10 @@ def superconducting_tf_power_iter_1988( :type v_tf_coil_dump_quench_kv: float :param e_tf_magnetic_stored_total_mj: Total stored energy in TF coils (MJ). :type e_tf_magnetic_stored_total_mj: float + :param ind_tf_total: Total inductance of TF coils (H). + :type ind_tf_total: float + :param ind_tf_coil: Inductance of a single TF coil (H). + :type ind_tf_coil: float :returns: Tuple containing: - tfckw (float): DC power supply rating (kW) @@ -1976,7 +1984,6 @@ def superconducting_tf_power_iter_1988( Available: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjX9Ozasb6OAxX1U0EAHV-3C 0QQFnoECBYQAQ&url=https%3A%2F%2Fengineering.purdue.edu%2FCMUXE%2FPublications%2FAHR%2FR88ORNL-FEDC-87-7.pdf& usg=AOvVaw1-LdCefwqI0hJumpHvfTlX&opi=89978449 - ‌ """ N_TF_COIL_BREAKERS = 1.0e0 # number of TF coils per circuit breaker @@ -1992,17 +1999,11 @@ def superconducting_tf_power_iter_1988( # Total steady state TF coil AC power demand (summed later) p_tf_electric_supplies_mw = 0.0e0 - # Inductance of all TF coils, Henries - ind_tf_total = 2.0e0 * e_tf_magnetic_stored_total_mj / c_tf_turn_ka**2 - # Number of circuit breakers n_tf_breakers = n_tf_coils / N_TF_COIL_BREAKERS - # Inductance per TF coil, Henries - ind_tf_coil = ind_tf_total / n_tf_coils - # Aluminium bus section area, sq cm - albusa = c_tf_turn_ka / j_tf_bus_design_ka_cm + a_tf_bus_cm = c_tf_turn_ka / j_tf_bus_design_ka_cm # Total TF system bus length, m len_tf_bus = 8.0e0 * np.pi * rmajor + (1.0e0 + n_tf_breakers) * ( @@ -2010,11 +2011,11 @@ def superconducting_tf_power_iter_1988( ) # Aluminium bus weight, tonnes - m_tf_bus_aluminium_tonnes = 2.7e0 * albusa * len_tf_bus / 1.0e4 + m_tf_bus_aluminium_tonnes = (constants.den_aluminium/1e3) * a_tf_bus_cm * len_tf_bus / 1.0e4 # Total resistance of TF bus, ohms - # res_tf_bus = 2.62e-4 * len_tf_bus / albusa - res_tf_bus = tfcoil_variables.rho_tf_bus * len_tf_bus / (albusa / 10000) + # res_tf_bus = 2.62e-4 * len_tf_bus / a_tf_bus_cm + res_tf_bus = tfcoil_variables.rho_tf_bus * len_tf_bus / (a_tf_bus_cm / 10000) # Total voltage drop across TF bus, volts v_tf_bus = 1000.0e0 * c_tf_turn_ka * res_tf_bus @@ -2217,8 +2218,8 @@ def superconducting_tf_power_iter_1988( po.ovarre( self.outfile, "Aluminium bus cross-sectional area (cm2)", - "(albusa)", - albusa, + "(a_tf_bus_cm)", + a_tf_bus_cm, "OP ", ) po.ovarre( From 2e9812bf46337843b91776b5995ff9873a71e3bd Mon Sep 17 00:00:00 2001 From: mn3981 Date: Wed, 3 Sep 2025 09:24:49 +0100 Subject: [PATCH 11/13] Add TF coil charging time parameter to power calculations --- process/power.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/process/power.py b/process/power.py index 950e743b8e..3a0b2466f1 100644 --- a/process/power.py +++ b/process/power.py @@ -1848,6 +1848,7 @@ def tfpwr(self, output: bool): / 1e6, ind_tf_total=superconducting_tf_coil_variables.ind_tf_total, ind_tf_coil=superconducting_tf_coil_variables.ind_tf_coil, + t_tf_charge=tfcoil_variables.t_tf_charge, ) return @@ -1942,7 +1943,8 @@ def superconducting_tf_power_iter_1988( v_tf_coil_dump_quench_kv: float, e_tf_magnetic_stored_total_mj: float, ind_tf_total: float, - ind_tf_coil: float + ind_tf_coil: float, + t_tf_charge: float = 4.0 * 3600.0, # Default: 4 hours in seconds ) -> tuple[float, float, float, float, float]: """ Calculates the TF coil power conversion system parameters for superconducting coils. @@ -1963,6 +1965,8 @@ def superconducting_tf_power_iter_1988( :type ind_tf_total: float :param ind_tf_coil: Inductance of a single TF coil (H). :type ind_tf_coil: float + :param t_tf_charge: TF coil charging time (s). + :type t_tf_charge: float :returns: Tuple containing: - tfckw (float): DC power supply rating (kW) @@ -1993,7 +1997,6 @@ def superconducting_tf_power_iter_1988( fspc2 = 0.8e0 # floor space coefficient for circuit breakers fspc3 = 0.4e0 # floor space coefficient for load centres - T_TF_CHARGE_HOURS = 4.0e0 # charge time of the coils, hours nsptfc = 1.0e0 # superconducting (1.0 = superconducting, 0.0 = resistive) # Total steady state TF coil AC power demand (summed later) @@ -2011,7 +2014,9 @@ def superconducting_tf_power_iter_1988( ) # Aluminium bus weight, tonnes - m_tf_bus_aluminium_tonnes = (constants.den_aluminium/1e3) * a_tf_bus_cm * len_tf_bus / 1.0e4 + m_tf_bus_aluminium_tonnes = ( + (constants.den_aluminium / 1e3) * a_tf_bus_cm * len_tf_bus / 1.0e4 + ) # Total resistance of TF bus, ohms # res_tf_bus = 2.62e-4 * len_tf_bus / a_tf_bus_cm @@ -2024,7 +2029,7 @@ def superconducting_tf_power_iter_1988( rcoils = 0.0 # Total impedance, ohms - ztotal = res_tf_bus + rcoils + ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) + ztotal = res_tf_bus + rcoils + ind_tf_total / t_tf_charge # Charging voltage for the TF coils, volts tfcv = 1000.0e0 * c_tf_turn_ka * ztotal @@ -2078,7 +2083,7 @@ def superconducting_tf_power_iter_1988( rpower = (n_tf_coils * 0.0 + res_tf_bus) * c_tf_turn_ka**2 # Total TF coil peak inductive power demand, MVA - xpower = ind_tf_total / (3600.0e0 * T_TF_CHARGE_HOURS) * c_tf_turn_ka**2 + xpower = ind_tf_total / t_tf_charge * c_tf_turn_ka**2 # Building space: # Power modules floor space, m2 @@ -2137,9 +2142,9 @@ def superconducting_tf_power_iter_1988( ) po.ovarre( self.outfile, - "TF coil charge time (hours)", - "(T_TF_CHARGE_HOURS)", - T_TF_CHARGE_HOURS, + "TF coil charge time (s)", + "(t_tf_charge)", + t_tf_charge, ) po.ovarre( self.outfile, From a03063cd01ee81c090bbf3d6d1e17e945f78dd8a Mon Sep 17 00:00:00 2001 From: mn3981 Date: Wed, 3 Sep 2025 09:27:02 +0100 Subject: [PATCH 12/13] :book: Add guidelines for impedance naming conventions in style guide --- documentation/development/standards.md | 6 ++++ .../eng-models/power-requirements.md | 4 +-- process/power.py | 35 +++++++++++-------- tests/unit/test_tfcoil.py | 1 - 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/documentation/development/standards.md b/documentation/development/standards.md index 3767925f44..00179271d4 100644 --- a/documentation/development/standards.md +++ b/documentation/development/standards.md @@ -284,6 +284,12 @@ This should be used for units of $\text{kg} \cdot \text{m}^{-2}\text{s}^{-1}$ --------------------- +##### Impedances + +- Impedances should start with the `imp_` prefix + +--------------------- + ##### Resistivity - Resistivity variables should start with the `rho_` prefix diff --git a/documentation/eng-models/power-requirements.md b/documentation/eng-models/power-requirements.md index 90d9e20bdc..3969d662f4 100644 --- a/documentation/eng-models/power-requirements.md +++ b/documentation/eng-models/power-requirements.md @@ -5,10 +5,10 @@ The main power flow is controlled by `power.py`. The main class `Power` controls ### TF Coils -Generall the newt power consumption of one magnet in $\text{VA}$ is given by: +Generall the net power consumption of one magnet in $\text{VA}$ is given by: $$ -P_{\text{TF,electric}} = \left(R_{\text{TF,coil}}+R_{\text{joints}}+R_{\text{feeder}}\right) \times I_{\text{TF,coil}}^2 +P_{\text{TF,electric}} = \left(\Omega_{\text{TF,coil}}+\Omega_{\text{joints}}+\Omega_{\text{feeder}}\right) \times I_{\text{TF,coil}}^2 \\ +\left(L_{\text{TF,coil-self}}+L_{\text{feeder}}\right)\frac{dI}{dt} $$ diff --git a/process/power.py b/process/power.py index 3a0b2466f1..5cd6d9f04e 100644 --- a/process/power.py +++ b/process/power.py @@ -1846,8 +1846,8 @@ def tfpwr(self, output: bool): v_tf_coil_dump_quench_kv=tfcoil_variables.v_tf_coil_dump_quench_kv, e_tf_magnetic_stored_total_mj=superconducting_tf_coil_variables.e_tf_magnetic_stored_total / 1e6, - ind_tf_total=superconducting_tf_coil_variables.ind_tf_total, - ind_tf_coil=superconducting_tf_coil_variables.ind_tf_coil, + ind_tf_total=tfcoil_variables.ind_tf_total, + ind_tf_coil=tfcoil_variables.ind_tf_coil, t_tf_charge=tfcoil_variables.t_tf_charge, ) return @@ -2026,34 +2026,34 @@ def superconducting_tf_power_iter_1988( v_tf_bus = 1000.0e0 * c_tf_turn_ka * res_tf_bus # Total resistance of the TF coils, ohms - rcoils = 0.0 + res_tf_coils = 0.0 # Total impedance, ohms - ztotal = res_tf_bus + rcoils + ind_tf_total / t_tf_charge + imp_tf_total = res_tf_bus + res_tf_coils + ind_tf_total / t_tf_charge # Charging voltage for the TF coils, volts - tfcv = 1000.0e0 * c_tf_turn_ka * ztotal + v_tf_charge = 1000.0e0 * c_tf_turn_ka * imp_tf_total # Number of TF power modules - ntfpm = (c_tf_turn_ka * (1.0e0 + nsptfc)) / 5.0e0 + n_tf_power_modules = (c_tf_turn_ka * (1.0e0 + nsptfc)) / 5.0e0 # TF coil power module voltage, volts - tfpmv = rtfps * tfcv / (1.0e0 + nsptfc) + v_tf_power_module = rtfps * v_tf_charge / (1.0e0 + nsptfc) # TF coil power supply voltage, volts - tfpsv = rtfps * tfcv + tfpsv = rtfps * v_tf_charge # Power supply current, kA tfpska = rtfps * c_tf_turn_ka # TF power module current, kA - tfpmka = rtfps * c_tf_turn_ka / (ntfpm / (1.0e0 + nsptfc)) + tfpmka = rtfps * c_tf_turn_ka / (n_tf_power_modules / (1.0e0 + nsptfc)) # TF power module power, kW - tfpmkw = tfpmv * tfpmka + tfpmkw = v_tf_power_module * tfpmka # Available DC power for charging the TF coils, kW - tfckw = tfpmkw * ntfpm + tfckw = tfpmkw * n_tf_power_modules # Peak AC power needed to charge coils, kW tfackw = tfckw / 0.9e0 @@ -2087,7 +2087,7 @@ def superconducting_tf_power_iter_1988( # Building space: # Power modules floor space, m2 - part1 = fspc1 * ntfpm * tfpmkw**0.667e0 + part1 = fspc1 * n_tf_power_modules * tfpmkw**0.667e0 # Circuit breakers floor space, m2 part2 = ( @@ -2156,14 +2156,19 @@ def superconducting_tf_power_iter_1988( po.ovarre( self.outfile, "Total resistance of TF coils (ohm)", - "(rcoils)", - rcoils, + "(res_tf_coils)", + res_tf_coils, "OP ", ) # MDK Remove this as it leads to confusion between (a) total inductance/n_tf_coils, or (b) # self-inductance of one single coil # po.ovarre(outfile,'Inductance per TF coil (H)','(ind_tf_coil)',ind_tf_coil, 'OP ') - po.ovarre(self.outfile, "TF coil charging voltage (V)", "(tfcv)", tfcv) + po.ovarre( + self.outfile, + "TF coil charging voltage (V)", + "(v_tf_charge)", + v_tf_charge, + ) po.ovarre( self.outfile, "Number of DC circuit breakers", diff --git a/tests/unit/test_tfcoil.py b/tests/unit/test_tfcoil.py index 22368b489e..8106894d93 100644 --- a/tests/unit/test_tfcoil.py +++ b/tests/unit/test_tfcoil.py @@ -724,7 +724,6 @@ class TfcindParam(NamedTuple): z_tf_arc=np.zeros(3), r_tf_arc=np.zeros(3), ind_tf_coil=0.0, - expected_ind_tf_coil=6.26806810007207e-06, ), ), ) From e9db0f0f1597ee3e23bcb4931bbb021eaf119158 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Mon, 29 Sep 2025 15:07:17 +0100 Subject: [PATCH 13/13] :sparkle: Enhance superconducting TF coil power requirements section with detailed calculations for bus dimensions, resistance, voltage drop, impedance, and charging voltage --- .../eng-models/power-requirements.md | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/documentation/eng-models/power-requirements.md b/documentation/eng-models/power-requirements.md index 3969d662f4..31da3e0497 100644 --- a/documentation/eng-models/power-requirements.md +++ b/documentation/eng-models/power-requirements.md @@ -19,15 +19,43 @@ $$ #### Superconducting TF coil power requirements | `superconducting_tf_power_iter_1988()` -Some details of the auxiliary systems are as follows. +The electrical power requirements for the superconducting TF coils are as follows: -`tfcpwr` calculates the TF coil power conversion system parameters. Only the steady-state power consumption for a superconducting TFC system is described here. +1. Calculate the cross-sectional areas of the TF bus by taking. -The TF current is carried from the power supplies to the reactor by room-temperature aluminium busbars, organised in $N_{circuit}$ circuits. The total length of the busbars is (somehwat arbitrarily) given by + $$ + A_{\text{bus}} = \frac{\overbrace{I_{\text{TF,turn}}}^{\texttt{c_tf_turn_ka}}}{J_{\text{TF,design}}} + $$ -$$ -L_bus = 8 \pi R_0 + (1 + N_{circuit}) (12 R_0 + 80) -$$ +2. The total bus length is defined as + + $$ + L_{\text{TF,bus}} = 8 \pi R_0 + (1 + N_{\text{circuit}}) (12 R_0 + 80) + $$ + +3. The total resistance of the bus bar is calculated + + $$ + \Omega_{\text{TF,bus}} = \frac{\overbrace{\rho_{\text{TF,bus}}}^{\texttt{rho_tf_bus}}}{L_{\text{TF,bus}}}{A_{\text{TF,bus}}} + $$ + +4. The total voltage drop across the busbar is given by: + + $$ + V_{\text{TF,bus}} = I_{\text{TF,turn}} \times \Omega_{\text{TF,bus}} + $$ + +5. The total impedance of the circuit is given by: + + $$ + Z_{\text{TF,total}} = \Omega_{\text{TF,bus}} + \frac{L_{\text{TF,total}}}{t_{\text{TF,charge}}} + $$ + +6. The charging voltage is thus: + + $$ + V_{\text{TF,charge}} = I_{\text{TF,turn}} \times L_{\text{TF,total}} + $$ The resistivity of the busbar is 2.62e-8 ohm.m (0.0262 ohm.mm²/m) (hard-coded).