From 285665403171b4a0b8fa5a63d78f8d4a41ef8790 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Dec 2025 10:42:56 +0000 Subject: [PATCH 01/35] Add VacuumVessel class and integrate into Caller model --- process/caller.py | 2 ++ process/main.py | 3 ++- process/vacuum.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/process/caller.py b/process/caller.py index 0a93243a15..3f5b0a0eff 100644 --- a/process/caller.py +++ b/process/caller.py @@ -276,6 +276,8 @@ def _call_models_once(self, xc: np.ndarray) -> None: # First wall model self.models.fw.run() + self.models.vacuum_vessel.run() + # Blanket model """Blanket switch values No. | model diff --git a/process/main.py b/process/main.py index 367fe51a76..6a8ab9b678 100644 --- a/process/main.py +++ b/process/main.py @@ -105,7 +105,7 @@ from process.structure import Structure from process.superconducting_tf_coil import SuperconductingTFCoil from process.tf_coil import TFCoil -from process.vacuum import Vacuum +from process.vacuum import Vacuum, VacuumVessel from process.water_use import WaterUse os.environ["PYTHON_PROCESS_ROOT"] = os.path.join(os.path.dirname(__file__)) @@ -664,6 +664,7 @@ def __init__(self): self.availability = Availability() self.buildings = Buildings() self.vacuum = Vacuum() + self.vacuum_vessel = VacuumVessel() self.water_use = WaterUse() self.pulse = Pulse() self.ife = IFE(availability=self.availability, costs=self.costs) diff --git a/process/vacuum.py b/process/vacuum.py index 13d5452125..48d3ac506e 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -5,6 +5,7 @@ from process import constants from process import process_output as po +from process.data_structure import blanket_library as blanket_library from process.data_structure import build_variables as buv from process.data_structure import divertor_variables as dv from process.data_structure import physics_variables as pv @@ -686,3 +687,60 @@ def vacuum( ) return pumpn, nduct, dlscalc, mvdsh, dimax + + +class VacuumVessel: + """Class containing vacuum vessel routines""" + + def __init__(self) -> None: + pass + + def run(self) -> None: + blanket_library.dz_vv_half = self.calculate_vessel_half_height( + z_tf_inside_half=buv.z_tf_inside_half, + dz_shld_vv_gap=buv.dz_shld_vv_gap, + dz_vv_lower=buv.dz_vv_lower, + n_divertors=pv.n_divertors, + dz_blkt_upper=buv.dz_blkt_upper, + dz_shld_upper=buv.dz_shld_upper, + z_plasma_xpoint_upper=buv.z_plasma_xpoint_upper, + dr_fw_plasma_gap_inboard=buv.dr_fw_plasma_gap_inboard, + dr_fw_plasma_gap_outboard=buv.dr_fw_plasma_gap_outboard, + dr_fw_inboard=buv.dr_fw_inboard, + dr_fw_outboard=buv.dr_fw_outboard, + ) + + def calculate_vessel_half_height( + self, + z_tf_inside_half: float, + dz_shld_vv_gap: float, + dz_vv_lower: float, + n_divertors: int, + dz_blkt_upper: float, + dz_shld_upper: float, + z_plasma_xpoint_upper: float, + dr_fw_plasma_gap_inboard: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_inboard: float, + dr_fw_outboard: float, + ) -> float: + """Calculate vacuum vessel internal half-height (m)""" + + z_bottom = z_tf_inside_half - dz_shld_vv_gap - dz_vv_lower + + # Calculate component internal upper half-height (m) + # If a double null machine then symmetric + if n_divertors == 2: + z_top = z_bottom + else: + z_top = z_plasma_xpoint_upper + 0.5 * ( + dr_fw_plasma_gap_inboard + + dr_fw_plasma_gap_outboard + + dr_fw_inboard + + dr_fw_outboard + + dz_blkt_upper + + dz_shld_upper + ) + + # Average of top and bottom (m) + return 0.5 * (z_top + z_bottom) From c8f1ad41d4bc864dd2f44c2857b81daccf147f5d Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Dec 2025 11:01:36 +0000 Subject: [PATCH 02/35] Add calculate_dshaped_vessel_volumes method to VacuumVessel class --- process/vacuum.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/process/vacuum.py b/process/vacuum.py index 48d3ac506e..b3402e72e0 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -5,9 +5,11 @@ from process import constants from process import process_output as po +from process.blanket_library import dshellvol from process.data_structure import blanket_library as blanket_library from process.data_structure import build_variables as buv from process.data_structure import divertor_variables as dv +from process.data_structure import fwbs_variables as fwbs_variables from process.data_structure import physics_variables as pv from process.data_structure import tfcoil_variables as tfv from process.data_structure import times_variables as tv @@ -710,6 +712,20 @@ def run(self) -> None: dr_fw_outboard=buv.dr_fw_outboard, ) + ( + blanket_library.vol_vv_inboard, + blanket_library.vol_vv_outboard, + fwbs_variables.vol_vv, + ) = self.calculate_dshaped_vessel_volumes( + rsldi=buv.rsldi, + rsldo=buv.rsldo, + dz_vv_half=blanket_library.dz_vv_half, + dr_vv_inboard=buv.dr_vv_inboard, + dr_vv_outboard=buv.dr_vv_outboard, + dz_vv_upper=buv.dz_vv_upper, + dz_vv_lower=buv.dz_vv_lower, + ) + def calculate_vessel_half_height( self, z_tf_inside_half: float, @@ -744,3 +760,33 @@ def calculate_vessel_half_height( # Average of top and bottom (m) return 0.5 * (z_top + z_bottom) + + def calculate_dshaped_vessel_volumes( + self, + rsldi: float, + rsldo: float, + dz_vv_half: float, + dr_vv_inboard: float, + dr_vv_outboard: float, + dz_vv_upper: float, + dz_vv_lower: float, + ) -> None: + """Calculate volumes of D-shaped vacuum vessel segments""" + + r_1 = rsldi + r_2 = rsldo - r_1 + + ( + vol_vv_inboard, + vol_vv_outboard, + vol_vv, + ) = dshellvol( + rmajor=r_1, + rminor=r_2, + zminor=dz_vv_half, + drin=dr_vv_inboard, + drout=dr_vv_outboard, + dz=(dz_vv_upper + dz_vv_lower) / 2, + ) + + return vol_vv_inboard, vol_vv_outboard, vol_vv From 223eaa89777b91b992b0afe5920f4b31aa5842a3 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 5 Dec 2025 11:14:48 +0000 Subject: [PATCH 03/35] Add calculate_elliptical_vessel_volumes method to VacuumVessel class --- process/vacuum.py | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/process/vacuum.py b/process/vacuum.py index b3402e72e0..0e049255de 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -5,7 +5,7 @@ from process import constants from process import process_output as po -from process.blanket_library import dshellvol +from process.blanket_library import dshellvol, eshellvol from process.data_structure import blanket_library as blanket_library from process.data_structure import build_variables as buv from process.data_structure import divertor_variables as dv @@ -770,7 +770,7 @@ def calculate_dshaped_vessel_volumes( dr_vv_outboard: float, dz_vv_upper: float, dz_vv_lower: float, - ) -> None: + ) -> tuple[float, float, float]: """Calculate volumes of D-shaped vacuum vessel segments""" r_1 = rsldi @@ -790,3 +790,40 @@ def calculate_dshaped_vessel_volumes( ) return vol_vv_inboard, vol_vv_outboard, vol_vv + + def calculate_elliptical_vessel_volumes( + self, + rmajor: float, + rminor: float, + triang: float, + rsldi: float, + rsldo: float, + dz_vv_half: float, + dr_vv_inboard: float, + dr_vv_outboard: float, + dz_vv_upper: float, + dz_vv_lower: float, + ) -> tuple[float, float, float]: + # Major radius to centre of inboard and outboard ellipses (m) + # (coincident in radius with top of plasma) + r_1 = rmajor - rminor * triang + + # Calculate distance between r1 and outer edge of inboard ... + # ... section (m) + r_2 = r_1 - rsldi + r_3 = rsldo - r_1 + + ( + vol_vv_inboard, + vol_vv_outboard, + vol_vv, + ) = eshellvol( + r_1, + r_2, + r_3, + dz_vv_half, + dr_vv_inboard, + dr_vv_outboard, + (dz_vv_upper + dz_vv_lower) / 2, + ) + return vol_vv_inboard, vol_vv_outboard, vol_vv From 134a43cb76a783e1905b64ab022eec7ad5d278ad Mon Sep 17 00:00:00 2001 From: mn3981 Date: Wed, 7 Jan 2026 15:00:24 +0000 Subject: [PATCH 04/35] :fire: Remove now redundant vacuum calcs from blanket library --- process/blanket_library.py | 51 ++------------------------------- process/caller.py | 4 +-- process/hcpb.py | 8 +++--- process/vacuum.py | 58 +++++++++++++++++++++++++++----------- 4 files changed, 51 insertions(+), 70 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index f90c0f9921..be01485ae4 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -57,25 +57,17 @@ def component_volumes(self): blanket_library.dz_blkt_half = self.component_half_height(icomponent=0) # Shield blanket_library.dz_shld_half = self.component_half_height(icomponent=1) - # Vacuum Vessel - blanket_library.dz_vv_half = self.component_half_height(icomponent=2) # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: - for icomponent in range(3): + for icomponent in range(2): self.dshaped_component(icomponent) # Elliptical blanket and shield else: - for icomponent in range(3): + for icomponent in range(2): self.elliptical_component(icomponent) - # This will fail the hts_REBCO and 2D_scan regression tests, - # the number of VMCON iterations (nviter) is different. - # Seems to be because in the blanket calculations (icomponent=0): - # r2 = 1.3836567143743970 rather than old value of r2 = 1.3836567143743972, - # r3 = 3.7009701431231936 rather than r3 = 3.7009701431231923. - # Apply coverage factors to volumes and surface areas self.apply_coverage_factors() @@ -109,7 +101,7 @@ def component_half_height(self, icomponent: int): - build_variables.dz_vv_lower ) else: - raise ProcessValueError(f"{icomponent=} is invalid, it must be either 0,1,2") + raise ProcessValueError(f"{icomponent=} is invalid, it must be either 0,1") # Calculate component internal upper half-height (m) # If a double null machine then symmetric @@ -126,11 +118,6 @@ def component_half_height(self, icomponent: int): # Shield if icomponent == 1: htop = htop + build_variables.dz_blkt_upper - # Vacuum Vessel - if icomponent == 2: - htop = ( - htop + build_variables.dz_blkt_upper + build_variables.dz_shld_upper - ) # Average of top and bottom (m) return 0.5 * (htop + hbot) @@ -209,19 +196,6 @@ def dshaped_component(self, icomponent: int): build_variables.dr_shld_outboard, build_variables.dz_shld_upper, ) - elif icomponent == 2: - ( - blanket_library.vol_vv_inboard, - blanket_library.vol_vv_outboard, - fwbs_variables.vol_vv, - ) = dshellvol( - r1, - r2, - blanket_library.dz_vv_half, - build_variables.dr_vv_inboard, - build_variables.dr_vv_outboard, - (build_variables.dz_vv_upper + build_variables.dz_vv_lower) / 2, - ) def elliptical_component(self, icomponent: int): """Calculate component surface area and volume using elliptical scheme @@ -299,20 +273,6 @@ def elliptical_component(self, icomponent: int): build_variables.dr_shld_outboard, build_variables.dz_shld_upper, ) - if icomponent == 2: - ( - blanket_library.vol_vv_inboard, - blanket_library.vol_vv_outboard, - fwbs_variables.vol_vv, - ) = eshellvol( - r1, - r2, - r3, - blanket_library.dz_vv_half, - build_variables.dr_vv_inboard, - build_variables.dr_vv_outboard, - (build_variables.dz_vv_upper + build_variables.dz_vv_lower) / 2, - ) def apply_coverage_factors(self): """Apply coverage factors to volumes @@ -383,11 +343,6 @@ def apply_coverage_factors(self): blanket_library.vol_shld_inboard + blanket_library.vol_shld_outboard ) - # Apply vacuum vessel coverage factor - # moved from dshaped_* and elliptical_* to keep coverage factor - # changes in the same location. - fwbs_variables.vol_vv = fwbs_variables.fvoldw * fwbs_variables.vol_vv - def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. Uses middle value of input and output temperatures of coolant. diff --git a/process/caller.py b/process/caller.py index 3f5b0a0eff..8cd74fefc8 100644 --- a/process/caller.py +++ b/process/caller.py @@ -276,8 +276,6 @@ def _call_models_once(self, xc: np.ndarray) -> None: # First wall model self.models.fw.run() - self.models.vacuum_vessel.run() - # Blanket model """Blanket switch values No. | model @@ -298,6 +296,8 @@ def _call_models_once(self, xc: np.ndarray) -> None: # DCLL model self.models.dcll.run(output=False) + self.models.vacuum_vessel.run() + self.models.divertor.run(output=False) self.models.cryostat.run() diff --git a/process/hcpb.py b/process/hcpb.py index 288beb7a51..6b96e6cd6e 100644 --- a/process/hcpb.py +++ b/process/hcpb.py @@ -474,10 +474,10 @@ def nuclear_heating_magnets(self, output: bool): if build_variables.dr_vv_outboard > d_vv_all: d_vv_all = build_variables.dr_vv_outboard - if d_vv_all > 1.0e-6: - ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv - else: - ccfe_hcpb_module.vv_density = 0.0 + # if d_vv_all > 1.0e-6: + # ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv + # else: + # ccfe_hcpb_module.vv_density = 0.0 # Calculation of average blanket/shield thickness [m] if physics_variables.itart == 1: diff --git a/process/vacuum.py b/process/vacuum.py index 0e049255de..7b2dbed13d 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -9,7 +9,9 @@ from process.data_structure import blanket_library as blanket_library from process.data_structure import build_variables as buv from process.data_structure import divertor_variables as dv +from process.data_structure import ccfe_hcpb_module as ccfe_hcpb_module from process.data_structure import fwbs_variables as fwbs_variables +from process.data_structure import physics_variables as physics_variables from process.data_structure import physics_variables as pv from process.data_structure import tfcoil_variables as tfv from process.data_structure import times_variables as tv @@ -711,20 +713,45 @@ def run(self) -> None: dr_fw_inboard=buv.dr_fw_inboard, dr_fw_outboard=buv.dr_fw_outboard, ) - - ( - blanket_library.vol_vv_inboard, - blanket_library.vol_vv_outboard, - fwbs_variables.vol_vv, - ) = self.calculate_dshaped_vessel_volumes( - rsldi=buv.rsldi, - rsldo=buv.rsldo, - dz_vv_half=blanket_library.dz_vv_half, - dr_vv_inboard=buv.dr_vv_inboard, - dr_vv_outboard=buv.dr_vv_outboard, - dz_vv_upper=buv.dz_vv_upper, - dz_vv_lower=buv.dz_vv_lower, - ) + # D-shaped blanket and shield + if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: + ( + blanket_library.vol_vv_inboard, + blanket_library.vol_vv_outboard, + fwbs_variables.vol_vv, + ) = self.calculate_dshaped_vessel_volumes( + rsldi=buv.rsldi, + rsldo=buv.rsldo, + dz_vv_half=blanket_library.dz_vv_half, + dr_vv_inboard=buv.dr_vv_inboard, + dr_vv_outboard=buv.dr_vv_outboard, + dz_vv_upper=buv.dz_vv_upper, + dz_vv_lower=buv.dz_vv_lower, + ) + else: + ( + blanket_library.vol_vv_inboard, + blanket_library.vol_vv_outboard, + fwbs_variables.vol_vv, + ) = self.calculate_elliptical_vessel_volumes( + rmajor=pv.rmajor, + rminor=pv.rminor, + triang=pv.triang, + rsldi=buv.rsldi, + rsldo=buv.rsldo, + dz_vv_half=blanket_library.dz_vv_half, + dr_vv_inboard=buv.dr_vv_inboard, + dr_vv_outboard=buv.dr_vv_outboard, + dz_vv_upper=buv.dz_vv_upper, + dz_vv_lower=buv.dz_vv_lower, + ) + + # Apply vacuum vessel coverage factor + # moved from dshaped_* and elliptical_* to keep coverage factor + # changes in the same location. + fwbs_variables.vol_vv = fwbs_variables.fvoldw * fwbs_variables.vol_vv + + ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv def calculate_vessel_half_height( self, @@ -754,9 +781,8 @@ def calculate_vessel_half_height( + dr_fw_plasma_gap_outboard + dr_fw_inboard + dr_fw_outboard - + dz_blkt_upper - + dz_shld_upper ) + z_top = z_top + dz_blkt_upper + dz_shld_upper # Average of top and bottom (m) return 0.5 * (z_top + z_bottom) From 25635e0e6ab5e02e271fc0756815832c30957c49 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 20 Jan 2026 11:14:45 +0000 Subject: [PATCH 05/35] Refactor BlanketLibrary: remove vacuum vessel calculations and update tests for elliptical vessel volumes --- process/blanket_library.py | 10 ---- tests/unit/test_blanket_library.py | 92 ------------------------------ tests/unit/test_vacuum.py | 80 +++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 103 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index be01485ae4..5dea134350 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -93,13 +93,6 @@ def component_half_height(self, icomponent: int): + build_variables.dz_xpoint_divertor + divertor_variables.dz_divertor ) - # Vacuum vessel - elif icomponent == 2: - hbot = ( - build_variables.z_tf_inside_half - - build_variables.dz_shld_vv_gap - - build_variables.dz_vv_lower - ) else: raise ProcessValueError(f"{icomponent=} is invalid, it must be either 0,1") @@ -151,9 +144,6 @@ def dshaped_component(self, icomponent: int): # Sheild if icomponent == 1: r2 = build_variables.dr_blkt_inboard + r2 + build_variables.dr_blkt_outboard - # Vaccum Vessel - if icomponent == 2: - r2 = build_variables.r_shld_outboard_outer - r1 # Calculate surface area, assuming 100% coverage if icomponent == 0: diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index 2ec8f49989..6d4a71ef9f 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -1030,58 +1030,6 @@ class EllipticalComponentParam(NamedTuple): expected_vol_vv_outboard=0, expected_icomponent=1, ), - EllipticalComponentParam( - r_shld_inboard_inner=4.0833333333333339, - dr_shld_inboard=0.30000000000000004, - dr_blkt_inboard=0.70000000000000007, - r_shld_outboard_outer=12.716666666666667, - dr_shld_outboard=0.80000000000000004, - dr_blkt_outboard=1, - a_blkt_inboard_surface=664.9687712975541, - a_blkt_outboard_surface=1101.3666396424403, - a_blkt_total_surface=1766.3354109399943, - dz_blkt_upper=0.85000000000000009, - a_shld_inboard_surface=700.06731267447844, - a_shld_outboard_surface=1344.1106481995357, - a_shld_total_surface=2044.1779608740142, - dz_shld_upper=0.59999999999999998, - dr_vv_inboard=0.30000000000000004, - dr_vv_outboard=0.30000000000000004, - dz_vv_upper=0.30000000000000004, - dz_vv_lower=0.30000000000000004, - vol_blkt_inboard=315.83946385183026, - vol_blkt_outboard=1020.3677420460117, - vol_blkt_total=1336.207205897842, - vol_shld_total=1124.4621612595051, - vol_vv=0, - rmajor=8, - rminor=2.6666666666666665, - triang=0.5, - vol_shld_inboard=177.89822933168091, - vol_shld_outboard=946.56393192782434, - vol_vv_inboard=0, - vol_vv_outboard=0, - dz_blkt_half=5.9532752487304119, - dz_shld_half=6.8032752487304133, - dz_vv_half=7.5032752487304135, - icomponent=2, - expected_a_blkt_inboard_surface=664.9687712975541, - expected_a_blkt_outboard_surface=1101.3666396424403, - expected_a_blkt_total_surface=1766.3354109399943, - expected_a_shld_inboard_surface=700.06731267447844, - expected_a_shld_outboard_surface=1344.1106481995357, - expected_a_shld_total_surface=2044.1779608740142, - expected_vol_blkt_inboard=315.83946385183026, - expected_vol_blkt_outboard=1020.3677420460117, - expected_volblkt=1336.207205897842, - expected_vol_shld_total=1124.4621612595051, - expected_vol_vv=584.07334775041659, - expected_vol_shld_inboard=177.89822933168091, - expected_vol_shld_outboard=946.56393192782434, - expected_vol_vv_inboard=143.03162449152501, - expected_vol_vv_outboard=441.04172325889158, - expected_icomponent=2, - ), ), ) def test_elliptical_component( @@ -1156,18 +1104,6 @@ def test_elliptical_component( monkeypatch.setattr( build_variables, "dz_shld_upper", ellipticalcomponentparam.dz_shld_upper ) - monkeypatch.setattr( - build_variables, "dr_vv_inboard", ellipticalcomponentparam.dr_vv_inboard - ) - monkeypatch.setattr( - build_variables, "dr_vv_outboard", ellipticalcomponentparam.dr_vv_outboard - ) - monkeypatch.setattr( - build_variables, "dz_vv_upper", ellipticalcomponentparam.dz_vv_upper - ) - monkeypatch.setattr( - build_variables, "dz_vv_lower", ellipticalcomponentparam.dz_vv_lower - ) monkeypatch.setattr( fwbs_variables, "vol_blkt_inboard", ellipticalcomponentparam.vol_blkt_inboard ) @@ -1180,7 +1116,6 @@ def test_elliptical_component( monkeypatch.setattr( fwbs_variables, "vol_shld_total", ellipticalcomponentparam.vol_shld_total ) - monkeypatch.setattr(fwbs_variables, "vol_vv", ellipticalcomponentparam.vol_vv) monkeypatch.setattr(physics_variables, "rmajor", ellipticalcomponentparam.rmajor) monkeypatch.setattr(physics_variables, "rminor", ellipticalcomponentparam.rminor) monkeypatch.setattr(physics_variables, "triang", ellipticalcomponentparam.triang) @@ -1190,21 +1125,12 @@ def test_elliptical_component( monkeypatch.setattr( blanket_library, "vol_shld_outboard", ellipticalcomponentparam.vol_shld_outboard ) - monkeypatch.setattr( - blanket_library, "vol_vv_inboard", ellipticalcomponentparam.vol_vv_inboard - ) - monkeypatch.setattr( - blanket_library, "vol_vv_outboard", ellipticalcomponentparam.vol_vv_outboard - ) monkeypatch.setattr( blanket_library, "dz_blkt_half", ellipticalcomponentparam.dz_blkt_half ) monkeypatch.setattr( blanket_library, "dz_shld_half", ellipticalcomponentparam.dz_shld_half ) - monkeypatch.setattr( - blanket_library, "dz_vv_half", ellipticalcomponentparam.dz_vv_half - ) blanket_library_fixture.elliptical_component(ellipticalcomponentparam.icomponent) @@ -1238,21 +1164,12 @@ def test_elliptical_component( assert fwbs_variables.vol_shld_total == pytest.approx( ellipticalcomponentparam.expected_vol_shld_total ) - assert fwbs_variables.vol_vv == pytest.approx( - ellipticalcomponentparam.expected_vol_vv - ) assert blanket_library.vol_shld_inboard == pytest.approx( ellipticalcomponentparam.expected_vol_shld_inboard ) assert blanket_library.vol_shld_outboard == pytest.approx( ellipticalcomponentparam.expected_vol_shld_outboard ) - assert blanket_library.vol_vv_inboard == pytest.approx( - ellipticalcomponentparam.expected_vol_vv_inboard - ) - assert blanket_library.vol_vv_outboard == pytest.approx( - ellipticalcomponentparam.expected_vol_vv_outboard - ) class ApplyCoverageFactorsParam(NamedTuple): @@ -1270,8 +1187,6 @@ class ApplyCoverageFactorsParam(NamedTuple): fvolsi: Any = None fvolso: Any = None vol_shld_total: Any = None - vol_vv: Any = None - fvoldw: Any = None n_divertors: Any = None vol_shld_inboard: Any = None vol_shld_outboard: Any = None @@ -1304,8 +1219,6 @@ class ApplyCoverageFactorsParam(NamedTuple): fvolsi=1, fvolso=0.64000000000000001, vol_shld_total=1124.4621612595051, - vol_vv=584.07334775041659, - fvoldw=1.74, n_divertors=1, vol_shld_inboard=177.89822933168091, vol_shld_outboard=946.56393192782434, @@ -1387,8 +1300,6 @@ def test_apply_coverage_factors( monkeypatch.setattr( fwbs_variables, "vol_shld_total", applycoveragefactorsparam.vol_shld_total ) - monkeypatch.setattr(fwbs_variables, "vol_vv", applycoveragefactorsparam.vol_vv) - monkeypatch.setattr(fwbs_variables, "fvoldw", applycoveragefactorsparam.fvoldw) monkeypatch.setattr( divertor_variables, "n_divertors", applycoveragefactorsparam.n_divertors ) @@ -1424,9 +1335,6 @@ def test_apply_coverage_factors( assert fwbs_variables.vol_shld_total == pytest.approx( applycoveragefactorsparam.expected_vol_shld_total ) - assert fwbs_variables.vol_vv == pytest.approx( - applycoveragefactorsparam.expected_vol_vv - ) assert blanket_library.vol_shld_outboard == pytest.approx( applycoveragefactorsparam.expected_vol_shld_outboard ) diff --git a/tests/unit/test_vacuum.py b/tests/unit/test_vacuum.py index 7479f5cafd..b517d14cf5 100644 --- a/tests/unit/test_vacuum.py +++ b/tests/unit/test_vacuum.py @@ -1,10 +1,12 @@ +from typing import Any, NamedTuple + import pytest from process.data_structure import physics_variables as pv from process.data_structure import tfcoil_variables as tfv from process.data_structure import times_variables as tv from process.data_structure import vacuum_variables as vacv -from process.vacuum import Vacuum +from process.vacuum import Vacuum, VacuumVessel @pytest.fixture @@ -17,6 +19,16 @@ def vacuum(): return Vacuum() +@pytest.fixture +def vacuum_vessel(): + """Provides Vacuum object for testing. + + :return vacuum: initialised Vacuum object + :type vacuum: process.vacuum.Vacuum + """ + return VacuumVessel() + + class TestVacuum: def test_simple_model(self, monkeypatch, vacuum): """Tests `vacuum_simple` subroutine. @@ -109,3 +121,69 @@ def test_old_model(self, monkeypatch, vacuum): assert dlscalc == pytest.approx(2.798765707267961) assert mvdsh == 0.0 assert dimax == pytest.approx(0.42414752916950604) + + +class EllipticalVesselVolumes(NamedTuple): + rmajor: Any = None + rminor: Any = None + triang: Any = None + rsldi: Any = None + rsldo: Any = None + dz_vv_half: Any = None + dr_vv_inboard: Any = None + dr_vv_outboard: Any = None + dz_vv_upper: Any = None + dz_vv_lower: Any = None + + +@pytest.mark.parametrize( + "elliptical_vessel_volumes, expected", + [ + ( + EllipticalVesselVolumes( + rmajor=8, + rminor=2.6666666666666665, + triang=0.5, + rsldi=4.083333333333334, + rsldo=12.716666666666667, + dz_vv_half=7.5032752487304135, + dr_vv_inboard=0.30000000000000004, + dr_vv_outboard=0.30000000000000004, + dz_vv_upper=0.30000000000000004, + dz_vv_lower=0.30000000000000004, + ), + ( + pytest.approx(143.03162449152501), + pytest.approx(441.04172325889158), + pytest.approx(584.07334775041659), + ), + ) + ], +) +def test_elliptical_vessel_volumes(vacuum_vessel, elliptical_vessel_volumes, expected): + """Tests `elliptical_vessel_volumes` function. + + :param elliptical_vessel_volumes: input parameters for the function + :type elliptical_vessel_volumes: EllipticalVesselVolumes + + + """ + + vol_vv_inboard, vol_vv_outboard, vol_vv = ( + vacuum_vessel.calculate_elliptical_vessel_volumes( + rmajor=elliptical_vessel_volumes.rmajor, + rminor=elliptical_vessel_volumes.rminor, + triang=elliptical_vessel_volumes.triang, + rsldi=elliptical_vessel_volumes.rsldi, + rsldo=elliptical_vessel_volumes.rsldo, + dz_vv_half=elliptical_vessel_volumes.dz_vv_half, + dr_vv_inboard=elliptical_vessel_volumes.dr_vv_inboard, + dr_vv_outboard=elliptical_vessel_volumes.dr_vv_outboard, + dz_vv_upper=elliptical_vessel_volumes.dz_vv_upper, + dz_vv_lower=elliptical_vessel_volumes.dz_vv_lower, + ) + ) + + assert vol_vv_inboard == expected[0] + assert vol_vv_outboard == expected[1] + assert vol_vv == expected[2] From 4dfb4a2a288b1e843562f9611b677670c2d35724 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 20 Jan 2026 11:42:01 +0000 Subject: [PATCH 06/35] Add tests for DShaped vessel volume calculations in vacuum module --- process/hcpb.py | 8 ++--- process/vacuum.py | 3 +- tests/unit/test_blanket_library.py | 55 +---------------------------- tests/unit/test_vacuum.py | 56 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 59 deletions(-) diff --git a/process/hcpb.py b/process/hcpb.py index 6b96e6cd6e..288beb7a51 100644 --- a/process/hcpb.py +++ b/process/hcpb.py @@ -474,10 +474,10 @@ def nuclear_heating_magnets(self, output: bool): if build_variables.dr_vv_outboard > d_vv_all: d_vv_all = build_variables.dr_vv_outboard - # if d_vv_all > 1.0e-6: - # ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv - # else: - # ccfe_hcpb_module.vv_density = 0.0 + if d_vv_all > 1.0e-6: + ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv + else: + ccfe_hcpb_module.vv_density = 0.0 # Calculation of average blanket/shield thickness [m] if physics_variables.itart == 1: diff --git a/process/vacuum.py b/process/vacuum.py index 7b2dbed13d..321526eb4e 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -782,7 +782,8 @@ def calculate_vessel_half_height( + dr_fw_inboard + dr_fw_outboard ) - z_top = z_top + dz_blkt_upper + dz_shld_upper + + z_top = z_top + dz_blkt_upper + dz_shld_upper # Average of top and bottom (m) return 0.5 * (z_top + z_bottom) diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index 6d4a71ef9f..f2c95f5617 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -647,7 +647,7 @@ class DshapedComponentParam(NamedTuple): dz_blkt_half=8.25, dz_shld_half=8.75, dz_vv_half=9.4349999999999987, - icomponent=0, + icomponent=1, expected_a_blkt_inboard_surface=196.97785938008002, expected_a_blkt_outboard_surface=852.24160940262459, expected_a_blkt_total_surface=1049.2194687827046, @@ -664,59 +664,6 @@ class DshapedComponentParam(NamedTuple): expected_vol_vv_outboard=0, expected_icomponent=1, ), - DshapedComponentParam( - r_shld_inboard_inner=1.5, - dr_shld_inboard=0.40000000000000002, - dr_blkt_inboard=0, - dr_fw_inboard=0.018000000000000002, - dr_fw_plasma_gap_inboard=0.10000000000000001, - dr_fw_plasma_gap_outboard=0.10000000000000001, - dr_fw_outboard=0.018000000000000002, - a_blkt_inboard_surface=196.97785938008002, - a_blkt_outboard_surface=852.24160940262459, - a_blkt_total_surface=1049.2194687827046, - dr_blkt_outboard=1, - dz_blkt_upper=0.5, - a_shld_inboard_surface=208.91591146372122, - a_shld_outboard_surface=1013.8483589087293, - a_shld_total_surface=1222.7642703724505, - dr_shld_outboard=0.30000000000000004, - dz_shld_upper=0.60000000000000009, - r_shld_outboard_outer=8.4000000000000004, - dr_vv_inboard=0.20000000000000001, - dr_vv_outboard=0.30000000000000004, - dz_vv_upper=0.30000000000000004, - dz_vv_lower=0.30000000000000004, - vol_blkt_inboard=0, - vol_blkt_outboard=691.06561956756764, - vol_blkt_total=691.06561956756764, - vol_shld_total=450.46122947809488, - vol_vv=0, - rminor=2.5, - vol_shld_inboard=79.896984366095609, - vol_shld_outboard=370.5642451119993, - vol_vv_inboard=0, - vol_vv_outboard=0, - dz_blkt_half=8.25, - dz_shld_half=8.75, - dz_vv_half=9.4349999999999987, - icomponent=1, - expected_a_blkt_inboard_surface=196.97785938008002, - expected_a_blkt_outboard_surface=852.24160940262459, - expected_a_blkt_total_surface=1049.2194687827046, - expected_a_shld_inboard_surface=208.91591146372122, - expected_a_shld_outboard_surface=1013.8483589087293, - expected_a_shld_total_surface=1222.7642703724505, - expected_vol_blkt_outboard=691.06561956756764, - expected_volblkt=691.06561956756764, - expected_vol_shld_total=450.46122947809488, - expected_vol_vv=340.45369594344834, - expected_vol_shld_inboard=79.896984366095609, - expected_vol_shld_outboard=370.5642451119993, - expected_vol_vv_inboard=34.253413020620215, - expected_vol_vv_outboard=306.20028292282814, - expected_icomponent=2, - ), ), ) def test_dshaped_component(dshapedcomponentparam, monkeypatch, blanket_library_fixture): diff --git a/tests/unit/test_vacuum.py b/tests/unit/test_vacuum.py index b517d14cf5..d0c7bef2ca 100644 --- a/tests/unit/test_vacuum.py +++ b/tests/unit/test_vacuum.py @@ -187,3 +187,59 @@ def test_elliptical_vessel_volumes(vacuum_vessel, elliptical_vessel_volumes, exp assert vol_vv_inboard == expected[0] assert vol_vv_outboard == expected[1] assert vol_vv == expected[2] + + +class DShapedVesselVolumes(NamedTuple): + rsldi: Any = None + rsldo: Any = None + dz_vv_half: Any = None + dr_vv_inboard: Any = None + dr_vv_outboard: Any = None + dz_vv_upper: Any = None + dz_vv_lower: Any = None + + +@pytest.mark.parametrize( + "dshaped_vessel_volumes, expected", + [ + ( + DShapedVesselVolumes( + rsldi=1.5, + rsldo=8.4000000000000004, + dz_vv_half=9.4349999999999987, + dr_vv_inboard=0.20000000000000001, + dr_vv_outboard=0.30000000000000004, + dz_vv_upper=0.30000000000000004, + dz_vv_lower=0.30000000000000004, + ), + ( + pytest.approx(34.253413020620215), + pytest.approx(306.20028292282814), + pytest.approx(340.45369594344834), + ), + ) + ], +) +def test_dshaped_vessel_volumes(vacuum_vessel, dshaped_vessel_volumes, expected): + """Tests `dshaped_vessel_volumes` function. + + :param dshaped_vessel_volumes: input parameters for the function + :type dshaped_vessel_volumes: DShapedVesselVolumes + + """ + + vol_vv_inboard, vol_vv_outboard, vol_vv = ( + vacuum_vessel.calculate_dshaped_vessel_volumes( + rsldi=dshaped_vessel_volumes.rsldi, + rsldo=dshaped_vessel_volumes.rsldo, + dz_vv_half=dshaped_vessel_volumes.dz_vv_half, + dr_vv_inboard=dshaped_vessel_volumes.dr_vv_inboard, + dr_vv_outboard=dshaped_vessel_volumes.dr_vv_outboard, + dz_vv_upper=dshaped_vessel_volumes.dz_vv_upper, + dz_vv_lower=dshaped_vessel_volumes.dz_vv_lower, + ) + ) + + assert vol_vv_inboard == expected[0] + assert vol_vv_outboard == expected[1] + assert vol_vv == expected[2] From 3252aeb27c26f3a32a08ec6503affa49417f4e9d Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 11:42:01 +0000 Subject: [PATCH 07/35] Add Shield class with calculate_shield_half_height method --- process/shield.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 process/shield.py diff --git a/process/shield.py b/process/shield.py new file mode 100644 index 0000000000..7c74634eca --- /dev/null +++ b/process/shield.py @@ -0,0 +1,45 @@ +import logging + +logger = logging.getLogger(__name__) + + +class Shield: + def __init__(self) -> None: + pass + + def run(self) -> None: + pass + + @staticmethod + def calculate_shield_half_height( + z_plasma_xpoint_lower: float, + dz_xpoint_divertor: float, + dz_divertor: float, + n_divertors: int, + z_plasma_xpoint_upper: float, + dr_fw_plasma_gap_inboard: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_inboard: float, + dr_fw_outboard: float, + dz_blkt_upper: float, + ) -> float: + """Calculate shield half-height.""" + + z_bottom = z_plasma_xpoint_lower + dz_xpoint_divertor + dz_divertor + + # Calculate component internal upper half-height (m) + # If a double null machine then symmetric + if n_divertors == 2: + z_top = z_bottom + else: + z_top = z_plasma_xpoint_upper + 0.5 * ( + dr_fw_plasma_gap_inboard + + dr_fw_plasma_gap_outboard + + dr_fw_inboard + + dr_fw_outboard + ) + + z_top = z_top + dz_blkt_upper + + # Average of top and bottom (m) + return 0.5 * (z_top + z_bottom) From c56de6c0233b244785396a2cc249cf5a4ca032eb Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 11:58:36 +0000 Subject: [PATCH 08/35] Add calculate_dshaped_shield_volumes method to Shield class --- process/shield.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/process/shield.py b/process/shield.py index 7c74634eca..77e49bbc9b 100644 --- a/process/shield.py +++ b/process/shield.py @@ -1,5 +1,7 @@ import logging +from process.blanket_library import dshellvol + logger = logging.getLogger(__name__) @@ -43,3 +45,46 @@ def calculate_shield_half_height( # Average of top and bottom (m) return 0.5 * (z_top + z_bottom) + + @staticmethod + def calculate_dshaped_shield_volumes( + rsldi: float, + dr_shld_inboard: float, + dr_fw_inboard: float, + dr_fw_plasma_gap_inboard: float, + rminor: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_outboard: float, + dr_blkt_inboard: float, + dr_blkt_outboard: float, + dz_shld_half: float, + dr_shld_outboard: float, + dz_shld_upper: float, + ) -> tuple[float, float, float]: + """Calculate volumes of D-shaped shield segments.""" + + r_1 = rsldi + dr_shld_inboard + r_2 = ( + dr_fw_inboard + + dr_fw_plasma_gap_inboard + + 2.0 * rminor + + dr_fw_plasma_gap_outboard + + dr_fw_outboard + ) + + r_2 = dr_blkt_inboard + r_2 + dr_blkt_outboard + + ( + vol_shld_inboard, + vol_shld_outboard, + vol_shld_total, + ) = dshellvol( + rmajor=r_1, + rminor=r_2, + zminor=dz_shld_half, + drin=dr_shld_inboard, + drout=dr_shld_outboard, + dz=dz_shld_upper, + ) + + return vol_shld_inboard, vol_shld_outboard, vol_shld_total From 06496a56ebae9c4fc38c67bc413a23322827666e Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 13:14:11 +0000 Subject: [PATCH 09/35] Add calculate_dshaped_shield_areas method to Shield class --- process/shield.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/process/shield.py b/process/shield.py index 77e49bbc9b..593b2ce131 100644 --- a/process/shield.py +++ b/process/shield.py @@ -1,6 +1,6 @@ import logging -from process.blanket_library import dshellvol +from process.blanket_library import dshellarea, dshellvol logger = logging.getLogger(__name__) @@ -88,3 +88,37 @@ def calculate_dshaped_shield_volumes( ) return vol_shld_inboard, vol_shld_outboard, vol_shld_total + + @staticmethod + def calculate_dshaped_shield_areas( + rsldi: float, + dr_shld_inboard: float, + dr_fw_inboard: float, + dr_fw_plasma_gap_inboard: float, + rminor: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_outboard: float, + dr_blkt_inboard: float, + dr_blkt_outboard: float, + dz_shld_half: float, + ) -> tuple[float, float, float]: + """Calculate areas of D-shaped shield segments.""" + + r_1 = rsldi + dr_shld_inboard + r_2 = ( + dr_fw_inboard + + dr_fw_plasma_gap_inboard + + 2.0 * rminor + + dr_fw_plasma_gap_outboard + + dr_fw_outboard + ) + + r_2 = dr_blkt_inboard + r_2 + dr_blkt_outboard + + ( + a_shld_inboard_surface, + a_shld_outboard_surface, + a_shld_total_surface, + ) = dshellarea(rmajor=r_1, rminor=r_2, zminor=dz_shld_half) + + return a_shld_inboard_surface, a_shld_outboard_surface, a_shld_total_surface From 64e913d9d21dba4ad46a44d0633edb071f54596a Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 13:19:01 +0000 Subject: [PATCH 10/35] Add calculate_elliptical_shield_volumes method to Shield class --- process/shield.py | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/process/shield.py b/process/shield.py index 593b2ce131..4f3bffee90 100644 --- a/process/shield.py +++ b/process/shield.py @@ -1,6 +1,6 @@ import logging -from process.blanket_library import dshellarea, dshellvol +from process.blanket_library import dshellarea, dshellvol, eshellvol logger = logging.getLogger(__name__) @@ -122,3 +122,43 @@ def calculate_dshaped_shield_areas( ) = dshellarea(rmajor=r_1, rminor=r_2, zminor=dz_shld_half) return a_shld_inboard_surface, a_shld_outboard_surface, a_shld_total_surface + + @staticmethod + def calculate_elliptical_shield_volumes( + rsldi: float, + rsldo: float, + rmajor: float, + triang: float, + dr_shld_inboard: float, + rminor: float, + dz_shld_half: float, + dr_shld_outboard: float, + dz_shld_upper: float, + ) -> tuple[float, float, float]: + """Calculate volumes of elliptical shield segments.""" + + # Major radius to centre of inboard and outboard ellipses (m) + # (coincident in radius with top of plasma) + r_1 = rmajor - rminor * triang + r_2 = r_1 - rsldi + + r_2 = r_2 - dr_shld_inboard + + r_3 = rsldo - r_1 + r_3 = r_3 - dr_shld_outboard + + ( + vol_shld_inboard, + vol_shld_outboard, + vol_shld_total, + ) = eshellvol( + rshell=r_1, + rmini=r_2, + rmino=r_3, + zminor=dz_shld_half, + drin=dr_shld_inboard, + drout=dr_shld_outboard, + dz=dz_shld_upper, + ) + + return vol_shld_inboard, vol_shld_outboard, vol_shld_total From dcfe308fc15be0ffedeee90a537062e70a652303 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 13:23:06 +0000 Subject: [PATCH 11/35] Add calculate_elliptical_shield_areas method to Shield class --- process/hcpb.py | 5 ----- process/shield.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/process/hcpb.py b/process/hcpb.py index 288beb7a51..a238e1405f 100644 --- a/process/hcpb.py +++ b/process/hcpb.py @@ -474,11 +474,6 @@ def nuclear_heating_magnets(self, output: bool): if build_variables.dr_vv_outboard > d_vv_all: d_vv_all = build_variables.dr_vv_outboard - if d_vv_all > 1.0e-6: - ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv - else: - ccfe_hcpb_module.vv_density = 0.0 - # Calculation of average blanket/shield thickness [m] if physics_variables.itart == 1: # There is no inner blanket for TART design [m] diff --git a/process/shield.py b/process/shield.py index 4f3bffee90..6905adf7d8 100644 --- a/process/shield.py +++ b/process/shield.py @@ -1,6 +1,6 @@ import logging -from process.blanket_library import dshellarea, dshellvol, eshellvol +from process.blanket_library import dshellarea, dshellvol, eshellarea, eshellvol logger = logging.getLogger(__name__) @@ -162,3 +162,34 @@ def calculate_elliptical_shield_volumes( ) return vol_shld_inboard, vol_shld_outboard, vol_shld_total + + @staticmethod + def calculate_elliptical_shield_areas( + rsldi: float, + rsldo: float, + rmajor: float, + triang: float, + dr_shld_inboard: float, + rminor: float, + dz_shld_half: float, + dr_shld_outboard: float, + ) -> tuple[float, float, float]: + """Calculate areas of elliptical shield segments.""" + + # Major radius to centre of inboard and outboard ellipses (m) + # (coincident in radius with top of plasma) + r_1 = rmajor - rminor * triang + r_2 = r_1 - rsldi + + r_2 = r_2 - dr_shld_inboard + + r_3 = rsldo - r_1 + r_3 = r_3 - dr_shld_outboard + + ( + a_shld_inboard_surface, + a_shld_outboard_surface, + a_shld_total_surface, + ) = eshellarea(rshell=r_1, rmini=r_2, rmino=r_3, zminor=dz_shld_half) + + return a_shld_inboard_surface, a_shld_outboard_surface, a_shld_total_surface From 9ec634c253aaad620aa90b626aa6cb25c461077d Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 13:41:29 +0000 Subject: [PATCH 12/35] Add Shield model integration to Caller and Models classes --- process/caller.py | 1 + process/main.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/process/caller.py b/process/caller.py index 8cd74fefc8..29682d85ce 100644 --- a/process/caller.py +++ b/process/caller.py @@ -296,6 +296,7 @@ def _call_models_once(self, xc: np.ndarray) -> None: # DCLL model self.models.dcll.run(output=False) + self.models.shield.run() self.models.vacuum_vessel.run() self.models.divertor.run(output=False) diff --git a/process/main.py b/process/main.py index 6a8ab9b678..9dc607dfb6 100644 --- a/process/main.py +++ b/process/main.py @@ -101,6 +101,7 @@ from process.pulse import Pulse from process.resistive_tf_coil import AluminiumTFCoil, CopperTFCoil, ResistiveTFCoil from process.scan import Scan +from process.shield import Shield from process.stellarator import Neoclassics, Stellarator from process.structure import Structure from process.superconducting_tf_coil import SuperconductingTFCoil @@ -667,6 +668,7 @@ def __init__(self): self.vacuum_vessel = VacuumVessel() self.water_use = WaterUse() self.pulse = Pulse() + self.shield = Shield() self.ife = IFE(availability=self.availability, costs=self.costs) self.plasma_profile = PlasmaProfile() self.fw = Fw() From fae93af0ec2bb55799aa2b21fa9905e8515cca20 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 13:56:46 +0000 Subject: [PATCH 13/35] Implement shield area and volume calculations in run method of Shield class --- process/shield.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/process/shield.py b/process/shield.py index 6905adf7d8..73a263c303 100644 --- a/process/shield.py +++ b/process/shield.py @@ -1,6 +1,12 @@ import logging from process.blanket_library import dshellarea, dshellvol, eshellarea, eshellvol +from process.data_structure import blanket_library as blanket_library +from process.data_structure import build_variables as build_variables +from process.data_structure import ccfe_hcpb_module as ccfe_hcpb_module +from process.data_structure import divertor_variables as divertor_variables +from process.data_structure import fwbs_variables as fwbs_variables +from process.data_structure import physics_variables as physics_variables logger = logging.getLogger(__name__) @@ -10,7 +16,87 @@ def __init__(self) -> None: pass def run(self) -> None: - pass + blanket_library.dz_shld_half = self.calculate_shield_half_height( + z_plasma_xpoint_lower=build_variables.z_plasma_xpoint_lower, + dz_xpoint_divertor=build_variables.dz_xpoint_divertor, + dz_divertor=divertor_variables.dz_divertor, + n_divertors=physics_variables.n_divertors, + z_plasma_xpoint_upper=build_variables.z_plasma_xpoint_upper, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + dz_blkt_upper=build_variables.dz_blkt_upper, + ) + # D-shaped blanket and shield + if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: + ( + blanket_library.a_shld_inboard_surface, + blanket_library.a_shld_outboard_surface, + blanket_library.a_shld_total_surface, + ) = self.calculate_dshaped_shield_areas( + rsldi=build_variables.rsldi, + dr_shld_inboard=build_variables.dr_shld_inboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + rminor=physics_variables.rminor, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + dr_blkt_inboard=build_variables.dr_blkt_inboard, + dr_blkt_outboard=build_variables.dr_blkt_outboard, + dz_shld_half=blanket_library.dz_shld_half, + ) + + ( + blanket_library.vol_shld_inboard, + blanket_library.vol_shld_outboard, + blanket_library.vol_shld_total, + ) = self.calculate_dshaped_shield_volumes( + rsldi=build_variables.rsldi, + dr_shld_inboard=build_variables.dr_shld_inboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + rminor=physics_variables.rminor, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + dr_blkt_inboard=build_variables.dr_blkt_inboard, + dr_blkt_outboard=build_variables.dr_blkt_outboard, + dz_shld_half=blanket_library.dz_shld_half, + dr_shld_outboard=build_variables.dr_shld_outboard, + dz_shld_upper=build_variables.dz_shld_upper, + ) + + else: + ( + build_variables.a_shld_inboard_surface, + build_variables.a_shld_outboard_surface, + build_variables.a_shld_total_surface, + ) = self.calculate_elliptical_shield_areas( + rsldi=build_variables.rsldi, + rsldo=build_variables.rsldo, + rmajor=physics_variables.rmajor, + triang=physics_variables.triang, + dr_shld_inboard=build_variables.dr_shld_inboard, + rminor=physics_variables.rminor, + dz_shld_half=blanket_library.dz_shld_half, + dr_shld_outboard=build_variables.dr_shld_outboard, + ) + + ( + build_variables.vol_shld_inboard, + build_variables.vol_shld_outboard, + build_variables.vol_shld_total, + ) = self.calculate_elliptical_shield_volumes( + rsldi=build_variables.rsldi, + rsldo=build_variables.rsldo, + rmajor=physics_variables.rmajor, + triang=physics_variables.triang, + dr_shld_inboard=build_variables.dr_shld_inboard, + rminor=physics_variables.rminor, + dz_shld_half=blanket_library.dz_shld_half, + dr_shld_outboard=build_variables.dr_shld_outboard, + dz_shld_upper=build_variables.dz_shld_upper, + ) @staticmethod def calculate_shield_half_height( From d434e7b4cb5051813458d537d601b36f5ac343fa Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 14:13:52 +0000 Subject: [PATCH 14/35] Refactor BlanketLibrary to remove shield component calculations and streamline component handling --- process/blanket_library.py | 84 ++++++-------------------------------- 1 file changed, 13 insertions(+), 71 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index 5dea134350..e87791e4eb 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -55,17 +55,15 @@ def component_volumes(self): # Calculate half-height # Blanket blanket_library.dz_blkt_half = self.component_half_height(icomponent=0) - # Shield - blanket_library.dz_shld_half = self.component_half_height(icomponent=1) # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: - for icomponent in range(2): + for icomponent in range(1): self.dshaped_component(icomponent) # Elliptical blanket and shield else: - for icomponent in range(2): + for icomponent in range(1): self.elliptical_component(icomponent) # Apply coverage factors to volumes and surface areas @@ -86,15 +84,10 @@ def component_half_height(self, icomponent: int): + divertor_variables.dz_divertor - build_variables.dz_blkt_upper ) - # Sheild - elif icomponent == 1: - hbot = ( - build_variables.z_plasma_xpoint_lower - + build_variables.dz_xpoint_divertor - + divertor_variables.dz_divertor - ) else: - raise ProcessValueError(f"{icomponent=} is invalid, it must be either 0,1") + raise ProcessValueError( + f"{icomponent=} is invalid, it must be 0 for blanket." + ) # Calculate component internal upper half-height (m) # If a double null machine then symmetric @@ -108,9 +101,6 @@ def component_half_height(self, icomponent: int): + build_variables.dr_fw_inboard + build_variables.dr_fw_outboard ) - # Shield - if icomponent == 1: - htop = htop + build_variables.dz_blkt_upper # Average of top and bottom (m) return 0.5 * (htop + hbot) @@ -123,13 +113,11 @@ def dshaped_component(self, icomponent: int): """ # Calculate major radius to outer edge of inboard ... # ... section (m) - r1 = build_variables.r_shld_inboard_inner - # ... shield (m) - if icomponent == 1: - r1 = r1 + build_variables.dr_shld_inboard + r1 = build_variables.rsldi + # ... blanket (m) - elif icomponent == 0: - r1 = r1 + build_variables.dr_shld_inboard + build_variables.dr_blkt_inboard + + r1 = r1 + build_variables.dr_shld_inboard + build_variables.dr_blkt_inboard # Horizontal distance between inside edges (m) # i.e. outer radius of inboard part to inner radius of outboard part @@ -141,9 +129,6 @@ def dshaped_component(self, icomponent: int): + build_variables.dr_fw_plasma_gap_outboard + build_variables.dr_fw_outboard ) - # Sheild - if icomponent == 1: - r2 = build_variables.dr_blkt_inboard + r2 + build_variables.dr_blkt_outboard # Calculate surface area, assuming 100% coverage if icomponent == 0: @@ -152,12 +137,6 @@ def dshaped_component(self, icomponent: int): build_variables.a_blkt_outboard_surface, build_variables.a_blkt_total_surface, ) = dshellarea(r1, r2, blanket_library.dz_blkt_half) - if icomponent == 1: - ( - build_variables.a_shld_inboard_surface, - build_variables.a_shld_outboard_surface, - build_variables.a_shld_total_surface, - ) = dshellarea(r1, r2, blanket_library.dz_shld_half) # Calculate volumes, assuming 100% coverage if icomponent == 0: @@ -173,19 +152,6 @@ def dshaped_component(self, icomponent: int): build_variables.dr_blkt_outboard, build_variables.dz_blkt_upper, ) - elif icomponent == 1: - ( - blanket_library.vol_shld_inboard, - blanket_library.vol_shld_outboard, - fwbs_variables.vol_shld_total, - ) = dshellvol( - r1, - r2, - blanket_library.dz_shld_half, - build_variables.dr_shld_inboard, - build_variables.dr_shld_outboard, - build_variables.dz_shld_upper, - ) def elliptical_component(self, icomponent: int): """Calculate component surface area and volume using elliptical scheme @@ -202,20 +168,16 @@ def elliptical_component(self, icomponent: int): # Calculate distance between r1 and outer edge of inboard ... # ... section (m) - r2 = r1 - build_variables.r_shld_inboard_inner - # ... shield (m) - if icomponent == 1: - r2 = r2 - build_variables.dr_shld_inboard + r2 = r1 - build_variables.rsldi + # ... blanket (m) if icomponent == 0: r2 = r2 - build_variables.dr_shld_inboard - build_variables.dr_blkt_inboard # Calculate distance between r1 and inner edge of outboard ... # ... section (m) - r3 = build_variables.r_shld_outboard_outer - r1 - # ... shield (m) - if icomponent == 1: - r3 = r3 - build_variables.dr_shld_outboard + r3 = build_variables.rsldo - r1 + # ... blanket (m) if icomponent == 0: r3 = r3 - build_variables.dr_shld_outboard - build_variables.dr_blkt_outboard @@ -227,12 +189,6 @@ def elliptical_component(self, icomponent: int): build_variables.a_blkt_outboard_surface, build_variables.a_blkt_total_surface, ) = eshellarea(r1, r2, r3, blanket_library.dz_blkt_half) - if icomponent == 1: - ( - build_variables.a_shld_inboard_surface, - build_variables.a_shld_outboard_surface, - build_variables.a_shld_total_surface, - ) = eshellarea(r1, r2, r3, blanket_library.dz_shld_half) # Calculate volumes, assuming 100% coverage if icomponent == 0: @@ -249,20 +205,6 @@ def elliptical_component(self, icomponent: int): build_variables.dr_blkt_outboard, build_variables.dz_blkt_upper, ) - if icomponent == 1: - ( - blanket_library.vol_shld_inboard, - blanket_library.vol_shld_outboard, - fwbs_variables.vol_shld_total, - ) = eshellvol( - r1, - r2, - r3, - blanket_library.dz_shld_half, - build_variables.dr_shld_inboard, - build_variables.dr_shld_outboard, - build_variables.dz_shld_upper, - ) def apply_coverage_factors(self): """Apply coverage factors to volumes From c03473bae0ae35c81f6b0b206c1dc85dd0e2cff9 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 14:28:37 +0000 Subject: [PATCH 15/35] Add unit test for elliptical shield volumes calculation --- tests/unit/test_shield.py | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/unit/test_shield.py diff --git a/tests/unit/test_shield.py b/tests/unit/test_shield.py new file mode 100644 index 0000000000..671b2f4100 --- /dev/null +++ b/tests/unit/test_shield.py @@ -0,0 +1,80 @@ +from typing import Any, NamedTuple + +import pytest + +from process.shield import Shield + + +@pytest.fixture +def shield(): + """Provides Shield object for testing. + + :return shield: initialised Shield object + :type shield: process.shield.Shield + """ + return Shield() + + +class EllipticalShieldVolumes(NamedTuple): + rmajor: Any = None + rminor: Any = None + triang: Any = None + rsldi: Any = None + rsldo: Any = None + dz_shield_half: Any = None + dr_shield_inboard: Any = None + dr_shield_outboard: Any = None + dz_shield_upper: Any = None + dz_shield_lower: Any = None + + +@pytest.mark.parametrize( + "elliptical_shield_volumes, expected", + [ + ( + EllipticalShieldVolumes( + rmajor=8, + rminor=2.6666666666666665, + triang=0.5, + rsldi=4.083333333333334, + rsldo=12.716666666666667, + dz_shield_half=6.8032752487304133, + dr_shield_inboard=0.30000000000000004, + dr_shield_outboard=0.80000000000000004, + dz_shield_upper=0.59999999999999998, + dz_shield_lower=0.59999999999999998, + ), + ( + pytest.approx(177.89822933168091), + pytest.approx(946.56393192782434), + pytest.approx(1124.4621612595051), + ), + ) + ], +) +def test_elliptical_shield_volumes(shield, elliptical_shield_volumes, expected): + """Tests `elliptical_shield_volumes` function. + + :param elliptical_shield_volumes: input parameters for the function + :type elliptical_shield_volumes: EllipticalShieldVolumes + + + """ + + vol_shield_inboard, vol_shield_outboard, vol_shield = ( + shield.calculate_elliptical_shield_volumes( + rsldi=elliptical_shield_volumes.rsldi, + rsldo=elliptical_shield_volumes.rsldo, + rmajor=elliptical_shield_volumes.rmajor, + triang=elliptical_shield_volumes.triang, + dr_shld_inboard=elliptical_shield_volumes.dr_shield_inboard, + rminor=elliptical_shield_volumes.rminor, + dz_shld_half=elliptical_shield_volumes.dz_shield_half, + dr_shld_outboard=elliptical_shield_volumes.dr_shield_outboard, + dz_shld_upper=elliptical_shield_volumes.dz_shield_upper, + ) + ) + + assert vol_shield_inboard == expected[0] + assert vol_shield_outboard == expected[1] + assert vol_shield == expected[2] From be1dc326b1b00fd403884aa5d0ae0abda6467b41 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 14:32:36 +0000 Subject: [PATCH 16/35] Add unit test for elliptical shield areas calculation --- tests/unit/test_shield.py | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/unit/test_shield.py b/tests/unit/test_shield.py index 671b2f4100..60db195f4a 100644 --- a/tests/unit/test_shield.py +++ b/tests/unit/test_shield.py @@ -78,3 +78,65 @@ def test_elliptical_shield_volumes(shield, elliptical_shield_volumes, expected): assert vol_shield_inboard == expected[0] assert vol_shield_outboard == expected[1] assert vol_shield == expected[2] + + +class EllipticalShieldAreas(NamedTuple): + rmajor: Any = None + rminor: Any = None + triang: Any = None + rsldi: Any = None + rsldo: Any = None + dz_shield_half: Any = None + dr_shield_inboard: Any = None + dr_shield_outboard: Any = None + dz_shield_upper: Any = None + dz_shield_lower: Any = None + + +@pytest.mark.parametrize( + "elliptical_shield_areas, expected", + [ + ( + EllipticalShieldAreas( + rmajor=8, + rminor=2.6666666666666665, + triang=0.5, + rsldi=4.083333333333334, + rsldo=12.716666666666667, + dz_shield_half=6.8032752487304133, + dr_shield_inboard=0.30000000000000004, + dr_shield_outboard=0.80000000000000004, + dz_shield_upper=0.59999999999999998, + ), + ( + pytest.approx(700.06731267447844), + pytest.approx(1344.1106481995357), + pytest.approx(2044.1779608740142), + ), + ) + ], +) +def test_elliptical_shield_areas(shield, elliptical_shield_areas, expected): + """Tests `elliptical_shield_areas` function. + :param elliptical_shield_areas: input parameters for the function + :type elliptical_shield_areas: EllipticalShieldAreas + + + """ + + a_shield_inboard, a_shield_outboard, a_shield = ( + shield.calculate_elliptical_shield_areas( + rsldi=elliptical_shield_areas.rsldi, + rsldo=elliptical_shield_areas.rsldo, + rmajor=elliptical_shield_areas.rmajor, + triang=elliptical_shield_areas.triang, + dr_shld_inboard=elliptical_shield_areas.dr_shield_inboard, + rminor=elliptical_shield_areas.rminor, + dz_shld_half=elliptical_shield_areas.dz_shield_half, + dr_shld_outboard=elliptical_shield_areas.dr_shield_outboard, + ) + ) + + assert a_shield_inboard == expected[0] + assert a_shield_outboard == expected[1] + assert a_shield == expected[2] From 297673025a6cdb25e96dfee27756a828402960a9 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 14:47:16 +0000 Subject: [PATCH 17/35] Add unit test for D-shaped shield volumes calculation --- tests/unit/test_shield.py | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/unit/test_shield.py b/tests/unit/test_shield.py index 60db195f4a..c7614a144c 100644 --- a/tests/unit/test_shield.py +++ b/tests/unit/test_shield.py @@ -140,3 +140,75 @@ def test_elliptical_shield_areas(shield, elliptical_shield_areas, expected): assert a_shield_inboard == expected[0] assert a_shield_outboard == expected[1] assert a_shield == expected[2] + + +class DShapedShieldVolumes(NamedTuple): + rminor: Any = None + rsldi: Any = None + dr_shld_inboard: Any = None + dr_fw_plasma_gap_inboard: Any = None + dr_fw_plasma_gap_outboard: Any = None + dr_fw_inboard: Any = None + dr_fw_outboard: Any = None + dr_blkt_inboard: Any = None + dr_blkt_outboard: Any = None + dz_shld_half: Any = None + dr_shld_outboard: Any = None + dz_shld_upper: Any = None + + +@pytest.mark.parametrize( + "dshaped_shield_volumes, expected", + [ + ( + DShapedShieldVolumes( + rminor=2.5, + dr_shld_inboard=0.40000000000000002, + rsldi=1.5, + dr_fw_plasma_gap_inboard=0.10000000000000001, + dr_fw_plasma_gap_outboard=0.10000000000000001, + dr_fw_inboard=0.018000000000000002, + dr_fw_outboard=0.018000000000000002, + dr_blkt_inboard=0.0, + dr_blkt_outboard=1.0, + dz_shld_half=8.75, + dr_shld_outboard=0.30000000000000004, + dz_shld_upper=0.6000000000000009, + ), + ( + pytest.approx(79.896984366095609), + pytest.approx(370.5642451119993), + pytest.approx(450.46122947809488), + ), + ) + ], +) +def test_dshaped_shield_volumes(shield, dshaped_shield_volumes, expected): + """Tests `dshaped_shield_volumes` function. + + :param dshaped_shield_volumes: input parameters for the function + :type dshaped_shield_volumes: DShapedShieldVolumes + + + """ + + vol_shield_inboard, vol_shield_outboard, vol_shield = ( + shield.calculate_dshaped_shield_volumes( + rsldi=dshaped_shield_volumes.rsldi, + dr_shld_inboard=dshaped_shield_volumes.dr_shld_inboard, + dr_fw_inboard=dshaped_shield_volumes.dr_fw_inboard, + dr_fw_plasma_gap_inboard=dshaped_shield_volumes.dr_fw_plasma_gap_inboard, + rminor=dshaped_shield_volumes.rminor, + dr_fw_plasma_gap_outboard=dshaped_shield_volumes.dr_fw_plasma_gap_outboard, + dr_fw_outboard=dshaped_shield_volumes.dr_fw_outboard, + dr_blkt_inboard=dshaped_shield_volumes.dr_blkt_inboard, + dr_blkt_outboard=dshaped_shield_volumes.dr_blkt_outboard, + dz_shld_half=dshaped_shield_volumes.dz_shld_half, + dr_shld_outboard=dshaped_shield_volumes.dr_shld_outboard, + dz_shld_upper=dshaped_shield_volumes.dz_shld_upper, + ) + ) + + assert vol_shield_inboard == expected[0] + assert vol_shield_outboard == expected[1] + assert vol_shield == expected[2] From e31d32ae39961d8113dfa3d8e5ab9f569ec948b2 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 15:14:22 +0000 Subject: [PATCH 18/35] Add unit test for D-shaped shield areas calculation --- tests/unit/test_shield.py | 66 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/unit/test_shield.py b/tests/unit/test_shield.py index c7614a144c..18d9717984 100644 --- a/tests/unit/test_shield.py +++ b/tests/unit/test_shield.py @@ -212,3 +212,69 @@ def test_dshaped_shield_volumes(shield, dshaped_shield_volumes, expected): assert vol_shield_inboard == expected[0] assert vol_shield_outboard == expected[1] assert vol_shield == expected[2] + + +class DShapedShieldAreas(NamedTuple): + rminor: Any = None + rsldi: Any = None + dr_shld_inboard: Any = None + dr_fw_plasma_gap_inboard: Any = None + dr_fw_plasma_gap_outboard: Any = None + dr_fw_inboard: Any = None + dr_fw_outboard: Any = None + dr_blkt_inboard: Any = None + dr_blkt_outboard: Any = None + dz_shld_half: Any = None + + +@pytest.mark.parametrize( + "dshaped_shield_areas, expected", + [ + ( + DShapedShieldAreas( + rminor=2.5, + dr_shld_inboard=0.40000000000000002, + rsldi=1.5, + dr_fw_plasma_gap_inboard=0.10000000000000001, + dr_fw_plasma_gap_outboard=0.10000000000000001, + dr_fw_inboard=0.018000000000000002, + dr_fw_outboard=0.018000000000000002, + dr_blkt_inboard=0.0, + dr_blkt_outboard=1.0, + dz_shld_half=8.75, + ), + ( + pytest.approx(208.91591146372122), + pytest.approx(1013.8483589087293), + pytest.approx(1222.7642703724505), + ), + ) + ], +) +def test_dshaped_shield_areas(shield, dshaped_shield_areas, expected): + """Tests `dshaped_shield_areas` function. + + :param dshaped_shield_areas: input parameters for the function + :type dshaped_shield_areas: DShapedShieldAreas + + + """ + + a_shield_inboard, a_shield_outboard, a_shield = ( + shield.calculate_dshaped_shield_areas( + rsldi=dshaped_shield_areas.rsldi, + dr_shld_inboard=dshaped_shield_areas.dr_shld_inboard, + dr_fw_inboard=dshaped_shield_areas.dr_fw_inboard, + dr_fw_plasma_gap_inboard=dshaped_shield_areas.dr_fw_plasma_gap_inboard, + rminor=dshaped_shield_areas.rminor, + dr_fw_plasma_gap_outboard=dshaped_shield_areas.dr_fw_plasma_gap_outboard, + dr_fw_outboard=dshaped_shield_areas.dr_fw_outboard, + dr_blkt_inboard=dshaped_shield_areas.dr_blkt_inboard, + dr_blkt_outboard=dshaped_shield_areas.dr_blkt_outboard, + dz_shld_half=dshaped_shield_areas.dz_shld_half, + ) + ) + + assert a_shield_inboard == expected[0] + assert a_shield_outboard == expected[1] + assert a_shield == expected[2] From 9c4b508ee8eedf83f72bf39801811816a8c227d4 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 15:14:58 +0000 Subject: [PATCH 19/35] Remove redundant D-shaped component parameters from test cases --- tests/unit/test_blanket_library.py | 53 ------------------------------ 1 file changed, 53 deletions(-) diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index f2c95f5617..b6f9130d70 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -611,59 +611,6 @@ class DshapedComponentParam(NamedTuple): expected_vol_vv_outboard=0, expected_icomponent=0, ), - DshapedComponentParam( - r_shld_inboard_inner=1.5, - dr_shld_inboard=0.40000000000000002, - dr_blkt_inboard=0, - dr_fw_inboard=0.018000000000000002, - dr_fw_plasma_gap_inboard=0.10000000000000001, - dr_fw_plasma_gap_outboard=0.10000000000000001, - dr_fw_outboard=0.018000000000000002, - a_blkt_inboard_surface=196.97785938008002, - a_blkt_outboard_surface=852.24160940262459, - a_blkt_total_surface=1049.2194687827046, - dr_blkt_outboard=1, - dz_blkt_upper=0.5, - a_shld_inboard_surface=0, - a_shld_outboard_surface=0, - a_shld_total_surface=0, - dr_shld_outboard=0.30000000000000004, - dz_shld_upper=0.60000000000000009, - r_shld_outboard_outer=8.4000000000000004, - dr_vv_inboard=0.20000000000000001, - dr_vv_outboard=0.30000000000000004, - dz_vv_upper=0.30000000000000004, - dz_vv_lower=0.30000000000000004, - vol_blkt_inboard=0, - vol_blkt_outboard=691.06561956756764, - vol_blkt_total=691.06561956756764, - vol_shld_total=0, - vol_vv=0, - rminor=2.5, - vol_shld_inboard=0, - vol_shld_outboard=0, - vol_vv_inboard=0, - vol_vv_outboard=0, - dz_blkt_half=8.25, - dz_shld_half=8.75, - dz_vv_half=9.4349999999999987, - icomponent=1, - expected_a_blkt_inboard_surface=196.97785938008002, - expected_a_blkt_outboard_surface=852.24160940262459, - expected_a_blkt_total_surface=1049.2194687827046, - expected_a_shld_inboard_surface=208.91591146372122, - expected_a_shld_outboard_surface=1013.8483589087293, - expected_a_shld_total_surface=1222.7642703724505, - expected_vol_blkt_outboard=691.06561956756764, - expected_volblkt=691.06561956756764, - expected_vol_shld_total=450.46122947809488, - expected_vol_vv=0, - expected_vol_shld_inboard=79.896984366095609, - expected_vol_shld_outboard=370.5642451119993, - expected_vol_vv_inboard=0, - expected_vol_vv_outboard=0, - expected_icomponent=1, - ), ), ) def test_dshaped_component(dshapedcomponentparam, monkeypatch, blanket_library_fixture): From 35f690c9adfa9588f7c9be464044118f285d2da8 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 23 Jan 2026 15:16:54 +0000 Subject: [PATCH 20/35] Remove redundant EllipticalComponentParam test cases --- tests/unit/test_blanket_library.py | 52 ------------------------------ 1 file changed, 52 deletions(-) diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index b6f9130d70..1f75da9c41 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -872,58 +872,6 @@ class EllipticalComponentParam(NamedTuple): expected_vol_vv_outboard=0, expected_icomponent=0, ), - EllipticalComponentParam( - r_shld_inboard_inner=4.0833333333333339, - dr_shld_inboard=0.30000000000000004, - dr_blkt_inboard=0.70000000000000007, - r_shld_outboard_outer=12.716666666666667, - dr_shld_outboard=0.80000000000000004, - dr_blkt_outboard=1, - a_blkt_inboard_surface=664.9687712975541, - a_blkt_outboard_surface=1101.3666396424403, - a_blkt_total_surface=1766.3354109399943, - dz_blkt_upper=0.85000000000000009, - a_shld_inboard_surface=0, - a_shld_outboard_surface=0, - a_shld_total_surface=0, - dz_shld_upper=0.59999999999999998, - dr_vv_inboard=0.30000000000000004, - dr_vv_outboard=0.30000000000000004, - dz_vv_upper=0.30000000000000004, - dz_vv_lower=0.30000000000000004, - vol_blkt_inboard=315.83946385183026, - vol_blkt_outboard=1020.3677420460117, - vol_blkt_total=1336.207205897842, - vol_shld_total=0, - vol_vv=0, - rmajor=8, - rminor=2.6666666666666665, - triang=0.5, - vol_shld_inboard=0, - vol_shld_outboard=0, - vol_vv_inboard=0, - vol_vv_outboard=0, - dz_blkt_half=5.9532752487304119, - dz_shld_half=6.8032752487304133, - dz_vv_half=7.5032752487304135, - icomponent=1, - expected_a_blkt_inboard_surface=664.9687712975541, - expected_a_blkt_outboard_surface=1101.3666396424403, - expected_a_blkt_total_surface=1766.3354109399943, - expected_a_shld_inboard_surface=700.06731267447844, - expected_a_shld_outboard_surface=1344.1106481995357, - expected_a_shld_total_surface=2044.1779608740142, - expected_vol_blkt_inboard=315.83946385183026, - expected_vol_blkt_outboard=1020.3677420460117, - expected_volblkt=1336.207205897842, - expected_vol_shld_total=1124.4621612595051, - expected_vol_vv=0, - expected_vol_shld_inboard=177.89822933168091, - expected_vol_shld_outboard=946.56393192782434, - expected_vol_vv_inboard=0, - expected_vol_vv_outboard=0, - expected_icomponent=1, - ), ), ) def test_elliptical_component( From 51f8c08f14c894edfc15f97609bee6905aa4ea5b Mon Sep 17 00:00:00 2001 From: mn3981 Date: Thu, 29 Jan 2026 10:48:15 +0000 Subject: [PATCH 21/35] Post rebase changes --- process/blanket_library.py | 22 ---------------------- process/caller.py | 7 ++++--- process/hcpb.py | 5 +++++ process/shield.py | 38 ++++++++++++++++++++++++++++++-------- process/vacuum.py | 6 ++---- 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index e87791e4eb..e37caca901 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -253,28 +253,6 @@ def apply_coverage_factors(self): fwbs_variables.vol_blkt_inboard + fwbs_variables.vol_blkt_outboard ) - # Apply shield coverage factors - build_variables.a_shld_inboard_surface = ( - fwbs_variables.fvolsi * build_variables.a_shld_inboard_surface - ) - build_variables.a_shld_outboard_surface = ( - fwbs_variables.fvolso * build_variables.a_shld_outboard_surface - ) - build_variables.a_shld_total_surface = ( - build_variables.a_shld_inboard_surface - + build_variables.a_shld_outboard_surface - ) - - blanket_library.vol_shld_inboard = ( - fwbs_variables.fvolsi * blanket_library.vol_shld_inboard - ) - blanket_library.vol_shld_outboard = ( - fwbs_variables.fvolso * blanket_library.vol_shld_outboard - ) - fwbs_variables.vol_shld_total = ( - blanket_library.vol_shld_inboard + blanket_library.vol_shld_outboard - ) - def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. Uses middle value of input and output temperatures of coolant. diff --git a/process/caller.py b/process/caller.py index 29682d85ce..7ed29c6687 100644 --- a/process/caller.py +++ b/process/caller.py @@ -276,6 +276,10 @@ def _call_models_once(self, xc: np.ndarray) -> None: # First wall model self.models.fw.run() + self.models.shield.run() + + self.models.vacuum_vessel.run() + # Blanket model """Blanket switch values No. | model @@ -296,9 +300,6 @@ def _call_models_once(self, xc: np.ndarray) -> None: # DCLL model self.models.dcll.run(output=False) - self.models.shield.run() - self.models.vacuum_vessel.run() - self.models.divertor.run(output=False) self.models.cryostat.run() diff --git a/process/hcpb.py b/process/hcpb.py index a238e1405f..288beb7a51 100644 --- a/process/hcpb.py +++ b/process/hcpb.py @@ -474,6 +474,11 @@ def nuclear_heating_magnets(self, output: bool): if build_variables.dr_vv_outboard > d_vv_all: d_vv_all = build_variables.dr_vv_outboard + if d_vv_all > 1.0e-6: + ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv + else: + ccfe_hcpb_module.vv_density = 0.0 + # Calculation of average blanket/shield thickness [m] if physics_variables.itart == 1: # There is no inner blanket for TART design [m] diff --git a/process/shield.py b/process/shield.py index 73a263c303..ec5ee96bd6 100644 --- a/process/shield.py +++ b/process/shield.py @@ -20,7 +20,7 @@ def run(self) -> None: z_plasma_xpoint_lower=build_variables.z_plasma_xpoint_lower, dz_xpoint_divertor=build_variables.dz_xpoint_divertor, dz_divertor=divertor_variables.dz_divertor, - n_divertors=physics_variables.n_divertors, + n_divertors=divertor_variables.n_divertors, z_plasma_xpoint_upper=build_variables.z_plasma_xpoint_upper, dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, @@ -31,9 +31,9 @@ def run(self) -> None: # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: ( - blanket_library.a_shld_inboard_surface, - blanket_library.a_shld_outboard_surface, - blanket_library.a_shld_total_surface, + build_variables.a_shld_inboard_surface, + build_variables.a_shld_outboard_surface, + build_variables.a_shld_total_surface, ) = self.calculate_dshaped_shield_areas( rsldi=build_variables.rsldi, dr_shld_inboard=build_variables.dr_shld_inboard, @@ -50,7 +50,7 @@ def run(self) -> None: ( blanket_library.vol_shld_inboard, blanket_library.vol_shld_outboard, - blanket_library.vol_shld_total, + fwbs_variables.vol_shld_total, ) = self.calculate_dshaped_shield_volumes( rsldi=build_variables.rsldi, dr_shld_inboard=build_variables.dr_shld_inboard, @@ -83,9 +83,9 @@ def run(self) -> None: ) ( - build_variables.vol_shld_inboard, - build_variables.vol_shld_outboard, - build_variables.vol_shld_total, + blanket_library.vol_shld_inboard, + blanket_library.vol_shld_outboard, + fwbs_variables.vol_shld_total, ) = self.calculate_elliptical_shield_volumes( rsldi=build_variables.rsldi, rsldo=build_variables.rsldo, @@ -98,6 +98,28 @@ def run(self) -> None: dz_shld_upper=build_variables.dz_shld_upper, ) + # Apply shield coverage factors + build_variables.a_shld_inboard_surface = ( + fwbs_variables.fvolsi * build_variables.a_shld_inboard_surface + ) + build_variables.a_shld_outboard_surface = ( + fwbs_variables.fvolso * build_variables.a_shld_outboard_surface + ) + build_variables.a_shld_total_surface = ( + build_variables.a_shld_inboard_surface + + build_variables.a_shld_outboard_surface + ) + + blanket_library.vol_shld_inboard = ( + fwbs_variables.fvolsi * blanket_library.vol_shld_inboard + ) + blanket_library.vol_shld_outboard = ( + fwbs_variables.fvolso * blanket_library.vol_shld_outboard + ) + fwbs_variables.vol_shld_total = ( + blanket_library.vol_shld_inboard + blanket_library.vol_shld_outboard + ) + @staticmethod def calculate_shield_half_height( z_plasma_xpoint_lower: float, diff --git a/process/vacuum.py b/process/vacuum.py index 321526eb4e..b6485f295b 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -8,8 +8,8 @@ from process.blanket_library import dshellvol, eshellvol from process.data_structure import blanket_library as blanket_library from process.data_structure import build_variables as buv -from process.data_structure import divertor_variables as dv from process.data_structure import ccfe_hcpb_module as ccfe_hcpb_module +from process.data_structure import divertor_variables as dv from process.data_structure import fwbs_variables as fwbs_variables from process.data_structure import physics_variables as physics_variables from process.data_structure import physics_variables as pv @@ -704,7 +704,7 @@ def run(self) -> None: z_tf_inside_half=buv.z_tf_inside_half, dz_shld_vv_gap=buv.dz_shld_vv_gap, dz_vv_lower=buv.dz_vv_lower, - n_divertors=pv.n_divertors, + n_divertors=dv.n_divertors, dz_blkt_upper=buv.dz_blkt_upper, dz_shld_upper=buv.dz_shld_upper, z_plasma_xpoint_upper=buv.z_plasma_xpoint_upper, @@ -751,8 +751,6 @@ def run(self) -> None: # changes in the same location. fwbs_variables.vol_vv = fwbs_variables.fvoldw * fwbs_variables.vol_vv - ccfe_hcpb_module.vv_density = fwbs_variables.m_vv / fwbs_variables.vol_vv - def calculate_vessel_half_height( self, z_tf_inside_half: float, From c6b1da3817a874be896010719ab73ef5d67820e0 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Thu, 29 Jan 2026 16:07:57 +0000 Subject: [PATCH 22/35] Remove redundant shield surface parameters from ApplyCoverageFactorsParam class --- process/blanket_library.py | 6 ++-- process/shield.py | 36 +++++++++---------- process/vacuum.py | 24 ++++++------- tests/unit/test_blanket_library.py | 55 ------------------------------ tests/unit/test_shield.py | 36 +++++++++---------- tests/unit/test_vacuum.py | 24 ++++++------- 6 files changed, 63 insertions(+), 118 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index e37caca901..231b874a63 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -113,7 +113,7 @@ def dshaped_component(self, icomponent: int): """ # Calculate major radius to outer edge of inboard ... # ... section (m) - r1 = build_variables.rsldi + r1 = build_variables.r_shld_inboard_inner # ... blanket (m) @@ -168,7 +168,7 @@ def elliptical_component(self, icomponent: int): # Calculate distance between r1 and outer edge of inboard ... # ... section (m) - r2 = r1 - build_variables.rsldi + r2 = r1 - build_variables.r_shld_inboard_inner # ... blanket (m) if icomponent == 0: @@ -176,7 +176,7 @@ def elliptical_component(self, icomponent: int): # Calculate distance between r1 and inner edge of outboard ... # ... section (m) - r3 = build_variables.rsldo - r1 + r3 = build_variables.r_shld_outboard_outer - r1 # ... blanket (m) if icomponent == 0: diff --git a/process/shield.py b/process/shield.py index ec5ee96bd6..d012282f5c 100644 --- a/process/shield.py +++ b/process/shield.py @@ -35,7 +35,7 @@ def run(self) -> None: build_variables.a_shld_outboard_surface, build_variables.a_shld_total_surface, ) = self.calculate_dshaped_shield_areas( - rsldi=build_variables.rsldi, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, dr_shld_inboard=build_variables.dr_shld_inboard, dr_fw_inboard=build_variables.dr_fw_inboard, dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, @@ -52,7 +52,7 @@ def run(self) -> None: blanket_library.vol_shld_outboard, fwbs_variables.vol_shld_total, ) = self.calculate_dshaped_shield_volumes( - rsldi=build_variables.rsldi, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, dr_shld_inboard=build_variables.dr_shld_inboard, dr_fw_inboard=build_variables.dr_fw_inboard, dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, @@ -72,8 +72,8 @@ def run(self) -> None: build_variables.a_shld_outboard_surface, build_variables.a_shld_total_surface, ) = self.calculate_elliptical_shield_areas( - rsldi=build_variables.rsldi, - rsldo=build_variables.rsldo, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + r_shld_outboard_outer=build_variables.r_shld_outboard_outer, rmajor=physics_variables.rmajor, triang=physics_variables.triang, dr_shld_inboard=build_variables.dr_shld_inboard, @@ -87,8 +87,8 @@ def run(self) -> None: blanket_library.vol_shld_outboard, fwbs_variables.vol_shld_total, ) = self.calculate_elliptical_shield_volumes( - rsldi=build_variables.rsldi, - rsldo=build_variables.rsldo, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + r_shld_outboard_outer=build_variables.r_shld_outboard_outer, rmajor=physics_variables.rmajor, triang=physics_variables.triang, dr_shld_inboard=build_variables.dr_shld_inboard, @@ -156,7 +156,7 @@ def calculate_shield_half_height( @staticmethod def calculate_dshaped_shield_volumes( - rsldi: float, + r_shld_inboard_inner: float, dr_shld_inboard: float, dr_fw_inboard: float, dr_fw_plasma_gap_inboard: float, @@ -171,7 +171,7 @@ def calculate_dshaped_shield_volumes( ) -> tuple[float, float, float]: """Calculate volumes of D-shaped shield segments.""" - r_1 = rsldi + dr_shld_inboard + r_1 = r_shld_inboard_inner + dr_shld_inboard r_2 = ( dr_fw_inboard + dr_fw_plasma_gap_inboard @@ -199,7 +199,7 @@ def calculate_dshaped_shield_volumes( @staticmethod def calculate_dshaped_shield_areas( - rsldi: float, + r_shld_inboard_inner: float, dr_shld_inboard: float, dr_fw_inboard: float, dr_fw_plasma_gap_inboard: float, @@ -212,7 +212,7 @@ def calculate_dshaped_shield_areas( ) -> tuple[float, float, float]: """Calculate areas of D-shaped shield segments.""" - r_1 = rsldi + dr_shld_inboard + r_1 = r_shld_inboard_inner + dr_shld_inboard r_2 = ( dr_fw_inboard + dr_fw_plasma_gap_inboard @@ -233,8 +233,8 @@ def calculate_dshaped_shield_areas( @staticmethod def calculate_elliptical_shield_volumes( - rsldi: float, - rsldo: float, + r_shld_inboard_inner: float, + r_shld_outboard_outer: float, rmajor: float, triang: float, dr_shld_inboard: float, @@ -248,11 +248,11 @@ def calculate_elliptical_shield_volumes( # Major radius to centre of inboard and outboard ellipses (m) # (coincident in radius with top of plasma) r_1 = rmajor - rminor * triang - r_2 = r_1 - rsldi + r_2 = r_1 - r_shld_inboard_inner r_2 = r_2 - dr_shld_inboard - r_3 = rsldo - r_1 + r_3 = r_shld_outboard_outer - r_1 r_3 = r_3 - dr_shld_outboard ( @@ -273,8 +273,8 @@ def calculate_elliptical_shield_volumes( @staticmethod def calculate_elliptical_shield_areas( - rsldi: float, - rsldo: float, + r_shld_inboard_inner: float, + r_shld_outboard_outer: float, rmajor: float, triang: float, dr_shld_inboard: float, @@ -287,11 +287,11 @@ def calculate_elliptical_shield_areas( # Major radius to centre of inboard and outboard ellipses (m) # (coincident in radius with top of plasma) r_1 = rmajor - rminor * triang - r_2 = r_1 - rsldi + r_2 = r_1 - r_shld_inboard_inner r_2 = r_2 - dr_shld_inboard - r_3 = rsldo - r_1 + r_3 = r_shld_outboard_outer - r_1 r_3 = r_3 - dr_shld_outboard ( diff --git a/process/vacuum.py b/process/vacuum.py index b6485f295b..ff274a6e44 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -720,8 +720,8 @@ def run(self) -> None: blanket_library.vol_vv_outboard, fwbs_variables.vol_vv, ) = self.calculate_dshaped_vessel_volumes( - rsldi=buv.rsldi, - rsldo=buv.rsldo, + r_shld_inboard_inner=buv.r_shld_inboard_inner, + r_shld_outboard_outer=buv.r_shld_outboard_outer, dz_vv_half=blanket_library.dz_vv_half, dr_vv_inboard=buv.dr_vv_inboard, dr_vv_outboard=buv.dr_vv_outboard, @@ -737,8 +737,8 @@ def run(self) -> None: rmajor=pv.rmajor, rminor=pv.rminor, triang=pv.triang, - rsldi=buv.rsldi, - rsldo=buv.rsldo, + r_shld_inboard_inner=buv.r_shld_inboard_inner, + r_shld_outboard_outer=buv.r_shld_outboard_outer, dz_vv_half=blanket_library.dz_vv_half, dr_vv_inboard=buv.dr_vv_inboard, dr_vv_outboard=buv.dr_vv_outboard, @@ -788,8 +788,8 @@ def calculate_vessel_half_height( def calculate_dshaped_vessel_volumes( self, - rsldi: float, - rsldo: float, + r_shld_inboard_inner: float, + r_shld_outboard_outer: float, dz_vv_half: float, dr_vv_inboard: float, dr_vv_outboard: float, @@ -798,8 +798,8 @@ def calculate_dshaped_vessel_volumes( ) -> tuple[float, float, float]: """Calculate volumes of D-shaped vacuum vessel segments""" - r_1 = rsldi - r_2 = rsldo - r_1 + r_1 = r_shld_inboard_inner + r_2 = r_shld_outboard_outer - r_1 ( vol_vv_inboard, @@ -821,8 +821,8 @@ def calculate_elliptical_vessel_volumes( rmajor: float, rminor: float, triang: float, - rsldi: float, - rsldo: float, + r_shld_inboard_inner: float, + r_shld_outboard_outer: float, dz_vv_half: float, dr_vv_inboard: float, dr_vv_outboard: float, @@ -835,8 +835,8 @@ def calculate_elliptical_vessel_volumes( # Calculate distance between r1 and outer edge of inboard ... # ... section (m) - r_2 = r_1 - rsldi - r_3 = rsldo - r_1 + r_2 = r_1 - r_shld_inboard_inner + r_3 = r_shld_outboard_outer - r_1 ( vol_vv_inboard, diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index 1f75da9c41..1074b101ab 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -1018,9 +1018,6 @@ class ApplyCoverageFactorsParam(NamedTuple): a_blkt_outboard_surface: Any = None a_blkt_total_surface: Any = None a_blkt_inboard_surface: Any = None - a_shld_inboard_surface: Any = None - a_shld_outboard_surface: Any = None - a_shld_total_surface: Any = None f_ster_div_single: Any = None f_a_fw_outboard_hcd: Any = None vol_blkt_outboard: Any = None @@ -1034,13 +1031,9 @@ class ApplyCoverageFactorsParam(NamedTuple): vol_shld_outboard: Any = None expected_a_blkt_outboard_surface: Any = None expected_a_blkt_total_surface: Any = None - expected_a_shld_outboard_surface: Any = None - expected_a_shld_total_surface: Any = None expected_vol_blkt_outboard: Any = None expected_volblkt: Any = None - expected_vol_shld_total: Any = None expected_vol_vv: Any = None - expected_vol_shld_outboard: Any = None @pytest.mark.parametrize( @@ -1050,9 +1043,6 @@ class ApplyCoverageFactorsParam(NamedTuple): a_blkt_outboard_surface=1101.3666396424403, a_blkt_total_surface=1766.3354109399943, a_blkt_inboard_surface=664.9687712975541, - a_shld_inboard_surface=700.06731267447844, - a_shld_outboard_surface=1344.1106481995357, - a_shld_total_surface=2044.1779608740142, f_ster_div_single=0.115, f_a_fw_outboard_hcd=0, vol_blkt_outboard=1020.3677420460117, @@ -1060,19 +1050,12 @@ class ApplyCoverageFactorsParam(NamedTuple): vol_blkt_total=1336.207205897842, fvolsi=1, fvolso=0.64000000000000001, - vol_shld_total=1124.4621612595051, n_divertors=1, - vol_shld_inboard=177.89822933168091, - vol_shld_outboard=946.56393192782434, expected_a_blkt_outboard_surface=898.23806738434075, expected_a_blkt_total_surface=1563.2068386818949, - expected_a_shld_outboard_surface=860.23081484770285, - expected_a_shld_total_surface=1560.2981275221814, expected_vol_blkt_outboard=866.70391336775992, expected_volblkt=1182.5433772195902, - expected_vol_shld_total=783.69914576548854, expected_vol_vv=1016.2876250857248, - expected_vol_shld_outboard=605.80091643380763, ), ), ) @@ -1105,21 +1088,6 @@ def test_apply_coverage_factors( "a_blkt_inboard_surface", applycoveragefactorsparam.a_blkt_inboard_surface, ) - monkeypatch.setattr( - build_variables, - "a_shld_inboard_surface", - applycoveragefactorsparam.a_shld_inboard_surface, - ) - monkeypatch.setattr( - build_variables, - "a_shld_outboard_surface", - applycoveragefactorsparam.a_shld_outboard_surface, - ) - monkeypatch.setattr( - build_variables, - "a_shld_total_surface", - applycoveragefactorsparam.a_shld_total_surface, - ) monkeypatch.setattr( fwbs_variables, "f_ster_div_single", applycoveragefactorsparam.f_ster_div_single ) @@ -1139,20 +1107,9 @@ def test_apply_coverage_factors( ) monkeypatch.setattr(fwbs_variables, "fvolsi", applycoveragefactorsparam.fvolsi) monkeypatch.setattr(fwbs_variables, "fvolso", applycoveragefactorsparam.fvolso) - monkeypatch.setattr( - fwbs_variables, "vol_shld_total", applycoveragefactorsparam.vol_shld_total - ) monkeypatch.setattr( divertor_variables, "n_divertors", applycoveragefactorsparam.n_divertors ) - monkeypatch.setattr( - blanket_library, "vol_shld_inboard", applycoveragefactorsparam.vol_shld_inboard - ) - monkeypatch.setattr( - blanket_library, - "vol_shld_outboard", - applycoveragefactorsparam.vol_shld_outboard, - ) blanket_library_fixture.apply_coverage_factors() @@ -1162,24 +1119,12 @@ def test_apply_coverage_factors( assert build_variables.a_blkt_total_surface == pytest.approx( applycoveragefactorsparam.expected_a_blkt_total_surface ) - assert build_variables.a_shld_outboard_surface == pytest.approx( - applycoveragefactorsparam.expected_a_shld_outboard_surface - ) - assert build_variables.a_shld_total_surface == pytest.approx( - applycoveragefactorsparam.expected_a_shld_total_surface - ) assert fwbs_variables.vol_blkt_outboard == pytest.approx( applycoveragefactorsparam.expected_vol_blkt_outboard ) assert fwbs_variables.vol_blkt_total == pytest.approx( applycoveragefactorsparam.expected_volblkt ) - assert fwbs_variables.vol_shld_total == pytest.approx( - applycoveragefactorsparam.expected_vol_shld_total - ) - assert blanket_library.vol_shld_outboard == pytest.approx( - applycoveragefactorsparam.expected_vol_shld_outboard - ) class BlanketModPolHeightParam(NamedTuple): diff --git a/tests/unit/test_shield.py b/tests/unit/test_shield.py index 18d9717984..a13cbf8dfe 100644 --- a/tests/unit/test_shield.py +++ b/tests/unit/test_shield.py @@ -19,8 +19,8 @@ class EllipticalShieldVolumes(NamedTuple): rmajor: Any = None rminor: Any = None triang: Any = None - rsldi: Any = None - rsldo: Any = None + r_shld_inboard_inner: Any = None + r_shld_outboard_outer: Any = None dz_shield_half: Any = None dr_shield_inboard: Any = None dr_shield_outboard: Any = None @@ -36,8 +36,8 @@ class EllipticalShieldVolumes(NamedTuple): rmajor=8, rminor=2.6666666666666665, triang=0.5, - rsldi=4.083333333333334, - rsldo=12.716666666666667, + r_shld_inboard_inner=4.083333333333334, + r_shld_outboard_outer=12.716666666666667, dz_shield_half=6.8032752487304133, dr_shield_inboard=0.30000000000000004, dr_shield_outboard=0.80000000000000004, @@ -63,8 +63,8 @@ def test_elliptical_shield_volumes(shield, elliptical_shield_volumes, expected): vol_shield_inboard, vol_shield_outboard, vol_shield = ( shield.calculate_elliptical_shield_volumes( - rsldi=elliptical_shield_volumes.rsldi, - rsldo=elliptical_shield_volumes.rsldo, + r_shld_inboard_inner=elliptical_shield_volumes.r_shld_inboard_inner, + r_shld_outboard_outer=elliptical_shield_volumes.r_shld_outboard_outer, rmajor=elliptical_shield_volumes.rmajor, triang=elliptical_shield_volumes.triang, dr_shld_inboard=elliptical_shield_volumes.dr_shield_inboard, @@ -84,8 +84,8 @@ class EllipticalShieldAreas(NamedTuple): rmajor: Any = None rminor: Any = None triang: Any = None - rsldi: Any = None - rsldo: Any = None + r_shld_inboard_inner: Any = None + r_shld_outboard_outer: Any = None dz_shield_half: Any = None dr_shield_inboard: Any = None dr_shield_outboard: Any = None @@ -101,8 +101,8 @@ class EllipticalShieldAreas(NamedTuple): rmajor=8, rminor=2.6666666666666665, triang=0.5, - rsldi=4.083333333333334, - rsldo=12.716666666666667, + r_shld_inboard_inner=4.083333333333334, + r_shld_outboard_outer=12.716666666666667, dz_shield_half=6.8032752487304133, dr_shield_inboard=0.30000000000000004, dr_shield_outboard=0.80000000000000004, @@ -126,8 +126,8 @@ def test_elliptical_shield_areas(shield, elliptical_shield_areas, expected): a_shield_inboard, a_shield_outboard, a_shield = ( shield.calculate_elliptical_shield_areas( - rsldi=elliptical_shield_areas.rsldi, - rsldo=elliptical_shield_areas.rsldo, + r_shld_inboard_inner=elliptical_shield_areas.r_shld_inboard_inner, + r_shld_outboard_outer=elliptical_shield_areas.r_shld_outboard_outer, rmajor=elliptical_shield_areas.rmajor, triang=elliptical_shield_areas.triang, dr_shld_inboard=elliptical_shield_areas.dr_shield_inboard, @@ -144,7 +144,7 @@ def test_elliptical_shield_areas(shield, elliptical_shield_areas, expected): class DShapedShieldVolumes(NamedTuple): rminor: Any = None - rsldi: Any = None + r_shld_inboard_inner: Any = None dr_shld_inboard: Any = None dr_fw_plasma_gap_inboard: Any = None dr_fw_plasma_gap_outboard: Any = None @@ -164,7 +164,7 @@ class DShapedShieldVolumes(NamedTuple): DShapedShieldVolumes( rminor=2.5, dr_shld_inboard=0.40000000000000002, - rsldi=1.5, + r_shld_inboard_inner=1.5, dr_fw_plasma_gap_inboard=0.10000000000000001, dr_fw_plasma_gap_outboard=0.10000000000000001, dr_fw_inboard=0.018000000000000002, @@ -194,7 +194,7 @@ def test_dshaped_shield_volumes(shield, dshaped_shield_volumes, expected): vol_shield_inboard, vol_shield_outboard, vol_shield = ( shield.calculate_dshaped_shield_volumes( - rsldi=dshaped_shield_volumes.rsldi, + r_shld_inboard_inner=dshaped_shield_volumes.r_shld_inboard_inner, dr_shld_inboard=dshaped_shield_volumes.dr_shld_inboard, dr_fw_inboard=dshaped_shield_volumes.dr_fw_inboard, dr_fw_plasma_gap_inboard=dshaped_shield_volumes.dr_fw_plasma_gap_inboard, @@ -216,7 +216,7 @@ def test_dshaped_shield_volumes(shield, dshaped_shield_volumes, expected): class DShapedShieldAreas(NamedTuple): rminor: Any = None - rsldi: Any = None + r_shld_inboard_inner: Any = None dr_shld_inboard: Any = None dr_fw_plasma_gap_inboard: Any = None dr_fw_plasma_gap_outboard: Any = None @@ -234,7 +234,7 @@ class DShapedShieldAreas(NamedTuple): DShapedShieldAreas( rminor=2.5, dr_shld_inboard=0.40000000000000002, - rsldi=1.5, + r_shld_inboard_inner=1.5, dr_fw_plasma_gap_inboard=0.10000000000000001, dr_fw_plasma_gap_outboard=0.10000000000000001, dr_fw_inboard=0.018000000000000002, @@ -262,7 +262,7 @@ def test_dshaped_shield_areas(shield, dshaped_shield_areas, expected): a_shield_inboard, a_shield_outboard, a_shield = ( shield.calculate_dshaped_shield_areas( - rsldi=dshaped_shield_areas.rsldi, + r_shld_inboard_inner=dshaped_shield_areas.r_shld_inboard_inner, dr_shld_inboard=dshaped_shield_areas.dr_shld_inboard, dr_fw_inboard=dshaped_shield_areas.dr_fw_inboard, dr_fw_plasma_gap_inboard=dshaped_shield_areas.dr_fw_plasma_gap_inboard, diff --git a/tests/unit/test_vacuum.py b/tests/unit/test_vacuum.py index d0c7bef2ca..387f19c7bf 100644 --- a/tests/unit/test_vacuum.py +++ b/tests/unit/test_vacuum.py @@ -127,8 +127,8 @@ class EllipticalVesselVolumes(NamedTuple): rmajor: Any = None rminor: Any = None triang: Any = None - rsldi: Any = None - rsldo: Any = None + r_shld_inboard_inner: Any = None + r_shld_outboard_outer: Any = None dz_vv_half: Any = None dr_vv_inboard: Any = None dr_vv_outboard: Any = None @@ -144,8 +144,8 @@ class EllipticalVesselVolumes(NamedTuple): rmajor=8, rminor=2.6666666666666665, triang=0.5, - rsldi=4.083333333333334, - rsldo=12.716666666666667, + r_shld_inboard_inner=4.083333333333334, + r_shld_outboard_outer=12.716666666666667, dz_vv_half=7.5032752487304135, dr_vv_inboard=0.30000000000000004, dr_vv_outboard=0.30000000000000004, @@ -174,8 +174,8 @@ def test_elliptical_vessel_volumes(vacuum_vessel, elliptical_vessel_volumes, exp rmajor=elliptical_vessel_volumes.rmajor, rminor=elliptical_vessel_volumes.rminor, triang=elliptical_vessel_volumes.triang, - rsldi=elliptical_vessel_volumes.rsldi, - rsldo=elliptical_vessel_volumes.rsldo, + r_shld_inboard_inner=elliptical_vessel_volumes.r_shld_inboard_inner, + r_shld_outboard_outer=elliptical_vessel_volumes.r_shld_outboard_outer, dz_vv_half=elliptical_vessel_volumes.dz_vv_half, dr_vv_inboard=elliptical_vessel_volumes.dr_vv_inboard, dr_vv_outboard=elliptical_vessel_volumes.dr_vv_outboard, @@ -190,8 +190,8 @@ def test_elliptical_vessel_volumes(vacuum_vessel, elliptical_vessel_volumes, exp class DShapedVesselVolumes(NamedTuple): - rsldi: Any = None - rsldo: Any = None + r_shld_inboard_inner: Any = None + r_shld_outboard_outer: Any = None dz_vv_half: Any = None dr_vv_inboard: Any = None dr_vv_outboard: Any = None @@ -204,8 +204,8 @@ class DShapedVesselVolumes(NamedTuple): [ ( DShapedVesselVolumes( - rsldi=1.5, - rsldo=8.4000000000000004, + r_shld_inboard_inner=1.5, + r_shld_outboard_outer=8.4000000000000004, dz_vv_half=9.4349999999999987, dr_vv_inboard=0.20000000000000001, dr_vv_outboard=0.30000000000000004, @@ -230,8 +230,8 @@ def test_dshaped_vessel_volumes(vacuum_vessel, dshaped_vessel_volumes, expected) vol_vv_inboard, vol_vv_outboard, vol_vv = ( vacuum_vessel.calculate_dshaped_vessel_volumes( - rsldi=dshaped_vessel_volumes.rsldi, - rsldo=dshaped_vessel_volumes.rsldo, + r_shld_inboard_inner=dshaped_vessel_volumes.r_shld_inboard_inner, + r_shld_outboard_outer=dshaped_vessel_volumes.r_shld_outboard_outer, dz_vv_half=dshaped_vessel_volumes.dz_vv_half, dr_vv_inboard=dshaped_vessel_volumes.dr_vv_inboard, dr_vv_outboard=dshaped_vessel_volumes.dr_vv_outboard, From 472208adef9ff7d44aa7cde2e448ca9cce69ab81 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 09:32:04 +0000 Subject: [PATCH 23/35] Requested style changes --- process/blanket_library.py | 100 ++++----- process/vacuum.py | 341 ++++++++++++++++------------- tests/unit/test_blanket_library.py | 6 +- 3 files changed, 233 insertions(+), 214 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index 231b874a63..aa447c98fa 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -58,13 +58,11 @@ def component_volumes(self): # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: - for icomponent in range(1): - self.dshaped_component(icomponent) + self.dshaped_component() # Elliptical blanket and shield else: - for icomponent in range(1): - self.elliptical_component(icomponent) + self.elliptical_component() # Apply coverage factors to volumes and surface areas self.apply_coverage_factors() @@ -84,10 +82,6 @@ def component_half_height(self, icomponent: int): + divertor_variables.dz_divertor - build_variables.dz_blkt_upper ) - else: - raise ProcessValueError( - f"{icomponent=} is invalid, it must be 0 for blanket." - ) # Calculate component internal upper half-height (m) # If a double null machine then symmetric @@ -105,7 +99,7 @@ def component_half_height(self, icomponent: int): # Average of top and bottom (m) return 0.5 * (htop + hbot) - def dshaped_component(self, icomponent: int): + def dshaped_component(self): """Calculate component surface area and volume using dshaped scheme Based on dshaped_blanket, dshaped_shield, dshaped_vv original author: J. Morris, CCFE, Culham Science Centre @@ -130,30 +124,26 @@ def dshaped_component(self, icomponent: int): + build_variables.dr_fw_outboard ) - # Calculate surface area, assuming 100% coverage - if icomponent == 0: - ( - build_variables.a_blkt_inboard_surface, - build_variables.a_blkt_outboard_surface, - build_variables.a_blkt_total_surface, - ) = dshellarea(r1, r2, blanket_library.dz_blkt_half) + ( + build_variables.a_blkt_inboard_surface, + build_variables.a_blkt_outboard_surface, + build_variables.a_blkt_total_surface, + ) = dshellarea(r1, r2, blanket_library.dz_blkt_half) - # Calculate volumes, assuming 100% coverage - if icomponent == 0: - ( - fwbs_variables.vol_blkt_inboard, - fwbs_variables.vol_blkt_outboard, - fwbs_variables.vol_blkt_total, - ) = dshellvol( - r1, - r2, - blanket_library.dz_blkt_half, - build_variables.dr_blkt_inboard, - build_variables.dr_blkt_outboard, - build_variables.dz_blkt_upper, - ) + ( + fwbs_variables.vol_blkt_inboard, + fwbs_variables.vol_blkt_outboard, + fwbs_variables.vol_blkt_total, + ) = dshellvol( + r1, + r2, + blanket_library.dz_blkt_half, + build_variables.dr_blkt_inboard, + build_variables.dr_blkt_outboard, + build_variables.dz_blkt_upper, + ) - def elliptical_component(self, icomponent: int): + def elliptical_component(self): """Calculate component surface area and volume using elliptical scheme Based on elliptical_blanket, elliptical_shield, elliptical_vv original author: J. Morris, CCFE, Culham Science Centre @@ -170,41 +160,37 @@ def elliptical_component(self, icomponent: int): # ... section (m) r2 = r1 - build_variables.r_shld_inboard_inner - # ... blanket (m) - if icomponent == 0: - r2 = r2 - build_variables.dr_shld_inboard - build_variables.dr_blkt_inboard + r2 = r2 - build_variables.dr_shld_inboard - build_variables.dr_blkt_inboard # Calculate distance between r1 and inner edge of outboard ... # ... section (m) r3 = build_variables.r_shld_outboard_outer - r1 - # ... blanket (m) - if icomponent == 0: - r3 = r3 - build_variables.dr_shld_outboard - build_variables.dr_blkt_outboard + r3 = r3 - build_variables.dr_shld_outboard - build_variables.dr_blkt_outboard # Calculate surface area, assuming 100% coverage - if icomponent == 0: - ( - build_variables.a_blkt_inboard_surface, - build_variables.a_blkt_outboard_surface, - build_variables.a_blkt_total_surface, - ) = eshellarea(r1, r2, r3, blanket_library.dz_blkt_half) + + ( + build_variables.a_blkt_inboard_surface, + build_variables.a_blkt_outboard_surface, + build_variables.a_blkt_total_surface, + ) = eshellarea(r1, r2, r3, blanket_library.dz_blkt_half) # Calculate volumes, assuming 100% coverage - if icomponent == 0: - ( - fwbs_variables.vol_blkt_inboard, - fwbs_variables.vol_blkt_outboard, - fwbs_variables.vol_blkt_total, - ) = eshellvol( - r1, - r2, - r3, - blanket_library.dz_blkt_half, - build_variables.dr_blkt_inboard, - build_variables.dr_blkt_outboard, - build_variables.dz_blkt_upper, - ) + + ( + fwbs_variables.vol_blkt_inboard, + fwbs_variables.vol_blkt_outboard, + fwbs_variables.vol_blkt_total, + ) = eshellvol( + r1, + r2, + r3, + blanket_library.dz_blkt_half, + build_variables.dr_blkt_inboard, + build_variables.dr_blkt_outboard, + build_variables.dz_blkt_upper, + ) def apply_coverage_factors(self): """Apply coverage factors to volumes diff --git a/process/vacuum.py b/process/vacuum.py index ff274a6e44..9a2d3a64a3 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -3,19 +3,18 @@ import numpy as np -from process import constants -from process import process_output as po +from process import constants, process_output from process.blanket_library import dshellvol, eshellvol -from process.data_structure import blanket_library as blanket_library -from process.data_structure import build_variables as buv -from process.data_structure import ccfe_hcpb_module as ccfe_hcpb_module -from process.data_structure import divertor_variables as dv -from process.data_structure import fwbs_variables as fwbs_variables -from process.data_structure import physics_variables as physics_variables -from process.data_structure import physics_variables as pv -from process.data_structure import tfcoil_variables as tfv -from process.data_structure import times_variables as tv -from process.data_structure import vacuum_variables as vacv +from process.data_structure import ( + blanket_library, + build_variables, + divertor_variables, + fwbs_variables, + physics_variables, + tfcoil_variables, + times_variables, + vacuum_variables, +) logger = logging.getLogger(__name__) @@ -49,47 +48,56 @@ def run(self, output: bool) -> None: # MDK Check this!! gasld = ( - 2.0e0 * pv.molflow_plasma_fuelling_required * pv.m_fuel_amu * constants.UMASS + 2.0e0 + * physics_variables.molflow_plasma_fuelling_required + * physics_variables.m_fuel_amu + * constants.UMASS ) - self.i_vacuum_pumping = vacv.i_vacuum_pumping + self.i_vacuum_pumping = vacuum_variables.i_vacuum_pumping # i_vacuum_pumping required to be compared to a b string # as this is what f2py returns if self.i_vacuum_pumping == "old": ( pumpn, - vacv.n_vv_vacuum_ducts, - vacv.dlscal, - vacv.m_vv_vacuum_duct_shield, - vacv.dia_vv_vacuum_ducts, + vacuum_variables.n_vv_vacuum_ducts, + vacuum_variables.dlscal, + vacuum_variables.m_vv_vacuum_duct_shield, + vacuum_variables.dia_vv_vacuum_ducts, ) = self.vacuum( - pv.p_fusion_total_mw, - pv.rmajor, - pv.rminor, - 0.5e0 * (buv.dr_fw_plasma_gap_inboard + buv.dr_fw_plasma_gap_outboard), - pv.a_plasma_surface, - pv.vol_plasma, - buv.dr_shld_outboard, - buv.dr_shld_inboard, - buv.dr_tf_inboard, - buv.r_shld_inboard_inner - - buv.dr_shld_vv_gap_inboard - - buv.dr_vv_inboard, - tfv.n_tf_coils, - tv.t_plant_pulse_dwell, - pv.nd_plasma_electrons_vol_avg, - dv.n_divertors, + physics_variables.p_fusion_total_mw, + physics_variables.rmajor, + physics_variables.rminor, + 0.5e0 + * ( + build_variables.dr_fw_plasma_gap_inboard + + build_variables.dr_fw_plasma_gap_outboard + ), + physics_variables.a_plasma_surface, + physics_variables.vol_plasma, + build_variables.dr_shld_outboard, + build_variables.dr_shld_inboard, + build_variables.dr_tf_inboard, + build_variables.r_shld_inboard_inner + - build_variables.dr_shld_vv_gap_inboard + - build_variables.dr_vv_inboard, + tfcoil_variables.n_tf_coils, + times_variables.t_plant_pulse_dwell, + physics_variables.nd_plasma_electrons_vol_avg, + divertor_variables.n_divertors, qtorus, gasld, output=output, ) # MDK pumpn is real: convert to integer by rounding. - vacv.n_vac_pumps_high = math.floor(pumpn + 0.5e0) + vacuum_variables.n_vac_pumps_high = math.floor(pumpn + 0.5e0) elif self.i_vacuum_pumping == "simple": - vacv.n_iter_vacuum_pumps = self.vacuum_simple(output=output) + vacuum_variables.n_iter_vacuum_pumps = self.vacuum_simple(output=output) else: - logger.error(f"i_vacuum_pumping is invalid: {vacv.i_vacuum_pumping}") + logger.error( + f"i_vacuum_pumping is invalid: {vacuum_variables.i_vacuum_pumping}" + ) def vacuum_simple(self, output) -> float: """Simple model of vacuum pumping system @@ -106,24 +114,27 @@ def vacuum_simple(self, output) -> float: # One ITER torus cryopump has a throughput of 50 Pa m3/s = 1.2155e+22 molecules/s # Issue #304 n_iter_vacuum_pumps = ( - pv.molflow_plasma_fuelling_required / vacv.molflow_vac_pumps + physics_variables.molflow_plasma_fuelling_required + / vacuum_variables.molflow_vac_pumps ) # Pump-down: # Pumping speed per pump m3/s pumpspeed = ( - vacv.volflow_vac_pumps_max - * vacv.f_a_vac_pump_port_plasma_surface - * vacv.f_volflow_vac_pumps_impedance - * pv.a_plasma_surface - / tfv.n_tf_coils + vacuum_variables.volflow_vac_pumps_max + * vacuum_variables.f_a_vac_pump_port_plasma_surface + * vacuum_variables.f_volflow_vac_pumps_impedance + * physics_variables.a_plasma_surface + / tfcoil_variables.n_tf_coils ) - wallarea = (pv.a_plasma_surface / 1084.0e0) * 2000.0e0 + wallarea = (physics_variables.a_plasma_surface / 1084.0e0) * 2000.0e0 # Required pumping speed for pump-down pumpdownspeed = ( - vacv.outgasfactor * wallarea / vacv.pres_vv_chamber_base - ) * tv.t_plant_pulse_dwell ** (-vacv.outgasindex) + vacuum_variables.outgasfactor + * wallarea + / vacuum_variables.pres_vv_chamber_base + ) * times_variables.t_plant_pulse_dwell ** (-vacuum_variables.outgasindex) # Number of pumps required for pump-down npumpdown = pumpdownspeed / pumpspeed @@ -133,32 +144,32 @@ def vacuum_simple(self, output) -> float: # Output section if output: - po.oheadr(self.outfile, "Vacuum System") - po.ovarst( + process_output.oheadr(self.outfile, "Vacuum System") + process_output.ovarst( self.outfile, "Switch for vacuum pumping model", "(i_vacuum_pumping)", '"' + self.i_vacuum_pumping + '"', ) - po.ocmmnt( + process_output.ocmmnt( self.outfile, "Simple steady-state model with comparison to ITER cryopumps", ) - po.ovarre( + process_output.ovarre( self.outfile, "Plasma fuelling rate (nucleus-pairs/s)", "(molflow_plasma_fuelling_required)", - pv.molflow_plasma_fuelling_required, + physics_variables.molflow_plasma_fuelling_required, "OP ", ) - po.ocmmnt( + process_output.ocmmnt( self.outfile, "Number of high vacuum pumps, each with the throughput" ) - po.ocmmnt( + process_output.ocmmnt( self.outfile, " of one ITER cryopump (50 Pa m3 s-1 = 1.2e+22 molecules/s),", ) - po.ovarre( + process_output.ovarre( self.outfile, " all operating at the same time", "(n_iter_vacuum_pumps)", @@ -166,20 +177,20 @@ def vacuum_simple(self, output) -> float: "OP ", ) - po.ovarre( + process_output.ovarre( self.outfile, "Dwell time", "(t_plant_pulse_dwell)", - tv.t_plant_pulse_dwell, + times_variables.t_plant_pulse_dwell, ) - po.ovarre( + process_output.ovarre( self.outfile, "Number of pumps required for pump-down", "(npumpdown)", npumpdown, "OP ", ) - po.ovarre( + process_output.ovarre( self.outfile, "Number of pumps required overall", "(npump)", @@ -316,7 +327,7 @@ def vacuum( # nitrogen, DT, helium, DT again sp = ( [1.95, 1.8, 1.8, 1.8] - if vacv.i_vacuum_pump_type == 0 + if vacuum_variables.i_vacuum_pump_type == 0 else [9.0, 25.0, 5.0, 25.0] ) @@ -334,8 +345,8 @@ def vacuum( area = plasma_sarea * (aw + dsol) / aw - ogas = vacv.outgrat_fw * area * 10.0e0 # Outgassing rate (Pa-m^3/s) - s.append(ogas / vacv.pres_vv_chamber_base) + ogas = vacuum_variables.outgrat_fw * area * 10.0e0 # Outgassing rate (Pa-m^3/s) + s.append(ogas / vacuum_variables.pres_vv_chamber_base) # Pumpdown between burns # s(2) = net pump speed (DT) required for pumpdown between burns (m^3/s) @@ -343,7 +354,7 @@ def vacuum( # t_plant_pulse_dwell = dwell time between burns (s) pend = ( - 0.5e0 * nplasma * k * vacv.temp_vv_chamber_gas_burn_end + 0.5e0 * nplasma * k * vacuum_variables.temp_vv_chamber_gas_burn_end ) # pressure in plasma chamber after burn (Pa) pstart = 0.01e0 * pend # pressure in chamber before start of burn (Pa) @@ -354,10 +365,10 @@ def vacuum( volume = plasma_vol * (aw + dsol) * (aw + dsol) / (aw * aw) # dwell pumping options - if (vacv.i_vac_pump_dwell == 1) or (t_plant_pulse_dwell == 0): - tpump = tv.t_plant_pulse_coil_precharge - elif vacv.i_vac_pump_dwell == 2: - tpump = t_plant_pulse_dwell + tv.t_plant_pulse_coil_precharge + if (vacuum_variables.i_vac_pump_dwell == 1) or (t_plant_pulse_dwell == 0): + tpump = times_variables.t_plant_pulse_coil_precharge + elif vacuum_variables.i_vac_pump_dwell == 2: + tpump = t_plant_pulse_dwell + times_variables.t_plant_pulse_coil_precharge else: tpump = t_plant_pulse_dwell @@ -373,12 +384,12 @@ def vacuum( fhe = source / (frate * 4.985e5) s.extend( ( - (source / vacv.pres_div_chamber_burn / fhe), + (source / vacuum_variables.pres_div_chamber_burn / fhe), # Removal of dt on steady state basis # s(4) = net speed (D-T) required to remove dt at fuelling rate (m^3/s) ( (frate * 4.985e5 - source) - / (vacv.pres_div_chamber_burn * (1.0e0 - fhe)) + / (vacuum_variables.pres_div_chamber_burn * (1.0e0 - fhe)) ), ), ) @@ -468,7 +479,7 @@ def vacuum( else: logger.error( - f"Newton's method not converging; check fusion power, te {pv.p_fusion_total_mw=} {pv.temp_plasma_electron_vol_avg_kev=}" + f"Newton's method not converging; check fusion power, te {physics_variables.p_fusion_total_mw=} {physics_variables.temp_plasma_electron_vol_avg_kev=}" ) theta = math.pi / ntf @@ -512,7 +523,7 @@ def vacuum( # If cryopumps are used then an additional pump is required # for continuous operation with regeneration. - if vacv.i_vacuum_pump_type == 1: + if vacuum_variables.i_vacuum_pump_type == 1: pumpn = pumpn * 2.0e0 # Information for costing routine @@ -531,29 +542,29 @@ def vacuum( if output: # Output section - po.oheadr(self.outfile, "Vacuum System") + process_output.oheadr(self.outfile, "Vacuum System") - po.ocmmnt(self.outfile, "Pumpdown to Base Pressure :") - po.oblnkl(self.outfile) - po.ovarre( + process_output.ocmmnt(self.outfile, "Pumpdown to Base Pressure :") + process_output.oblnkl(self.outfile) + process_output.ovarre( self.outfile, "First wall outgassing rate (Pa m/s)", "(outgrat_fw)", - vacv.outgrat_fw, + vacuum_variables.outgrat_fw, ) - po.ovarre( + process_output.ovarre( self.outfile, "Total outgassing load (Pa m3/s)", "(ogas)", ogas, "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "Base pressure required (Pa)", "(pres_vv_chamber_base)", - vacv.pres_vv_chamber_base, + vacuum_variables.pres_vv_chamber_base, ) - po.ovarre( + process_output.ovarre( self.outfile, "Required N2 pump speed (m3/s)", "(s(1))", s[0], "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "N2 pump speed provided (m3/s)", "(snet(1))", @@ -561,44 +572,44 @@ def vacuum( "OP ", ) - po.osubhd(self.outfile, "Pumpdown between Burns :") - po.ovarre( + process_output.osubhd(self.outfile, "Pumpdown between Burns :") + process_output.ovarre( self.outfile, "Plasma chamber volume (m3)", "(volume)", volume, "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "Chamber pressure after burn (Pa)", "(pend)", pend, "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "Chamber pressure before burn (Pa)", "(pstart)", pstart ) - po.ovarin( + process_output.ovarin( self.outfile, "Allowable pumping time switch", "(i_vac_pump_dwell)", - vacv.i_vac_pump_dwell, + vacuum_variables.i_vac_pump_dwell, ) - po.ovarre( + process_output.ovarre( self.outfile, "Dwell time between burns (s)", "(t_plant_pulse_dwell.)", t_plant_pulse_dwell, ) - po.ovarre( + process_output.ovarre( self.outfile, "CS ramp-up time burns (s)", "(t_plant_pulse_coil_precharge.)", - tv.t_plant_pulse_coil_precharge, + times_variables.t_plant_pulse_coil_precharge, ) - po.ovarre( + process_output.ovarre( self.outfile, "Allowable pumping time between burns (s)", "(tpump)", tpump, ) - po.ovarre( + process_output.ovarre( self.outfile, "Required D-T pump speed (m3/s)", "(s(2))", s[1], "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "D-T pump speed provided (m3/s)", "(snet(2))", @@ -606,24 +617,24 @@ def vacuum( "OP ", ) - po.osubhd(self.outfile, "Helium Ash Removal :") - po.ovarre( + process_output.osubhd(self.outfile, "Helium Ash Removal :") + process_output.ovarre( self.outfile, "Divertor chamber gas pressure (Pa)", "(pres_div_chamber_burn)", - vacv.pres_div_chamber_burn, + vacuum_variables.pres_div_chamber_burn, ) - po.ovarre( + process_output.ovarre( self.outfile, "Helium gas fraction in divertor chamber", "(fhe)", fhe, "OP ", ) - po.ovarre( + process_output.ovarre( self.outfile, "Required helium pump speed (m3/s)", "(s(3))", s[2], "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "Helium pump speed provided (m3/s)", "(snet(3))", @@ -631,12 +642,14 @@ def vacuum( "OP ", ) - po.osubhd(self.outfile, "D-T Removal at Fuelling Rate :") - po.ovarre(self.outfile, "D-T fuelling rate (kg/s)", "(frate)", frate, "OP ") - po.ovarre( + process_output.osubhd(self.outfile, "D-T Removal at Fuelling Rate :") + process_output.ovarre( + self.outfile, "D-T fuelling rate (kg/s)", "(frate)", frate, "OP " + ) + process_output.ovarre( self.outfile, "Required D-T pump speed (m3/s)", "(s(4))", s[3], "OP " ) - po.ovarre( + process_output.ovarre( self.outfile, "D-T pump speed provided (m3/s)", "(snet(4))", @@ -645,47 +658,69 @@ def vacuum( ) if nflag == 1: - po.oblnkl(self.outfile) - po.ocmmnt(self.outfile, "Vacuum pumping ducts are space limited.") - po.ocmmnt(self.outfile, f"Maximum duct diameter is only {d1max} m") - po.ocmmnt(self.outfile, "Conductance is inadequate.") - po.oblnkl(self.outfile) + process_output.oblnkl(self.outfile) + process_output.ocmmnt( + self.outfile, "Vacuum pumping ducts are space limited." + ) + process_output.ocmmnt( + self.outfile, f"Maximum duct diameter is only {d1max} m" + ) + process_output.ocmmnt(self.outfile, "Conductance is inadequate.") + process_output.oblnkl(self.outfile) i_fw_blkt_shared_coolant = ( - "cryo " if vacv.i_vacuum_pump_type == 1 else "turbo" + "cryo " if vacuum_variables.i_vacuum_pump_type == 1 else "turbo" ) - po.oblnkl(self.outfile) - po.ocmmnt(self.outfile, "The vacuum pumping system size is governed by the") + process_output.oblnkl(self.outfile) + process_output.ocmmnt( + self.outfile, "The vacuum pumping system size is governed by the" + ) if imax == 1: - po.ocmmnt(self.outfile, "requirements for pumpdown to base pressure.") + process_output.ocmmnt( + self.outfile, "requirements for pumpdown to base pressure." + ) elif imax == 2: - po.ocmmnt(self.outfile, "requirements for pumpdown between burns.") + process_output.ocmmnt( + self.outfile, "requirements for pumpdown between burns." + ) elif imax == 3: - po.ocmmnt(self.outfile, "requirements for helium ash removal.") + process_output.ocmmnt( + self.outfile, "requirements for helium ash removal." + ) else: - po.ocmmnt(self.outfile, "requirements for D-T removal at fuelling rate.") + process_output.ocmmnt( + self.outfile, "requirements for D-T removal at fuelling rate." + ) - po.oblnkl(self.outfile) - po.ovarin(self.outfile, "Number of large pump ducts", "(nduct)", nduct) - po.ovarre( + process_output.oblnkl(self.outfile) + process_output.ovarin( + self.outfile, "Number of large pump ducts", "(nduct)", nduct + ) + process_output.ovarre( self.outfile, "Passage diameter, divertor to ducts (m)", "(d(imax))", d[imax], "OP ", ) - po.ovarre(self.outfile, "Passage length (m)", "(l1)", l1, "OP ") - po.ovarre(self.outfile, "Diameter of ducts (m)", "(dout)", dout, "OP ") + process_output.ovarre(self.outfile, "Passage length (m)", "(l1)", l1, "OP ") + process_output.ovarre( + self.outfile, "Diameter of ducts (m)", "(dout)", dout, "OP " + ) - po.ovarre( + process_output.ovarre( self.outfile, "Duct length, divertor to elbow (m)", "(l2)", l2, "OP " ) - po.ovarre(self.outfile, "Duct length, elbow to pumps (m)", "(l3)", l3) - po.ovarre(self.outfile, "Number of pumps", "(pumpn)", pumpn, "OP ") - po.oblnkl(self.outfile) - po.ocmmnt( + process_output.ovarre( + self.outfile, "Duct length, elbow to pumps (m)", "(l3)", l3 + ) + process_output.ovarre( + self.outfile, "Number of pumps", "(pumpn)", pumpn, "OP " + ) + process_output.oblnkl(self.outfile) + process_output.ocmmnt( self.outfile, f"The vacuum system uses {i_fw_blkt_shared_coolant} pumps.", ) @@ -701,17 +736,17 @@ def __init__(self) -> None: def run(self) -> None: blanket_library.dz_vv_half = self.calculate_vessel_half_height( - z_tf_inside_half=buv.z_tf_inside_half, - dz_shld_vv_gap=buv.dz_shld_vv_gap, - dz_vv_lower=buv.dz_vv_lower, - n_divertors=dv.n_divertors, - dz_blkt_upper=buv.dz_blkt_upper, - dz_shld_upper=buv.dz_shld_upper, - z_plasma_xpoint_upper=buv.z_plasma_xpoint_upper, - dr_fw_plasma_gap_inboard=buv.dr_fw_plasma_gap_inboard, - dr_fw_plasma_gap_outboard=buv.dr_fw_plasma_gap_outboard, - dr_fw_inboard=buv.dr_fw_inboard, - dr_fw_outboard=buv.dr_fw_outboard, + z_tf_inside_half=build_variables.z_tf_inside_half, + dz_shld_vv_gap=build_variables.dz_shld_vv_gap, + dz_vv_lower=build_variables.dz_vv_lower, + n_divertors=divertor_variables.n_divertors, + dz_blkt_upper=build_variables.dz_blkt_upper, + dz_shld_upper=build_variables.dz_shld_upper, + z_plasma_xpoint_upper=build_variables.z_plasma_xpoint_upper, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_outboard=build_variables.dr_fw_outboard, ) # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: @@ -720,13 +755,13 @@ def run(self) -> None: blanket_library.vol_vv_outboard, fwbs_variables.vol_vv, ) = self.calculate_dshaped_vessel_volumes( - r_shld_inboard_inner=buv.r_shld_inboard_inner, - r_shld_outboard_outer=buv.r_shld_outboard_outer, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + r_shld_outboard_outer=build_variables.r_shld_outboard_outer, dz_vv_half=blanket_library.dz_vv_half, - dr_vv_inboard=buv.dr_vv_inboard, - dr_vv_outboard=buv.dr_vv_outboard, - dz_vv_upper=buv.dz_vv_upper, - dz_vv_lower=buv.dz_vv_lower, + dr_vv_inboard=build_variables.dr_vv_inboard, + dr_vv_outboard=build_variables.dr_vv_outboard, + dz_vv_upper=build_variables.dz_vv_upper, + dz_vv_lower=build_variables.dz_vv_lower, ) else: ( @@ -734,16 +769,16 @@ def run(self) -> None: blanket_library.vol_vv_outboard, fwbs_variables.vol_vv, ) = self.calculate_elliptical_vessel_volumes( - rmajor=pv.rmajor, - rminor=pv.rminor, - triang=pv.triang, - r_shld_inboard_inner=buv.r_shld_inboard_inner, - r_shld_outboard_outer=buv.r_shld_outboard_outer, + rmajor=physics_variables.rmajor, + rminor=physics_variables.rminor, + triang=physics_variables.triang, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + r_shld_outboard_outer=build_variables.r_shld_outboard_outer, dz_vv_half=blanket_library.dz_vv_half, - dr_vv_inboard=buv.dr_vv_inboard, - dr_vv_outboard=buv.dr_vv_outboard, - dz_vv_upper=buv.dz_vv_upper, - dz_vv_lower=buv.dz_vv_lower, + dr_vv_inboard=build_variables.dr_vv_inboard, + dr_vv_outboard=build_variables.dr_vv_outboard, + dz_vv_upper=build_variables.dz_vv_upper, + dz_vv_lower=build_variables.dz_vv_lower, ) # Apply vacuum vessel coverage factor @@ -751,8 +786,8 @@ def run(self) -> None: # changes in the same location. fwbs_variables.vol_vv = fwbs_variables.fvoldw * fwbs_variables.vol_vv + @staticmethod def calculate_vessel_half_height( - self, z_tf_inside_half: float, dz_shld_vv_gap: float, dz_vv_lower: float, @@ -786,8 +821,8 @@ def calculate_vessel_half_height( # Average of top and bottom (m) return 0.5 * (z_top + z_bottom) + @staticmethod def calculate_dshaped_vessel_volumes( - self, r_shld_inboard_inner: float, r_shld_outboard_outer: float, dz_vv_half: float, @@ -816,8 +851,8 @@ def calculate_dshaped_vessel_volumes( return vol_vv_inboard, vol_vv_outboard, vol_vv + @staticmethod def calculate_elliptical_vessel_volumes( - self, rmajor: float, rminor: float, triang: float, diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index 1074b101ab..24eb8a2524 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -537,7 +537,6 @@ class DshapedComponentParam(NamedTuple): dz_blkt_half: Any = None dz_shld_half: Any = None dz_vv_half: Any = None - icomponent: Any = None expected_a_blkt_inboard_surface: Any = None expected_a_blkt_outboard_surface: Any = None expected_a_blkt_total_surface: Any = None @@ -594,7 +593,6 @@ class DshapedComponentParam(NamedTuple): dz_blkt_half=8.25, dz_shld_half=8.75, dz_vv_half=9.4349999999999987, - icomponent=0, expected_a_blkt_inboard_surface=196.97785938008002, expected_a_blkt_outboard_surface=852.24160940262459, expected_a_blkt_total_surface=1049.2194687827046, @@ -745,7 +743,7 @@ def test_dshaped_component(dshapedcomponentparam, monkeypatch, blanket_library_f ) monkeypatch.setattr(blanket_library, "dz_vv_half", dshapedcomponentparam.dz_vv_half) - blanket_library_fixture.dshaped_component(dshapedcomponentparam.icomponent) + blanket_library_fixture.dshaped_component() assert build_variables.a_blkt_inboard_surface == pytest.approx( dshapedcomponentparam.expected_a_blkt_inboard_surface @@ -974,7 +972,7 @@ def test_elliptical_component( blanket_library, "dz_shld_half", ellipticalcomponentparam.dz_shld_half ) - blanket_library_fixture.elliptical_component(ellipticalcomponentparam.icomponent) + blanket_library_fixture.elliptical_component() assert build_variables.a_blkt_inboard_surface == pytest.approx( ellipticalcomponentparam.expected_a_blkt_inboard_surface From dde3844e3b79538884a38f4deb01d223d8b6e7fd Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 09:36:13 +0000 Subject: [PATCH 24/35] Add vacuum vessel mass calculation to VacuumVessel class --- process/cryostat.py | 3 --- process/vacuum.py | 3 +++ tests/unit/test_cryostat.py | 5 ----- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/process/cryostat.py b/process/cryostat.py index ab4951d82a..754ae6d5aa 100644 --- a/process/cryostat.py +++ b/process/cryostat.py @@ -80,9 +80,6 @@ def external_cryo_geometry() -> None: * (build_variables.dr_cryostat + fwbs_variables.z_cryostat_half_inside) ) - (fwbs_variables.vol_cryostat_internal) - # Vacuum vessel mass (kg) - fwbs_variables.m_vv = fwbs_variables.vol_vv * fwbs_variables.den_steel - # Sum of internal vacuum vessel and cryostat masses (kg) fwbs_variables.dewmkg = ( fwbs_variables.vol_vv + fwbs_variables.vol_cryostat diff --git a/process/vacuum.py b/process/vacuum.py index 9a2d3a64a3..477aef0eae 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -786,6 +786,9 @@ def run(self) -> None: # changes in the same location. fwbs_variables.vol_vv = fwbs_variables.fvoldw * fwbs_variables.vol_vv + # Vacuum vessel mass (kg) + fwbs_variables.m_vv = fwbs_variables.vol_vv * fwbs_variables.den_steel + @staticmethod def calculate_vessel_half_height( z_tf_inside_half: float, diff --git a/tests/unit/test_cryostat.py b/tests/unit/test_cryostat.py index 133c07c410..a23cb9c300 100644 --- a/tests/unit/test_cryostat.py +++ b/tests/unit/test_cryostat.py @@ -43,7 +43,6 @@ class ExternalCryoGeometryParam(NamedTuple): expected_r_cryostat_inboard: Any = None expected_z_cryostat_half_inside: Any = None expected_vol_cryostat: Any = None - expected_vvmass: Any = None expected_dewmkg: Any = None expected_dz_tf_cryostat: Any = None expected_dz_pf_cryostat: Any = None @@ -130,7 +129,6 @@ class ExternalCryoGeometryParam(NamedTuple): expected_r_cryostat_inboard=17.805470903073743, expected_z_cryostat_half_inside=15.259637557000296, expected_vol_cryostat=818.1630389343372, - expected_vvmass=7927043.4756686538, expected_dewmkg=14308715.179356484, expected_dz_tf_cryostat=5.514694530398824, expected_dz_pf_cryostat=5.3441455565624985, @@ -207,9 +205,6 @@ def test_external_cryo_geometry( assert fwbs_variables.vol_cryostat == pytest.approx( externalcryogeometryparam.expected_vol_cryostat ) - assert fwbs_variables.m_vv == pytest.approx( - externalcryogeometryparam.expected_vvmass - ) assert fwbs_variables.dewmkg == pytest.approx( externalcryogeometryparam.expected_dewmkg ) From 6280dc6cb5b6e7246175e287a9cbd765eccaa9d2 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 13:31:36 +0000 Subject: [PATCH 25/35] Add docstring to vacuum vessel volume calculation method --- process/vacuum.py | 1 + 1 file changed, 1 insertion(+) diff --git a/process/vacuum.py b/process/vacuum.py index 477aef0eae..4c452ea0f2 100644 --- a/process/vacuum.py +++ b/process/vacuum.py @@ -867,6 +867,7 @@ def calculate_elliptical_vessel_volumes( dz_vv_upper: float, dz_vv_lower: float, ) -> tuple[float, float, float]: + """Calculate volumes of elliptical vacuum vessel segments""" # Major radius to centre of inboard and outboard ellipses (m) # (coincident in radius with top of plasma) r_1 = rmajor - rminor * triang From c76772ddeb7f6c06ea9517565c8b94e49411d0df Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 13:59:27 +0000 Subject: [PATCH 26/35] =?UTF-8?q?=F0=9F=94=84=20Rename=20`component=5Fhalf?= =?UTF-8?q?=5Fheight`=20method=20to=20`calculate=5Fblkt=5Fhalf=5Fheight`?= =?UTF-8?q?=20for=20clarity=20and=20update=20references=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- process/blanket_library.py | 4 ++-- tests/unit/test_blanket_library.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index aa447c98fa..76991f7f9d 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -54,7 +54,7 @@ def component_volumes(self): # Calculate half-height # Blanket - blanket_library.dz_blkt_half = self.component_half_height(icomponent=0) + blanket_library.dz_blkt_half = self.calculate_blkt_half_height(icomponent=0) # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: @@ -67,7 +67,7 @@ def component_volumes(self): # Apply coverage factors to volumes and surface areas self.apply_coverage_factors() - def component_half_height(self, icomponent: int): + def calculate_blkt_half_height(self, icomponent: int): """Calculate the blanket, shield or vacuum vessel half-height Based on blanket_half_height, shield_half_height, vv_half_height original author: J. Morris, CCFE, Culham Science Centre diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index 24eb8a2524..cb5a6c07bd 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -422,7 +422,7 @@ class ComponentHalfHeightParam(NamedTuple): ), ), ) -def test_component_half_height( +def test_calculate_blkt_half_height( componenthalfheightparam, monkeypatch, blanket_library_fixture ): """ @@ -494,7 +494,7 @@ def test_component_half_height( divertor_variables, "dz_divertor", componenthalfheightparam.dz_divertor ) - half_height = blanket_library_fixture.component_half_height( + half_height = blanket_library_fixture.calculate_blkt_half_height( componenthalfheightparam.icomponent ) From 602eedea4a13fe5898eef2de995443cb889cbf53 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 14:16:22 +0000 Subject: [PATCH 27/35] Refactor `calculate_blkt_half_height` method to accept parameters directly instead of using an `icomponent` switch; update corresponding tests for consistency. --- process/blanket_library.py | 85 ++++++++++++++++++++++-------- tests/unit/test_blanket_library.py | 85 +++++------------------------- 2 files changed, 76 insertions(+), 94 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index 76991f7f9d..a11cbefbdc 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -49,12 +49,21 @@ def component_volumes(self): author: J. Morris, CCFE, Culham Science Centre Calculate the blanket, shield, vacuum vessel and cryostat volumes """ - # N.B. icomponent is a switch used to specify selected component: blanket=0, sheild=1, vacuum vessel=2 - # Replaced seperate subroutines for blnkt, shld and vv with fuction/subroutine with icomponent switch. # Calculate half-height # Blanket - blanket_library.dz_blkt_half = self.calculate_blkt_half_height(icomponent=0) + blanket_library.dz_blkt_half = self.calculate_blkt_half_height( + z_plasma_xpoint_lower=build_variables.z_plasma_xpoint_lower, + dz_xpoint_divertor=build_variables.dz_xpoint_divertor, + dz_divertor=divertor_variables.dz_divertor, + z_plasma_xpoint_upper=build_variables.z_plasma_xpoint_upper, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + dz_blkt_upper=build_variables.dz_blkt_upper, + n_divertors=divertor_variables.n_divertors, + ) # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: @@ -67,37 +76,67 @@ def component_volumes(self): # Apply coverage factors to volumes and surface areas self.apply_coverage_factors() - def calculate_blkt_half_height(self, icomponent: int): - """Calculate the blanket, shield or vacuum vessel half-height - Based on blanket_half_height, shield_half_height, vv_half_height - original author: J. Morris, CCFE, Culham Science Centre - author: G. Graham, CCFE, Culham Science Centre + @staticmethod + def calculate_blkt_half_height( + z_plasma_xpoint_lower: float, + dz_xpoint_divertor: float, + dz_divertor: float, + z_plasma_xpoint_upper: float, + dr_fw_plasma_gap_inboard: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_inboard: float, + dr_fw_outboard: float, + dz_blkt_upper: float, + n_divertors: int, + ) -> float: + """ + Calculate the blanket half-height based on plasma and component geometry. + + :param z_plasma_xpoint_lower: Lower vertical position of the plasma x-point (m) + :type z_plasma_xpoint_lower: float + :param dz_xpoint_divertor: Vertical distance from x-point to divertor (m) + :type dz_xpoint_divertor: float + :param dz_divertor: Vertical thickness of the divertor (m) + :type dz_divertor: float + :param z_plasma_xpoint_upper: Upper vertical position of the plasma x-point (m) + :type z_plasma_xpoint_upper: float + :param dr_fw_plasma_gap_inboard: Radial gap between first wall and plasma on inboard side (m) + :type dr_fw_plasma_gap_inboard: float + :param dr_fw_plasma_gap_outboard: Radial gap between first wall and plasma on outboard side (m) + :type dr_fw_plasma_gap_outboard: float + :param dr_fw_inboard: Radial thickness of the first wall on inboard side (m) + :type dr_fw_inboard: float + :param dr_fw_outboard: Radial thickness of the first wall on outboard side (m) + :type dr_fw_outboard: float + :param dz_blkt_upper: Vertical thickness of the upper blanket (m) + :type dz_blkt_upper: float + :param n_divertors: Number of divertors (1 for single null, 2 for double null) + :type n_divertors: int + + :return: Calculated blanket half-height (m) + :rtype: float """ # Calculate component internal lower half-height (m) # Blanket - if icomponent == 0: - hbot = ( - build_variables.z_plasma_xpoint_lower - + build_variables.dz_xpoint_divertor - + divertor_variables.dz_divertor - - build_variables.dz_blkt_upper - ) + z_bottom = ( + z_plasma_xpoint_lower + dz_xpoint_divertor + dz_divertor - dz_blkt_upper + ) # Calculate component internal upper half-height (m) # If a double null machine then symmetric - if divertor_variables.n_divertors == 2: - htop = hbot + if n_divertors == 2: + z_top = z_bottom else: # Blanket - htop = build_variables.z_plasma_xpoint_upper + 0.5 * ( - build_variables.dr_fw_plasma_gap_inboard - + build_variables.dr_fw_plasma_gap_outboard - + build_variables.dr_fw_inboard - + build_variables.dr_fw_outboard + z_top = z_plasma_xpoint_upper + 0.5 * ( + dr_fw_plasma_gap_inboard + + dr_fw_plasma_gap_outboard + + dr_fw_inboard + + dr_fw_outboard ) # Average of top and bottom (m) - return 0.5 * (htop + hbot) + return 0.5 * (z_top + z_bottom) def dshaped_component(self): """Calculate component surface area and volume using dshaped scheme diff --git a/tests/unit/test_blanket_library.py b/tests/unit/test_blanket_library.py index cb5a6c07bd..cab860a56c 100644 --- a/tests/unit/test_blanket_library.py +++ b/tests/unit/test_blanket_library.py @@ -392,7 +392,6 @@ class ComponentHalfHeightParam(NamedTuple): z_plasma_xpoint_upper: Any = None n_divertors: Any = None dz_divertor: Any = None - icomponent: Any = None expected_icomponent: Any = None expected_half_height: Any = None @@ -416,86 +415,30 @@ class ComponentHalfHeightParam(NamedTuple): z_plasma_xpoint_upper=4.93333333333333333, n_divertors=1, dz_divertor=0.62000000000000011, - icomponent=0, - expected_icomponent=0, expected_half_height=5.9532752487304119, ), ), ) -def test_calculate_blkt_half_height( - componenthalfheightparam, monkeypatch, blanket_library_fixture -): +def test_calculate_blkt_half_height(componenthalfheightparam, blanket_library_fixture): """ - Automatically generated Regression Unit Test for component_half_height. + Regression Unit Test for component_half_height. - This test was generated using data from tests/regression/input_files/large_tokamak.IN.DAT. + This test was generated using data from large_tokamak.IN.DAT. - :param componenthalfheightparam: the data used to mock and assert in this test. + :param componenthalfheightparam: the data used in this test. :type componenthalfheightparam: componenthalfheightparam - - :param monkeypatch: pytest fixture used to mock module/class variables - :type monkeypatch: _pytest.monkeypatch.monkeypatch """ - monkeypatch.setattr( - build_variables, "z_tf_inside_half", componenthalfheightparam.z_tf_inside_half - ) - monkeypatch.setattr( - build_variables, - "dz_xpoint_divertor", - componenthalfheightparam.dz_xpoint_divertor, - ) - monkeypatch.setattr( - build_variables, - "dz_shld_vv_gap", - componenthalfheightparam.dz_shld_vv_gap, - ) - monkeypatch.setattr( - build_variables, "dz_blkt_upper", componenthalfheightparam.dz_blkt_upper - ) - monkeypatch.setattr( - build_variables, "dz_shld_upper", componenthalfheightparam.dz_shld_upper - ) - monkeypatch.setattr( - build_variables, - "dr_fw_plasma_gap_inboard", - componenthalfheightparam.dr_fw_plasma_gap_inboard, - ) - monkeypatch.setattr( - build_variables, - "dr_fw_plasma_gap_outboard", - componenthalfheightparam.dr_fw_plasma_gap_outboard, - ) - monkeypatch.setattr( - build_variables, "dr_fw_inboard", componenthalfheightparam.dr_fw_inboard - ) - monkeypatch.setattr( - build_variables, "dr_fw_outboard", componenthalfheightparam.dr_fw_outboard - ) - monkeypatch.setattr( - build_variables, "dz_vv_lower", componenthalfheightparam.dz_vv_lower - ) - monkeypatch.setattr( - build_variables, "dz_vv_upper", componenthalfheightparam.dz_vv_upper - ) - monkeypatch.setattr( - build_variables, - "z_plasma_xpoint_lower", - componenthalfheightparam.z_plasma_xpoint_lower, - ) - monkeypatch.setattr( - build_variables, - "z_plasma_xpoint_upper", - componenthalfheightparam.z_plasma_xpoint_upper, - ) - monkeypatch.setattr( - divertor_variables, "n_divertors", componenthalfheightparam.n_divertors - ) - monkeypatch.setattr( - divertor_variables, "dz_divertor", componenthalfheightparam.dz_divertor - ) - half_height = blanket_library_fixture.calculate_blkt_half_height( - componenthalfheightparam.icomponent + z_plasma_xpoint_lower=componenthalfheightparam.z_plasma_xpoint_lower, + dz_xpoint_divertor=componenthalfheightparam.dz_xpoint_divertor, + dz_divertor=componenthalfheightparam.dz_divertor, + z_plasma_xpoint_upper=componenthalfheightparam.z_plasma_xpoint_upper, + dr_fw_plasma_gap_inboard=componenthalfheightparam.dr_fw_plasma_gap_inboard, + dr_fw_plasma_gap_outboard=componenthalfheightparam.dr_fw_plasma_gap_outboard, + dr_fw_inboard=componenthalfheightparam.dr_fw_inboard, + dr_fw_outboard=componenthalfheightparam.dr_fw_outboard, + dz_blkt_upper=componenthalfheightparam.dz_blkt_upper, + n_divertors=componenthalfheightparam.n_divertors, ) assert half_height == pytest.approx(componenthalfheightparam.expected_half_height) From 06e4b94a513f3fcd49536efef9c47bbb596c32ae Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 14:52:31 +0000 Subject: [PATCH 28/35] Add methods to calculate D-shaped blanket areas and volumes --- process/blanket_library.py | 169 ++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index a11cbefbdc..874eb651a2 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -67,7 +67,39 @@ def component_volumes(self): # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: - self.dshaped_component() + ( + build_variables.a_blkt_inboard_surface, + build_variables.a_blkt_outboard_surface, + build_variables.a_blkt_total_surface, + ) = self.calculate_dshaped_blkt_areas( + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + dr_shld_inboard=build_variables.dr_shld_inboard, + dr_blkt_inboard=build_variables.dr_blkt_inboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + rminor=physics_variables.rminor, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + dz_blkt_half=blanket_library.dz_blkt_half, + ) + + ( + fwbs_variables.vol_blkt_inboard, + fwbs_variables.vol_blkt_outboard, + fwbs_variables.vol_blkt_total, + ) = self.calculate_dshaped_blkt_volumes( + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + dr_shld_inboard=build_variables.dr_shld_inboard, + dr_blkt_inboard=build_variables.dr_blkt_inboard, + dr_fw_inboard=build_variables.dr_fw_inboard, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + rminor=physics_variables.rminor, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + dz_blkt_half=blanket_library.dz_blkt_half, + dr_blkt_outboard=build_variables.dr_blkt_outboard, + dz_blkt_upper=build_variables.dz_blkt_upper, + ) # Elliptical blanket and shield else: @@ -182,6 +214,141 @@ def dshaped_component(self): build_variables.dz_blkt_upper, ) + @staticmethod + def calculate_dshaped_blkt_areas( + r_shld_inboard_inner: float, + dr_shld_inboard: float, + dr_blkt_inboard: float, + dr_fw_inboard: float, + dr_fw_plasma_gap_inboard: float, + rminor: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_outboard: float, + dz_blkt_half: float, + ) -> tuple[float, float, float]: + """ + Calculate D-shaped blanket surface areas. + + :param r_shld_inboard_inner: Inner radius of inboard shield (m) + :type r_shld_inboard_inner: float + :param dr_shld_inboard: Thickness of inboard shield (m) + :type dr_shld_inboard: float + :param dr_blkt_inboard: Thickness of inboard blanket (m) + :type dr_blkt_inboard: float + :param dr_fw_inboard: Thickness of inboard first wall (m) + :type dr_fw_inboard: float + :param dr_fw_plasma_gap_inboard: Radial gap between inboard first wall and plasma (m) + :type dr_fw_plasma_gap_inboard: float + :param rminor: Minor radius of the plasma (m) + :type rminor: float + :param dr_fw_plasma_gap_outboard: Radial gap between outboard first wall and plasma (m) + :type dr_fw_plasma_gap_outboard: float + :param dr_fw_outboard: Thickness of outboard first wall (m) + :type dr_fw_outboard: float + :param dz_blkt_half: Half-height of the blanket (m) + :type dz_blkt_half: float + + :return: Tuple containing inboard blanket surface area (m²), outboard blanket surface area (m²), and total blanket surface area (m²) + """ + # Calculate major radius to outer edge of inboard ... + # ... section (m) + r1 = r_shld_inboard_inner + + # ... blanket (m) + + r1 = r1 + dr_shld_inboard + dr_blkt_inboard + # Horizontal distance between inside edges (m) + # i.e. outer radius of inboard part to inner radius of outboard part + + r2 = ( + dr_fw_inboard + + dr_fw_plasma_gap_inboard + + 2.0 * rminor + + dr_fw_plasma_gap_outboard + + dr_fw_outboard + ) + + ( + a_blkt_inboard_surface, + a_blkt_outboard_surface, + a_blkt_total_surface, + ) = dshellarea(rmajor=r1, rminor=r2, zminor=dz_blkt_half) + + return a_blkt_inboard_surface, a_blkt_outboard_surface, a_blkt_total_surface + + @staticmethod + def calculate_dshaped_blkt_volumes( + r_shld_inboard_inner: float, + dr_shld_inboard: float, + dr_blkt_inboard: float, + dr_fw_inboard: float, + dr_fw_plasma_gap_inboard: float, + rminor: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_outboard: float, + dz_blkt_half: float, + dr_blkt_outboard: float, + dz_blkt_upper: float, + ) -> tuple[float, float, float]: + """ + Calculate D-shaped blanket volumes. + + :param r_shld_inboard_inner: Inner radius of inboard shield (m) + :type r_shld_inboard_inner: float + :param dr_shld_inboard: Thickness of inboard shield (m) + :type dr_shld_inboard: float + :param dr_blkt_inboard: Thickness of inboard blanket (m) + :type dr_blkt_inboard: float + :param dr_fw_inboard: Thickness of inboard first wall (m) + :type dr_fw_inboard: float + :param dr_fw_plasma_gap_inboard: Radial gap between inboard first wall and plasma (m) + :type dr_fw_plasma_gap_inboard: float + :param rminor: Minor radius of the plasma (m) + :type rminor: float + :param dr_fw_plasma_gap_outboard: Radial gap between outboard first wall and plasma (m) + :type dr_fw_plasma_gap_outboard: float + :param dr_fw_outboard: Thickness of outboard first wall (m) + :type dr_fw_outboard: float + :param dz_blkt_half: Half-height of the blanket (m) + :type dz_blkt_half: float + :param dr_blkt_outboard: Thickness of outboard blanket (m) + :type dr_blkt_outboard: float + :param dz_blkt_upper: Upper vertical thickness of the blanket (m) + :type dz_blkt_upper: float + + :return: Tuple containing inboard blanket volume (m³), outboard blanket volume (m³), and total blanket volume (m³) + """ + # Calculate major radius to outer edge of inboard ... + # ... section (m) + r1 = r_shld_inboard_inner + + r1 = r1 + dr_shld_inboard + dr_blkt_inboard + # Horizontal distance between inside edges (m) + # i.e. outer radius of inboard part to inner radius of outboard part + + r2 = ( + dr_fw_inboard + + dr_fw_plasma_gap_inboard + + 2.0 * rminor + + dr_fw_plasma_gap_outboard + + dr_fw_outboard + ) + + ( + vol_blkt_inboard, + vol_blkt_outboard, + vol_blkt_total, + ) = dshellvol( + rmajor=r1, + rminor=r2, + zminor=dz_blkt_half, + drin=dr_blkt_inboard, + drout=dr_blkt_outboard, + dz=dz_blkt_upper, + ) + + return vol_blkt_inboard, vol_blkt_outboard, vol_blkt_total + def elliptical_component(self): """Calculate component surface area and volume using elliptical scheme Based on elliptical_blanket, elliptical_shield, elliptical_vv From c354072771df1c646bc215e9e01bcf0d2cfb2799 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 15:13:47 +0000 Subject: [PATCH 29/35] Add methods to calculate elliptical blanket areas and volumes --- process/blanket_library.py | 176 ++++++++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 1 deletion(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index 874eb651a2..ffe43cc7b4 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -103,7 +103,40 @@ def component_volumes(self): # Elliptical blanket and shield else: - self.elliptical_component() + ( + build_variables.a_blkt_inboard_surface, + build_variables.a_blkt_outboard_surface, + build_variables.a_blkt_total_surface, + ) = self.calculate_elliptical_blkt_areas( + rmajor=physics_variables.rmajor, + rminor=physics_variables.rminor, + triang=physics_variables.triang, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + dr_shld_inboard=build_variables.dr_shld_inboard, + dr_blkt_inboard=build_variables.dr_blkt_inboard, + r_shld_outboard_outer=build_variables.r_shld_outboard_outer, + dr_shld_outboard=build_variables.dr_shld_outboard, + dr_blkt_outboard=build_variables.dr_blkt_outboard, + dz_blkt_half=blanket_library.dz_blkt_half, + ) + + ( + fwbs_variables.vol_blkt_inboard, + fwbs_variables.vol_blkt_outboard, + fwbs_variables.vol_blkt_total, + ) = self.calculate_elliptical_blkt_volumes( + rmajor=physics_variables.rmajor, + rminor=physics_variables.rminor, + triang=physics_variables.triang, + r_shld_inboard_inner=build_variables.r_shld_inboard_inner, + dr_shld_inboard=build_variables.dr_shld_inboard, + dr_blkt_inboard=build_variables.dr_blkt_inboard, + r_shld_outboard_outer=build_variables.r_shld_outboard_outer, + dr_shld_outboard=build_variables.dr_shld_outboard, + dr_blkt_outboard=build_variables.dr_blkt_outboard, + dz_blkt_half=blanket_library.dz_blkt_half, + dz_blkt_upper=build_variables.dz_blkt_upper, + ) # Apply coverage factors to volumes and surface areas self.apply_coverage_factors() @@ -349,6 +382,147 @@ def calculate_dshaped_blkt_volumes( return vol_blkt_inboard, vol_blkt_outboard, vol_blkt_total + @staticmethod + def calculate_elliptical_blkt_areas( + rmajor: float, + rminor: float, + triang: float, + r_shld_inboard_inner: float, + dr_shld_inboard: float, + dr_blkt_inboard: float, + r_shld_outboard_outer: float, + dr_shld_outboard: float, + dr_blkt_outboard: float, + dz_blkt_half: float, + ) -> tuple[float, float, float]: + """Calculate elliptical blanket surface areas. + + :param rmajor: Major radius of the plasma (m) + :type rmajor: float + :param rminor: Minor radius of the plasma (m) + :type rminor: float + :param triang: Triangularity of the plasma + :type triang: float + :param r_shld_inboard_inner: Inner radius of inboard shield (m) + :type r_shld_inboard_inner: float + :param dr_shld_inboard: Thickness of inboard shield (m) + :type dr_shld_inboard: float + :param dr_blkt_inboard: Thickness of inboard blanket (m) + :type dr_blkt_inboard: float + :param r_shld_outboard_outer: Outer radius of outboard shield (m) + :type r_shld_outboard_outer: float + :param dr_shld_outboard: Thickness of outboard shield (m) + :type dr_shld_outboard: float + :param dr_blkt_outboard: Thickness of outboard blanket (m) + :type dr_blkt_outboard: float + :param dz_blkt_half: Half-height of the blanket (m) + :type dz_blkt_half: float + + :return: Tuple containing inboard blanket surface area (m²), outboard blanket surface area (m²), and total blanket surface area (m²) + + """ + # Major radius to centre of inboard and outboard ellipses (m) + # (coincident in radius with top of plasma) + r1 = rmajor - rminor * triang + + # Calculate distance between r1 and outer edge of inboard ... + # ... section (m) + r2 = r1 - r_shld_inboard_inner + + r2 = r2 - dr_shld_inboard - dr_blkt_inboard + + # Calculate distance between r1 and inner edge of outboard ... + # ... section (m) + r3 = r_shld_outboard_outer - r1 + + r3 = r3 - dr_shld_outboard - dr_blkt_outboard + + # Calculate surface area, assuming 100% coverage + + ( + a_blkt_inboard_surface, + a_blkt_outboard_surface, + a_blkt_total_surface, + ) = eshellarea(r1, r2, r3, dz_blkt_half) + + return a_blkt_inboard_surface, a_blkt_outboard_surface, a_blkt_total_surface + + @staticmethod + def calculate_elliptical_blkt_volumes( + rmajor: float, + rminor: float, + triang: float, + r_shld_inboard_inner: float, + dr_shld_inboard: float, + dr_blkt_inboard: float, + r_shld_outboard_outer: float, + dr_shld_outboard: float, + dr_blkt_outboard: float, + dz_blkt_half: float, + dz_blkt_upper: float, + ) -> tuple[float, float, float]: + """Calculate elliptical blanket volumes. + + :param rmajor: Major radius of the plasma (m) + :type rmajor: float + :param rminor: Minor radius of the plasma (m) + :type rminor: float + :param triang: Triangularity of the plasma + :type triang: float + :param r_shld_inboard_inner: Inner radius of inboard shield (m) + :type r_shld_inboard_inner: float + :param dr_shld_inboard: Thickness of inboard shield (m) + :type dr_shld_inboard: float + :param dr_blkt_inboard: Thickness of inboard blanket (m) + :type dr_blkt_inboard: float + :param r_shld_outboard_outer: Outer radius of outboard shield (m) + :type r_shld_outboard_outer: float + :param dr_shld_outboard: Thickness of outboard shield (m) + :type dr_shld_outboard: float + :param dr_blkt_outboard: Thickness of outboard blanket (m) + :type dr_blkt_outboard: float + :param dz_blkt_half: Half-height of the blanket (m) + :type dz_blkt_half: float + :param dz_blkt_upper: Upper vertical thickness of the blanket (m) + :type dz_blkt_upper: float + + :return: Tuple containing inboard blanket volume (m³), outboard blanket volume (m³), and total blanket volume (m³) + + """ + # Major radius to centre of inboard and outboard ellipses (m) + # (coincident in radius with top of plasma) + r1 = rmajor - rminor * triang + + # Calculate distance between r1 and outer edge of inboard ... + # ... section (m) + r2 = r1 - r_shld_inboard_inner + + r2 = r2 - dr_shld_inboard - dr_blkt_inboard + + # Calculate distance between r1 and inner edge of outboard ... + # ... section (m) + r3 = r_shld_outboard_outer - r1 + + r3 = r3 - dr_shld_outboard - dr_blkt_outboard + + # Calculate surface area, assuming 100% coverage + + ( + vol_blkt_inboard, + vol_blkt_outboard, + vol_blkt_total, + ) = eshellvol( + rshell=r1, + rmini=r2, + rmino=r3, + zminor=dz_blkt_half, + drin=dr_blkt_inboard, + drout=dr_blkt_outboard, + dz=dz_blkt_upper, + ) + + return vol_blkt_inboard, vol_blkt_outboard, vol_blkt_total + def elliptical_component(self): """Calculate component surface area and volume using elliptical scheme Based on elliptical_blanket, elliptical_shield, elliptical_vv From 17b91cfc3418a283ed5a8cde0badafc04bf2d5af Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 16:11:31 +0000 Subject: [PATCH 30/35] Add `plot_blkt_structure` function to visualize blanket and first wall cross-section --- process/io/plot_proc.py | 115 ++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 40 deletions(-) diff --git a/process/io/plot_proc.py b/process/io/plot_proc.py index 95a6f80adb..6f8828ac7c 100644 --- a/process/io/plot_proc.py +++ b/process/io/plot_proc.py @@ -12743,6 +12743,80 @@ def plot_inequality_constraint_equations(axis: plt.Axes, m_file: mf.MFile, scan: axis.set_xticklabels([]) +def plot_blkt_structure( + ax: plt.Axes, + m_file: mf.MFile, + scan: int, + radial_build: dict[str, float], + colour_scheme: Literal[1, 2], +): + """Plot the BLKT structure on the given axis.""" + + rmajor = m_file.get("rmajor", scan=scan) + + plot_blanket(ax, m_file, scan, radial_build, colour_scheme) + plot_firstwall(ax, m_file, scan, radial_build, colour_scheme) + ax.set_xlabel("Radial position [m]") + ax.set_ylabel("Vertical position [m]") + ax.set_title("Blanket and First Wall Poloidal Cross-Section") + ax.minorticks_on() + ax.grid(which="minor", linestyle=":", linewidth=0.5, alpha=0.5) + # Plot major radius line (vertical dashed line at rmajor) + ax.axvline( + m_file.get("rminor", scan=scan), + color="black", + linestyle="--", + linewidth=1.5, + label="Major Radius $R_0$", + ) + # Plot a horizontal line at dz_blkt_half (blanket half height) + dz_blkt_half = m_file.get("dz_blkt_half", scan=scan) + ax.axhline( + dz_blkt_half, + color="purple", + linestyle="--", + linewidth=1.5, + label="Blanket Half Height", + ) + ax.axhline( + -dz_blkt_half, + color="purple", + linestyle="--", + linewidth=1.5, + label="Blanket Half Height", + ) + + ax.annotate( + "", + xy=(rmajor, dz_blkt_half), + xytext=(rmajor, -dz_blkt_half), + arrowprops={"arrowstyle": "<->", "color": "black"}, + ) + + # Add a label for the internal coil width + ax.text( + rmajor, + 0.0, + f"{2 * dz_blkt_half:.3f} m", + fontsize=7, + color="black", + rotation=270, + verticalalignment="center", + horizontalalignment="center", + bbox={"boxstyle": "round", "facecolor": "pink", "alpha": 1.0}, + zorder=101, # Ensure label is on top of all plots + ) + + # Plot midplane line (horizontal dashed line at Z=0) + ax.axhline( + 0.0, + color="black", + linestyle="--", + linewidth=1.5, + label="Midplane", + ) + + def main_plot( figs: list[Axes], m_file: mf.MFile, @@ -13012,46 +13086,7 @@ def main_plot( plot_blkt_pipe_bends(figs[27], m_file, scan) ax_blanket = figs[27].add_subplot(122, aspect="equal") - plot_blanket(ax_blanket, m_file, scan, radial_build, colour_scheme) - plot_firstwall(ax_blanket, m_file, scan, radial_build, colour_scheme) - ax_blanket.set_xlabel("Radial position [m]") - ax_blanket.set_ylabel("Vertical position [m]") - ax_blanket.set_title("Blanket and First Wall Poloidal Cross-Section") - ax_blanket.minorticks_on() - ax_blanket.grid(which="minor", linestyle=":", linewidth=0.5, alpha=0.5) - # Plot major radius line (vertical dashed line at rmajor) - ax_blanket.axvline( - m_file.get("rminor", scan=scan), - color="black", - linestyle="--", - linewidth=1.5, - label="Major Radius $R_0$", - ) - # Plot a horizontal line at dz_blkt_half (blanket half height) - dz_blkt_half = m_file.get("dz_blkt_half", scan=scan) - ax_blanket.axhline( - dz_blkt_half, - color="purple", - linestyle="--", - linewidth=1.5, - label="Blanket Half Height", - ) - ax_blanket.axhline( - -dz_blkt_half, - color="purple", - linestyle="--", - linewidth=1.5, - label="Blanket Half Height", - ) - - # Plot midplane line (horizontal dashed line at Z=0) - ax_blanket.axhline( - 0.0, - color="black", - linestyle="--", - linewidth=1.5, - label="Midplane", - ) + plot_blkt_structure(ax_blanket, m_file, scan, radial_build, colour_scheme) plot_main_power_flow( figs[28].add_subplot(111, aspect="equal"), m_file, scan, figs[28] From 0343e87bfd2449406c687530666f63569c28b000 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 16:24:43 +0000 Subject: [PATCH 31/35] Refactor blanket area and volume calculations to include full coverage variables for D-shaped and elliptical shapes --- process/blanket_library.py | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index ffe43cc7b4..943db2aa06 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -68,9 +68,9 @@ def component_volumes(self): # D-shaped blanket and shield if physics_variables.itart == 1 or fwbs_variables.i_fw_blkt_vv_shape == 1: ( - build_variables.a_blkt_inboard_surface, - build_variables.a_blkt_outboard_surface, - build_variables.a_blkt_total_surface, + build_variables.a_blkt_inboard_surface_full_coverage, + build_variables.a_blkt_outboard_surface_full_coverage, + build_variables.a_blkt_total_surface_full_coverage, ) = self.calculate_dshaped_blkt_areas( r_shld_inboard_inner=build_variables.r_shld_inboard_inner, dr_shld_inboard=build_variables.dr_shld_inboard, @@ -84,9 +84,9 @@ def component_volumes(self): ) ( - fwbs_variables.vol_blkt_inboard, - fwbs_variables.vol_blkt_outboard, - fwbs_variables.vol_blkt_total, + fwbs_variables.vol_blkt_inboard_full_coverage, + fwbs_variables.vol_blkt_outboard_full_coverage, + fwbs_variables.vol_blkt_total_full_coverage, ) = self.calculate_dshaped_blkt_volumes( r_shld_inboard_inner=build_variables.r_shld_inboard_inner, dr_shld_inboard=build_variables.dr_shld_inboard, @@ -104,9 +104,9 @@ def component_volumes(self): # Elliptical blanket and shield else: ( - build_variables.a_blkt_inboard_surface, - build_variables.a_blkt_outboard_surface, - build_variables.a_blkt_total_surface, + build_variables.a_blkt_inboard_surface_full_coverage, + build_variables.a_blkt_outboard_surface_full_coverage, + build_variables.a_blkt_total_surface_full_coverage, ) = self.calculate_elliptical_blkt_areas( rmajor=physics_variables.rmajor, rminor=physics_variables.rminor, @@ -121,9 +121,9 @@ def component_volumes(self): ) ( - fwbs_variables.vol_blkt_inboard, - fwbs_variables.vol_blkt_outboard, - fwbs_variables.vol_blkt_total, + fwbs_variables.vol_blkt_inboard_full_coverage, + fwbs_variables.vol_blkt_outboard_full_coverage, + fwbs_variables.vol_blkt_total_full_coverage, ) = self.calculate_elliptical_blkt_volumes( rmajor=physics_variables.rmajor, rminor=physics_variables.rminor, @@ -581,42 +581,43 @@ def apply_coverage_factors(self): if divertor_variables.n_divertors == 2: # double null configuration build_variables.a_blkt_outboard_surface = ( - build_variables.a_blkt_total_surface + build_variables.a_blkt_total_surface_full_coverage * ( 1.0 - 2.0 * fwbs_variables.f_ster_div_single - fwbs_variables.f_a_fw_outboard_hcd ) - - build_variables.a_blkt_inboard_surface + - build_variables.a_blkt_inboard_surface_full_coverage ) else: # single null configuration build_variables.a_blkt_outboard_surface = ( - build_variables.a_blkt_total_surface + build_variables.a_blkt_total_surface_full_coverage * ( 1.0 - fwbs_variables.f_ster_div_single - fwbs_variables.f_a_fw_outboard_hcd ) - - build_variables.a_blkt_inboard_surface + - build_variables.a_blkt_inboard_surface_full_coverage ) build_variables.a_blkt_total_surface = ( - build_variables.a_blkt_inboard_surface + build_variables.a_blkt_inboard_surface_full_coverage + build_variables.a_blkt_outboard_surface ) fwbs_variables.vol_blkt_outboard = ( - fwbs_variables.vol_blkt_total + fwbs_variables.vol_blkt_total_full_coverage * ( 1.0 - fwbs_variables.f_ster_div_single - fwbs_variables.f_a_fw_outboard_hcd ) - - fwbs_variables.vol_blkt_inboard + - fwbs_variables.vol_blkt_inboard_full_coverage ) fwbs_variables.vol_blkt_total = ( - fwbs_variables.vol_blkt_inboard + fwbs_variables.vol_blkt_outboard + fwbs_variables.vol_blkt_inboard_full_coverage + + fwbs_variables.vol_blkt_outboard ) def primary_coolant_properties(self, output: bool): From 8fefceef9f932a9320c0b610b92916371a9249d4 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 17:05:39 +0000 Subject: [PATCH 32/35] Add output function for blanket volumes and areas in blanket_library; integrate into DCLL and CCFE_HCPB classes --- process/blanket_library.py | 83 ++++++++++++++++++++++++++++++++++++++ process/dcll.py | 2 + process/hcpb.py | 3 ++ 3 files changed, 88 insertions(+) diff --git a/process/blanket_library.py b/process/blanket_library.py index 943db2aa06..53508101ce 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -615,11 +615,94 @@ def apply_coverage_factors(self): ) - fwbs_variables.vol_blkt_inboard_full_coverage ) + fwbs_variables.vol_blkt_inboard = fwbs_variables.vol_blkt_inboard_full_coverage + fwbs_variables.vol_blkt_total = ( fwbs_variables.vol_blkt_inboard_full_coverage + fwbs_variables.vol_blkt_outboard ) + def output_blkt_volumes_and_areas(self): + """Outputs blanket volumes and areas to the output file""" + + po.oheadr(self.outfile, "Blanket Volumes and Surface Areas") + + po.ovarst( + self.outfile, + "Inboard Blanket Volume with gaps and holes (m3)", + "(vol_blkt_inboard)", + fwbs_variables.vol_blkt_inboard, + ) + po.ovarst( + self.outfile, + "Outboard Blanket Volume with gaps and holes (m3)", + "(vol_blkt_outboard)", + fwbs_variables.vol_blkt_outboard, + ) + po.ovarst( + self.outfile, + "Total Blanket Volume with gaps and holes (m3)", + "(vol_blkt_total)", + fwbs_variables.vol_blkt_total, + ) + + po.ovarst( + self.outfile, + "Inboard Blanket Volume if toridally continuous (m3)", + "(vol_blkt_inboard_full_coverage)", + fwbs_variables.vol_blkt_inboard_full_coverage, + ) + po.ovarst( + self.outfile, + "Outboard Blanket Volume if toridally continuous (m3)", + "(vol_blkt_outboard_full_coverage)", + fwbs_variables.vol_blkt_outboard_full_coverage, + ) + po.ovarst( + self.outfile, + "Total Blanket Volume if toridally continuous (m3)", + "(vol_blkt_total_full_coverage)", + fwbs_variables.vol_blkt_total_full_coverage, + ) + + po.ovarst( + self.outfile, + "Inboard Blanket Surface Area with gaps and holes (m2)", + "(a_blkt_inboard_surface)", + build_variables.a_blkt_inboard_surface, + ) + po.ovarst( + self.outfile, + "Outboard Blanket Surface Area with gaps and holes (m2)", + "(a_blkt_outboard_surface)", + build_variables.a_blkt_outboard_surface, + ) + po.ovarst( + self.outfile, + "Total Blanket Surface Area with gaps and holes (m2)", + "(a_blkt_total_surface)", + build_variables.a_blkt_total_surface, + ) + + po.ovarst( + self.outfile, + "Inboard blanket surface area if toridally continuous (m2)", + "(a_blkt_inboard_surface_full_coverage)", + build_variables.a_blkt_inboard_surface_full_coverage, + ) + po.ovarst( + self.outfile, + "Outboard blanket surface area if toridally continuous (m2)", + "(a_blkt_outboard_surface_full_coverage)", + build_variables.a_blkt_outboard_surface_full_coverage, + ) + po.ovarst( + self.outfile, + "Total blanket surface area if toridally continuous (m2)", + "(a_blkt_total_surface_full_coverage)", + build_variables.a_blkt_total_surface_full_coverage, + ) + def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. Uses middle value of input and output temperatures of coolant. diff --git a/process/dcll.py b/process/dcll.py index 2b368ac7fc..c96637a66b 100644 --- a/process/dcll.py +++ b/process/dcll.py @@ -912,6 +912,8 @@ def write_output(self): # Component Volumes po.osubhd(self.outfile, "Component Volumes :") + self.output_blkt_volumes_and_areas() + po.ovarrf( self.outfile, "First Wall Armour Volume (m3)", diff --git a/process/hcpb.py b/process/hcpb.py index 288beb7a51..32868cfe14 100644 --- a/process/hcpb.py +++ b/process/hcpb.py @@ -1221,6 +1221,9 @@ def st_centrepost_nuclear_heating(self, pneut, sh_width): def write_output(self): po.oheadr(self.outfile, "First wall and blanket : CCFE HCPB model") + + self.output_blkt_volumes_and_areas() + po.osubhd(self.outfile, "Blanket Composition by volume :") po.ovarrf( From e74a3b56fb500bb8152d5c41766d437f944423b6 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 17:29:53 +0000 Subject: [PATCH 33/35] Add surface area and volume calculations for blanket with full coverage; update plotting functions to display these metrics --- process/blanket_library.py | 4 +++ process/io/plot_proc.py | 59 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index 53508101ce..e8b6a50d87 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -617,6 +617,10 @@ def apply_coverage_factors(self): ) fwbs_variables.vol_blkt_inboard = fwbs_variables.vol_blkt_inboard_full_coverage + build_variables.a_blkt_inboard_surface = ( + build_variables.a_blkt_inboard_surface_full_coverage + ) + fwbs_variables.vol_blkt_total = ( fwbs_variables.vol_blkt_inboard_full_coverage + fwbs_variables.vol_blkt_outboard diff --git a/process/io/plot_proc.py b/process/io/plot_proc.py index 6f8828ac7c..406f1b44bc 100644 --- a/process/io/plot_proc.py +++ b/process/io/plot_proc.py @@ -10596,8 +10596,8 @@ def plot_tf_stress(axis: plt.Axes, mfile: mf.MFile): def plot_blkt_pipe_bends(fig, m_file, scan: int): """Plot the blanket pipe bends on the given axis, with axes in mm.""" - ax_90 = fig.add_subplot(331) - ax_180 = fig.add_subplot(334) + ax_90 = fig.add_subplot(341) + ax_180 = fig.add_subplot(342) # Get pipe radius from m_file, fallback to 0.1 m r = m_file.get("radius_blkt_channel", scan=scan) @@ -12745,6 +12745,7 @@ def plot_inequality_constraint_equations(axis: plt.Axes, m_file: mf.MFile, scan: def plot_blkt_structure( ax: plt.Axes, + fig: plt.Figure, m_file: mf.MFile, scan: int, radial_build: dict[str, float], @@ -12816,6 +12817,58 @@ def plot_blkt_structure( label="Midplane", ) + textstr_blkt_areas = ( + f"$\\mathbf{{Blanket \\ Areas:}}$\n\n" + f"Inboard blanket, with holes and gaps: {m_file.get('a_blkt_inboard_surface', scan=scan):,.3f} $\\text{{m}}^2$ \n" + f"Outboard blanket, with holes and gaps: {m_file.get('a_blkt_outboard_surface', scan=scan):,.3f} $\\text{{m}}^2$ \n" + f"Total blanket, with holes and gaps: {m_file.get('a_blkt_total_surface', scan=scan):,.3f} $\\text{{m}}^2$ \n\n" + f"Inboard blanket, full coverage: {m_file.get('a_blkt_inboard_surface_full_coverage', scan=scan):,.3f} $\\text{{m}}^2$ \n" + f"Outboard blanket, full coverage: {m_file.get('a_blkt_outboard_surface_full_coverage', scan=scan):,.3f} $\\text{{m}}^2$ \n" + f"Total blanket, full coverage: {m_file.get('a_blkt_total_surface_full_coverage', scan=scan):,.3f} $\\text{{m}}^2$ " + ) + + ax.text( + 0.05, + 0.3, + textstr_blkt_areas, + fontsize=9, + verticalalignment="bottom", + horizontalalignment="left", + transform=fig.transFigure, + bbox={ + "boxstyle": "round", + "facecolor": "wheat", + "alpha": 1.0, + "linewidth": 2, + }, + ) + + textstr_blkt_volumes = ( + f"$\\mathbf{{Blanket \\ Volumes:}}$\n\n" + f"Inboard blanket, with holes and gaps: {m_file.get('vol_blkt_inboard', scan=scan):,.3f} $\\text{{m}}^3$ \n" + f"Outboard blanket, with holes and gaps: {m_file.get('vol_blkt_outboard', scan=scan):,.3f} $\\text{{m}}^3$ \n" + f"Total blanket, with holes and gaps: {m_file.get('vol_blkt_total', scan=scan):,.3f} $\\text{{m}}^3$ \n\n" + f"Inboard blanket, full coverage: {m_file.get('vol_blkt_inboard_full_coverage', scan=scan):,.3f} $\\text{{m}}^3$ \n" + f"Outboard blanket, full coverage: {m_file.get('vol_blkt_outboard_full_coverage', scan=scan):,.3f} $\\text{{m}}^3$ \n" + f"Total blanket, full coverage: {m_file.get('vol_blkt_total_full_coverage', scan=scan):,.3f} $\\text{{m}}^3$ " + ) + + ax.text( + 0.05, + 0.05, + textstr_blkt_volumes, + fontsize=9, + verticalalignment="bottom", + horizontalalignment="left", + transform=fig.transFigure, + bbox={ + "boxstyle": "round", + "facecolor": "wheat", + "alpha": 1.0, + "linewidth": 2, + }, + ) + def main_plot( figs: list[Axes], @@ -13086,7 +13139,7 @@ def main_plot( plot_blkt_pipe_bends(figs[27], m_file, scan) ax_blanket = figs[27].add_subplot(122, aspect="equal") - plot_blkt_structure(ax_blanket, m_file, scan, radial_build, colour_scheme) + plot_blkt_structure(ax_blanket, figs[27], m_file, scan, radial_build, colour_scheme) plot_main_power_flow( figs[28].add_subplot(111, aspect="equal"), m_file, scan, figs[28] From 026f41d694a53abbdaac2b0e5253c3b71903987c Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 17:54:35 +0000 Subject: [PATCH 34/35] Add blanket arc radius variables to fwbs_variables module --- process/data_structure/fwbs_variables.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/process/data_structure/fwbs_variables.py b/process/data_structure/fwbs_variables.py index 5decc9c3d1..818eef440f 100644 --- a/process/data_structure/fwbs_variables.py +++ b/process/data_structure/fwbs_variables.py @@ -373,6 +373,14 @@ dr_fw_wall: float = None """wall thickness of first wall coolant channels [m]""" +r_blkt_arc_1: float = None +"""First blanket arc radius [m]""" + +r_blkt_arc_2: float = None +"""Second blanket arc radius [m]""" + +r_blkt_arc_3: float = None +"""Third blanket arc radius [m]""" radius_fw_channel: float = None """radius of first wall cooling channels [m]""" @@ -989,6 +997,9 @@ def init_fwbs_variables(): i_blkt_coolant_type, \ i_fw_coolant_type, \ dr_fw_wall, \ + r_blkt_arc_1, \ + r_blkt_arc_2, \ + r_blkt_arc_3, \ radius_fw_channel, \ dx_fw_module, \ temp_fw_coolant_in, \ @@ -1184,6 +1195,9 @@ def init_fwbs_variables(): i_blkt_coolant_type = 1 i_fw_coolant_type = "helium" dr_fw_wall = 0.003 + r_blkt_arc_1 = 0.0 + r_blkt_arc_2 = 0.0 + r_blkt_arc_3 = 0.0 radius_fw_channel = 0.006 dx_fw_module = 0.02 temp_fw_coolant_in = 573.0 From 5526a2bba559d463edf4349c7b82879f0208fc86 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Fri, 30 Jan 2026 19:15:25 +0000 Subject: [PATCH 35/35] Add blanket arc radius calculations and update plotting to visualize arc points --- process/blanket_library.py | 38 +++++++++++++++++++++++++++++++++++--- process/io/plot_proc.py | 15 +++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/process/blanket_library.py b/process/blanket_library.py index e8b6a50d87..a4442251ad 100644 --- a/process/blanket_library.py +++ b/process/blanket_library.py @@ -107,6 +107,9 @@ def component_volumes(self): build_variables.a_blkt_inboard_surface_full_coverage, build_variables.a_blkt_outboard_surface_full_coverage, build_variables.a_blkt_total_surface_full_coverage, + fwbs_variables.r_blkt_arc_1, + fwbs_variables.r_blkt_arc_2, + fwbs_variables.r_blkt_arc_3, ) = self.calculate_elliptical_blkt_areas( rmajor=physics_variables.rmajor, rminor=physics_variables.rminor, @@ -394,7 +397,7 @@ def calculate_elliptical_blkt_areas( dr_shld_outboard: float, dr_blkt_outboard: float, dz_blkt_half: float, - ) -> tuple[float, float, float]: + ) -> tuple[float, float, float, float, float, float]: """Calculate elliptical blanket surface areas. :param rmajor: Major radius of the plasma (m) @@ -418,7 +421,8 @@ def calculate_elliptical_blkt_areas( :param dz_blkt_half: Half-height of the blanket (m) :type dz_blkt_half: float - :return: Tuple containing inboard blanket surface area (m²), outboard blanket surface area (m²), and total blanket surface area (m²) + :return: Tuple containing inboard blanket surface area (m²), outboard blanket surface area (m²), and total blanket surface area (m²), + and three blanket arc radii (m) """ # Major radius to centre of inboard and outboard ellipses (m) @@ -445,7 +449,14 @@ def calculate_elliptical_blkt_areas( a_blkt_total_surface, ) = eshellarea(r1, r2, r3, dz_blkt_half) - return a_blkt_inboard_surface, a_blkt_outboard_surface, a_blkt_total_surface + return ( + a_blkt_inboard_surface, + a_blkt_outboard_surface, + a_blkt_total_surface, + r1, + r2, + r3, + ) @staticmethod def calculate_elliptical_blkt_volumes( @@ -707,6 +718,27 @@ def output_blkt_volumes_and_areas(self): build_variables.a_blkt_total_surface_full_coverage, ) + po.oblnkl(self.outfile) + + po.ovarst( + self.outfile, + "First radial blanket arc point (m)", + "(r_blkt_arc_1)", + fwbs_variables.r_blkt_arc_1, + ) + po.ovarst( + self.outfile, + "Second radial blanket arc point (m)", + "(r_blkt_arc_2)", + fwbs_variables.r_blkt_arc_2, + ) + po.ovarst( + self.outfile, + "Third radial blanket arc point (m)", + "(r_blkt_arc_3)", + fwbs_variables.r_blkt_arc_3, + ) + def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. Uses middle value of input and output temperatures of coolant. diff --git a/process/io/plot_proc.py b/process/io/plot_proc.py index 406f1b44bc..dfb282f0d8 100644 --- a/process/io/plot_proc.py +++ b/process/io/plot_proc.py @@ -12817,6 +12817,21 @@ def plot_blkt_structure( label="Midplane", ) + # Plot the points as black dots, number them, and connect them with lines + xs = [m_file.get(f"r_blkt_arc_{i}", scan=scan) for i in range(1, 4)] + for i, (x,) in enumerate(zip(xs, strict=False), 1): + ax.plot(x, 0.0, "ko", markersize=8) + ax.text( + x, + 0.0, + str(i), + color="red", + fontsize=5, + ha="center", + va="center", + fontweight="bold", + ) + textstr_blkt_areas = ( f"$\\mathbf{{Blanket \\ Areas:}}$\n\n" f"Inboard blanket, with holes and gaps: {m_file.get('a_blkt_inboard_surface', scan=scan):,.3f} $\\text{{m}}^2$ \n"