From ae99919b5a28e5a25687e4cc4a8ab31f7ff07430 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 09:42:14 +0100 Subject: [PATCH 01/17] Add poloidal angle attributes for inboard and outboard blankets Co-authored-by: Copilot --- process/data_structure/blanket_library.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/process/data_structure/blanket_library.py b/process/data_structure/blanket_library.py index 2cd99c3645..5c29dad6b5 100644 --- a/process/data_structure/blanket_library.py +++ b/process/data_structure/blanket_library.py @@ -236,6 +236,12 @@ icomponent: int = None """Switch used to specify selected component: blanket=0, shield=1, vacuum vessel=2""" +deg_blkt_outboard_poloidal_plasma: float = None +"""Outboard blanket poloidal angle subtended by plasma (degrees)""" + +deg_blkt_inboard_poloidal_plasma: float = None +"""Inboard blanket poloidal angle subtended by plasma (degrees)""" + def init_blanket_library(): global \ @@ -288,7 +294,9 @@ def init_blanket_library(): htpmw_blkti, \ htpmw_blkto, \ vfblkti, \ - vfblkto + vfblkto, \ + deg_blkt_outboard_poloidal_plasma, \ + deg_blkt_inboard_poloidal_plasma dz_blkt_half = 0.0 dz_shld_half = 0.0 @@ -340,3 +348,5 @@ def init_blanket_library(): htpmw_blkto = 0.0 vfblkti = 0.0 vfblkto = 0.0 + deg_blkt_outboard_poloidal_plasma = 0.0 + deg_blkt_inboard_poloidal_plasma = 0.0 From 36d1337f8d1fd213bcc27d018f459e5029dd3dad Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 10:06:42 +0100 Subject: [PATCH 02/17] Add calculation for outboard blanket poloidal angle subtended by plasma Co-authored-by: Copilot --- process/models/blankets/blanket_library.py | 48 ++++++++++++++++++++++ process/models/blankets/hcpb.py | 10 +++++ 2 files changed, 58 insertions(+) diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index 3f1cf646c9..ff0cc2bcad 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -643,6 +643,13 @@ def output_blkt_volumes_and_areas(self): "(a_blkt_total_surface_full_coverage)", build_variables.a_blkt_total_surface_full_coverage, ) + po.oblnkl(self.outfile) + po.ovarre( + self.outfile, + "Outboard blanket poloidal angle subtended by plasma (degrees)", + "(deg_blkt_outboard_poloidal_plasma)", + blanket_library.deg_blkt_outboard_poloidal_plasma, + ) def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. @@ -3677,6 +3684,47 @@ def calculate_basic_geometry(self): fwbs_variables.radius_blkt_channel_180_bend, ) = self.calculate_pipe_bend_radius(i_ps=1) + @staticmethod + def calculate_blkt_outboard_poloidal_plasma_angle( + rminor: float, + dr_blkt_outboard: float, + dz_blkt_half: float, + dr_fw_plasma_gap_outboard: float, + dr_fw_outboard: float, + ) -> float: + """Calculate the poloidal angle subtended by the outboard blanket at the plasma mid-plane. + + Parameters + ---------- + rminor : + Plasma minor radius (m). + dr_blkt_outboard : + Radial thickness of outboard blanket (m). + dz_blkt_half : + Vertical half-height of outboard blanket (m). + dr_fw_plasma_gap_outboard : + Outboard first wall to plasma gap (m). + dr_fw_outboard : + Radial thickness of outboard first wall (m). + + Returns + ------- + deg_blkt_outboard_poloidal_plasma : + Poloidal angle subtended by outboard blanket at plasma mid-plane (degrees). + """ + return np.degrees( + 2.0 + * np.arctan( + dz_blkt_half + / ( + rminor + + dr_blkt_outboard + + dr_fw_plasma_gap_outboard + + dr_fw_outboard + ) + ) + ) + def calculate_blanket_outboard_module_geometry( self, n_blkt_outboard_modules_toroidal: int, diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index a93ce4bd7d..21f54899d8 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -52,6 +52,16 @@ def run(self, output: bool = False): # Calculate blanket, shield, vacuum vessel and cryostat volumes self.component_volumes() + blanket_vars.deg_blkt_outboard_poloidal_plasma = ( + self.calculate_blkt_outboard_poloidal_plasma_angle( + rminor=physics_variables.rminor, + dr_blkt_outboard=build_variables.dr_blkt_outboard, + dz_blkt_half=blanket_vars.dz_blkt_half, + dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, + dr_fw_outboard=build_variables.dr_fw_outboard, + ) + ) + dia_blkt_channel = self.pipe_hydraulic_diameter(i_channel_shape=1) fwbs_variables.radius_blkt_channel = dia_blkt_channel / 2 ( From c832dd029cc4f6d075e7713216e6b1dda9457947 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 10:58:09 +0100 Subject: [PATCH 03/17] Add poloidal angle visualization for blanket structure in plot Co-authored-by: Copilot --- process/core/io/plot/summary.py | 101 ++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index 261cd8dd5d..31409e2839 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13743,14 +13743,36 @@ def plot_blkt_structure( ): """Plot the BLKT structure on the given axis.""" rmajor = m_file.get("rmajor", scan=scan) + rminor = m_file.get("rminor", scan=scan) + dr_fw_plasma_gap_outboard = m_file.get("dr_fw_plasma_gap_outboard", scan=scan) + dr_fw_plasma_gap_inboard = m_file.get("dr_fw_plasma_gap_inboard", scan=scan) + dr_fw_inboard = m_file.get("dr_fw_inboard", scan=scan) + dr_fw_outboard = m_file.get("dr_fw_outboard", scan=scan) + dr_blkt_outboard = m_file.get("dr_blkt_outboard", scan=scan) + dr_blkt_inboard = m_file.get("dr_blkt_inboard", scan=scan) + dz_blkt_half = m_file.get("dz_blkt_half", scan=scan) + deg_blkt_outboard_poloidal_plasma = m_file.get( + "deg_blkt_outboard_poloidal_plasma", scan=scan + ) plot_blanket(ax, m_file, scan, radial_build, colour_scheme) + plot_plasma(ax, m_file, scan, 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) + + r_blkt_outboard_out = ( + rmajor + rminor + dr_fw_outboard + dr_fw_plasma_gap_outboard + dr_blkt_outboard + ) + r_blkt_inboard_in = ( + rmajor - rminor - dr_fw_plasma_gap_inboard - dr_fw_inboard - dr_blkt_inboard + ) + r_fw_outboard_in = r_blkt_outboard_out - dr_blkt_outboard - dr_fw_outboard + r_fw_inboard_out = r_blkt_inboard_in + dr_blkt_inboard + dr_fw_inboard + # Plot major radius line (vertical dashed line at rmajor) ax.axvline( m_file.get("rminor", scan=scan), @@ -13760,7 +13782,6 @@ def plot_blkt_structure( 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", @@ -13778,23 +13799,77 @@ def plot_blkt_structure( ax.annotate( "", - xy=(rmajor, dz_blkt_half), - xytext=(rmajor, -dz_blkt_half), - arrowprops={"arrowstyle": "<->", "color": "black"}, + xy=(rmajor, 0), + xytext=(r_blkt_outboard_out, dz_blkt_half), + arrowprops={"arrowstyle": "<-", "color": "purple"}, ) - # Add a label for the internal coil width + ax.annotate( + "", + xy=(rmajor, 0), + xytext=(r_blkt_outboard_out, -dz_blkt_half), + arrowprops={"arrowstyle": "<-", "color": "purple"}, + ) + + # Plot arc showing the angle between the two arrows + arc_radius = 1.0 + angle_start = -deg_blkt_outboard_poloidal_plasma / 2 + angle_end = deg_blkt_outboard_poloidal_plasma / 2 + + theta = np.linspace(np.deg2rad(angle_start), np.deg2rad(angle_end), 50) + arc_x = rmajor + arc_radius * np.cos(theta) + arc_y = arc_radius * np.sin(theta) + + ax.plot(arc_x, arc_y, color="purple", linewidth=2) + + # Add angle label at the arc + mid_angle = np.deg2rad((angle_start + angle_end) / 2) + label_radius = arc_radius * 1.5 + label_x = rmajor + label_radius * np.cos(mid_angle) + label_y = label_radius * np.sin(mid_angle) + ax.text( + label_x, + label_y, + f"{deg_blkt_outboard_poloidal_plasma:.1f}°", + fontsize=10, + color="purple", + ha="center", + va="center", + weight="bold", + ) + + ax.annotate( + "", + xy=(rmajor, 0), + xytext=(r_blkt_inboard_in, dz_blkt_half), + arrowprops={"arrowstyle": "<-", "color": "purple"}, + ) + + ax.annotate( + "", + xy=(rmajor, 0), + xytext=(r_blkt_inboard_in, -dz_blkt_half), + arrowprops={"arrowstyle": "<-", "color": "purple"}, + ) + + # Plot vertical lines at the inner and outer radial boundaries of the blanket + ax.axvline( + r_blkt_inboard_in, color="black", linestyle="--", linewidth=1.5, zorder=10 + ) + ax.axvline( + r_blkt_outboard_out, color="black", linestyle="--", linewidth=1.5, zorder=10 + ) + ax.axvline(r_fw_inboard_out, color="black", linestyle="--", linewidth=1.5, zorder=10) + + ax.axvline(r_fw_outboard_in, color="black", linestyle="--", linewidth=1.5, zorder=10) + + ax.axvline( 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 + linestyle="--", + linewidth=1.5, + label="Major Radius $R_0$", ) # Plot midplane line (horizontal dashed line at Z=0) From 85e6c9496abfa40189066e5b093459c8c39c1ea0 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 11:34:05 +0100 Subject: [PATCH 04/17] Add calculation and visualization for inboard blanket poloidal angle Co-authored-by: Copilot --- process/core/io/plot/summary.py | 53 ++++++++++++++++++++-- process/models/blankets/blanket_library.py | 34 ++++++++++++++ process/models/blankets/hcpb.py | 8 ++++ 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index 31409e2839..65262ca656 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13754,6 +13754,9 @@ def plot_blkt_structure( deg_blkt_outboard_poloidal_plasma = m_file.get( "deg_blkt_outboard_poloidal_plasma", scan=scan ) + deg_blkt_inboard_poloidal_plasma = m_file.get( + "deg_blkt_inboard_poloidal_plasma", scan=scan + ) plot_blanket(ax, m_file, scan, radial_build, colour_scheme) plot_plasma(ax, m_file, scan, colour_scheme) @@ -13824,7 +13827,7 @@ def plot_blkt_structure( # Add angle label at the arc mid_angle = np.deg2rad((angle_start + angle_end) / 2) - label_radius = arc_radius * 1.5 + label_radius = arc_radius * 1.8 label_x = rmajor + label_radius * np.cos(mid_angle) label_y = label_radius * np.sin(mid_angle) @@ -13832,27 +13835,69 @@ def plot_blkt_structure( label_x, label_y, f"{deg_blkt_outboard_poloidal_plasma:.1f}°", - fontsize=10, + fontsize=8, color="purple", ha="center", va="center", weight="bold", + bbox={ + "boxstyle": "round", + "facecolor": "white", + "alpha": 0.8, + "edgecolor": "purple", + "linewidth": 1.5, + }, ) ax.annotate( "", xy=(rmajor, 0), - xytext=(r_blkt_inboard_in, dz_blkt_half), + xytext=(r_fw_inboard_out, dz_blkt_half), arrowprops={"arrowstyle": "<-", "color": "purple"}, ) ax.annotate( "", xy=(rmajor, 0), - xytext=(r_blkt_inboard_in, -dz_blkt_half), + xytext=(r_fw_inboard_out, -dz_blkt_half), arrowprops={"arrowstyle": "<-", "color": "purple"}, ) + # Plot arc showing the angle between the two arrows + arc_radius = 1.0 + angle_start = -deg_blkt_inboard_poloidal_plasma / 2 + angle_end = deg_blkt_inboard_poloidal_plasma / 2 + + theta = np.linspace(np.deg2rad(angle_start), np.deg2rad(angle_end), 50) + arc_x = rmajor - arc_radius * np.cos(theta) + arc_y = arc_radius * np.sin(theta) + + ax.plot(arc_x, arc_y, color="purple", linewidth=2) + + # Add angle label at the arc + mid_angle = np.deg2rad((angle_start + angle_end) / 2) + label_radius = arc_radius * 1.8 + label_x = rmajor - label_radius * np.cos(mid_angle) + label_y = label_radius * np.sin(mid_angle) + + ax.text( + label_x, + label_y, + f"{deg_blkt_inboard_poloidal_plasma:.1f}°", + fontsize=8, + color="purple", + ha="center", + va="center", + weight="bold", + bbox={ + "boxstyle": "round", + "facecolor": "white", + "alpha": 0.8, + "edgecolor": "purple", + "linewidth": 1.5, + }, + ) + # Plot vertical lines at the inner and outer radial boundaries of the blanket ax.axvline( r_blkt_inboard_in, color="black", linestyle="--", linewidth=1.5, zorder=10 diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index ff0cc2bcad..ba85101829 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -650,6 +650,12 @@ def output_blkt_volumes_and_areas(self): "(deg_blkt_outboard_poloidal_plasma)", blanket_library.deg_blkt_outboard_poloidal_plasma, ) + po.ovarre( + self.outfile, + "Inboard blanket poloidal angle subtended by plasma (degrees)", + "(deg_blkt_inboard_poloidal_plasma)", + blanket_library.deg_blkt_inboard_poloidal_plasma, + ) def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. @@ -3768,6 +3774,34 @@ def calculate_basic_geometry(self): self.set_blanket_module_geometry() + @staticmethod + def calculate_blkt_inboard_poloidal_plasma_angle( + rminor: float, + dz_blkt_half: float, + dr_fw_plasma_gap_inboard: float, + ) -> float: + """Calculate the poloidal angle subtended by the inboard blanket at the plasma mid-plane. + + Angle is taken from the FW surface + + Parameters + ---------- + rminor : + Plasma minor radius (m). + dz_blkt_half : + Vertical half-height of inboard blanket (m). + dr_fw_plasma_gap_inboard : + Inboard first wall to plasma gap (m). + + Returns + ------- + deg_blkt_inboard_poloidal_plasma : + Poloidal angle subtended by inboard blanket at plasma mid-plane (degrees). + """ + return np.degrees( + 2.0 * np.arctan(dz_blkt_half / (rminor + dr_fw_plasma_gap_inboard)) + ) + def calculate_blanket_inboard_module_geometry( self, n_blkt_inboard_modules_toroidal: int, diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index 21f54899d8..f8228c3012 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -62,6 +62,14 @@ def run(self, output: bool = False): ) ) + blanket_vars.deg_blkt_inboard_poloidal_plasma = ( + self.calculate_blkt_inboard_poloidal_plasma_angle( + rminor=physics_variables.rminor, + dz_blkt_half=blanket_vars.dz_blkt_half, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + ) + ) + dia_blkt_channel = self.pipe_hydraulic_diameter(i_channel_shape=1) fwbs_variables.radius_blkt_channel = dia_blkt_channel / 2 ( From a70ea9e587ee04488ea76cf3b7f261288762fe9f Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 11:59:36 +0100 Subject: [PATCH 05/17] Add outboard blanket poloidal angle calculation and update plot annotations Co-authored-by: Copilot --- process/core/io/plot/summary.py | 18 +++++++++++------- process/models/blankets/blanket_library.py | 5 +++++ process/models/blankets/hcpb.py | 9 ++------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index 65262ca656..ac71a986e2 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13803,15 +13803,17 @@ def plot_blkt_structure( ax.annotate( "", xy=(rmajor, 0), - xytext=(r_blkt_outboard_out, dz_blkt_half), + xytext=(rmajor, dz_blkt_half), arrowprops={"arrowstyle": "<-", "color": "purple"}, + zorder=5, ) ax.annotate( "", xy=(rmajor, 0), - xytext=(r_blkt_outboard_out, -dz_blkt_half), + xytext=(rmajor, -dz_blkt_half), arrowprops={"arrowstyle": "<-", "color": "purple"}, + zorder=5, ) # Plot arc showing the angle between the two arrows @@ -13853,14 +13855,16 @@ def plot_blkt_structure( "", xy=(rmajor, 0), xytext=(r_fw_inboard_out, dz_blkt_half), - arrowprops={"arrowstyle": "<-", "color": "purple"}, + arrowprops={"arrowstyle": "<-", "color": "green"}, + zorder=5, ) ax.annotate( "", xy=(rmajor, 0), xytext=(r_fw_inboard_out, -dz_blkt_half), - arrowprops={"arrowstyle": "<-", "color": "purple"}, + arrowprops={"arrowstyle": "<-", "color": "green"}, + zorder=5, ) # Plot arc showing the angle between the two arrows @@ -13872,7 +13876,7 @@ def plot_blkt_structure( arc_x = rmajor - arc_radius * np.cos(theta) arc_y = arc_radius * np.sin(theta) - ax.plot(arc_x, arc_y, color="purple", linewidth=2) + ax.plot(arc_x, arc_y, color="green", linewidth=2) # Add angle label at the arc mid_angle = np.deg2rad((angle_start + angle_end) / 2) @@ -13885,7 +13889,7 @@ def plot_blkt_structure( label_y, f"{deg_blkt_inboard_poloidal_plasma:.1f}°", fontsize=8, - color="purple", + color="green", ha="center", va="center", weight="bold", @@ -13893,7 +13897,7 @@ def plot_blkt_structure( "boxstyle": "round", "facecolor": "white", "alpha": 0.8, - "edgecolor": "purple", + "edgecolor": "green", "linewidth": 1.5, }, ) diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index ba85101829..1648cd48cc 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -3690,6 +3690,11 @@ def calculate_basic_geometry(self): fwbs_variables.radius_blkt_channel_180_bend, ) = self.calculate_pipe_bend_radius(i_ps=1) + @property + def blkt_outboard_poloidal_plasma_angle(self) -> float: + """Calculate the poloidal angle subtended by the outboard blanket at the plasma mid-plane.""" + return 180.0 + @staticmethod def calculate_blkt_outboard_poloidal_plasma_angle( rminor: float, diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index f8228c3012..ce1419dfc3 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -52,14 +52,9 @@ def run(self, output: bool = False): # Calculate blanket, shield, vacuum vessel and cryostat volumes self.component_volumes() + # If Shfranov shift is added, the angle formula can be used where the shift is added to the minor radius. For now, the shift is neglected and the angle is calculated using the minor radius only. blanket_vars.deg_blkt_outboard_poloidal_plasma = ( - self.calculate_blkt_outboard_poloidal_plasma_angle( - rminor=physics_variables.rminor, - dr_blkt_outboard=build_variables.dr_blkt_outboard, - dz_blkt_half=blanket_vars.dz_blkt_half, - dr_fw_plasma_gap_outboard=build_variables.dr_fw_plasma_gap_outboard, - dr_fw_outboard=build_variables.dr_fw_outboard, - ) + self.blkt_outboard_poloidal_plasma_angle ) blanket_vars.deg_blkt_inboard_poloidal_plasma = ( From 98f7eb16e39d99238c0e0c35d778f47b5ab0b395 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 12:05:01 +0100 Subject: [PATCH 06/17] Add divertor poloidal angle subtended by plasma variable Co-authored-by: Copilot --- process/data_structure/divertor_variables.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/process/data_structure/divertor_variables.py b/process/data_structure/divertor_variables.py index e096caac03..3769428b90 100644 --- a/process/data_structure/divertor_variables.py +++ b/process/data_structure/divertor_variables.py @@ -71,6 +71,9 @@ n_divertors: int = None """Number of divertors (calculated from `i_single_null`)""" +deg_div_poloidal_plasma: float = None +"""Divertor poloidal angle subtended by plasma (degrees)""" + def init_divertor_variables(): global \ @@ -96,7 +99,8 @@ def init_divertor_variables(): p_div_upper_nuclear_heat_mw, \ p_div_upper_rad_mw, \ p_div_lower_rad_mw, \ - n_divertors + n_divertors, \ + deg_div_poloidal_plasma anginc = 0.262 deg_div_field_plate = 1.0 @@ -121,3 +125,4 @@ def init_divertor_variables(): p_div_upper_rad_mw = 0.0 p_div_lower_rad_mw = 0.0 n_divertors = 2 + deg_div_poloidal_plasma = 0.0 From 459fb4046d1ef325d2d6fd1d4e64cd56d424862b Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 12:30:30 +0100 Subject: [PATCH 07/17] Add calculation and visualization for divertor poloidal angle subtended by plasma Co-authored-by: Copilot --- process/core/io/plot/summary.py | 36 +++++++++++++++++++++++++++++++++ process/models/build.py | 14 +++++++++++++ process/models/divertor.py | 18 +++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index ac71a986e2..8a609889ed 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13757,6 +13757,7 @@ def plot_blkt_structure( deg_blkt_inboard_poloidal_plasma = m_file.get( "deg_blkt_inboard_poloidal_plasma", scan=scan ) + deg_div_poloidal_plasma = m_file.get("deg_div_poloidal_plasma", scan=scan) plot_blanket(ax, m_file, scan, radial_build, colour_scheme) plot_plasma(ax, m_file, scan, colour_scheme) @@ -13902,6 +13903,41 @@ def plot_blkt_structure( }, ) + # Plot arc showing the angle between the two arrows (divertor angle) + arc_radius = 1.5 + angle_start = -deg_blkt_outboard_poloidal_plasma / 2 - deg_div_poloidal_plasma + angle_end = -deg_blkt_inboard_poloidal_plasma / 2 - deg_div_poloidal_plasma + + theta = np.linspace(np.deg2rad(angle_start), np.deg2rad(angle_end), 50) + arc_x = rmajor + arc_radius * np.cos(theta) + arc_y = arc_radius * np.sin(theta) + + ax.plot(arc_x, arc_y, color="black", linewidth=2) + + # Add angle label at the arc + mid_angle = np.deg2rad((angle_start + angle_end) / 2) + label_radius = arc_radius * 1.8 + label_x = rmajor + label_radius * np.cos(mid_angle) + label_y = label_radius * np.sin(mid_angle) + + ax.text( + label_x, + label_y, + f"{deg_div_poloidal_plasma:.1f}°", + fontsize=8, + color="black", + ha="center", + va="center", + weight="bold", + bbox={ + "boxstyle": "round", + "facecolor": "white", + "alpha": 0.8, + "edgecolor": "black", + "linewidth": 1.5, + }, + ) + # Plot vertical lines at the inner and outer radial boundaries of the blanket ax.axvline( r_blkt_inboard_in, color="black", linestyle="--", linewidth=1.5, zorder=10 diff --git a/process/models/build.py b/process/models/build.py index 36cd137695..3eda097aab 100644 --- a/process/models/build.py +++ b/process/models/build.py @@ -1188,6 +1188,13 @@ def divgeom(self, output: bool): divht, "OP ", ) + po.ovarrf( + self.outfile, + "Divertor poloidal angle subtended by plasma (degrees)", + "(deg_div_poloidal_plasma)", + divertor_variables.deg_div_poloidal_plasma, + "OP ", + ) elif divertor_variables.n_divertors == 2: po.oheadr(self.outfile, "Divertor build and plasma position") @@ -1498,6 +1505,13 @@ def divgeom(self, output: bool): divht, "OP ", ) + po.ovarrf( + self.outfile, + "Divertor poloidal angle subtended by plasma (degrees)", + "(deg_div_poloidal_plasma)", + divertor_variables.deg_div_poloidal_plasma, + "OP ", + ) else: po.oheadr(self.outfile, "Divertor build and plasma position") po.ocmmnt( diff --git a/process/models/divertor.py b/process/models/divertor.py index f89a42b1ee..706ff9d0e7 100644 --- a/process/models/divertor.py +++ b/process/models/divertor.py @@ -6,6 +6,7 @@ from process.core import process_output as po from process.core.exceptions import ProcessValueError from process.core.model import Model +from process.data_structure import blanket_library from process.data_structure import build_variables as bv from process.data_structure import divertor_variables as dv from process.data_structure import fwbs_variables as fwbs @@ -38,6 +39,8 @@ def run(self, output: bool = False): output : indicate whether output should be written to the output file, or not """ + dv.deg_div_poloidal_plasma = self.single_divertor_angle + fwbs.p_div_nuclear_heat_total_mw = self.incident_neutron_power( p_plasma_neutron_mw=pv.p_plasma_neutron_mw, f_ster_div_single=fwbs.f_ster_div_single, @@ -88,6 +91,21 @@ def run(self, output: bool = False): ) return + @property + def single_divertor_angle(self): + """ + Calculate the angle subtended by a single divertor. + Angle is calculated as 360 degrees minus the sum of the inboard + and outboard blanket poloidal angles, divided by 2 (for two divertors). + """ + return ( + 360.0 + - ( + blanket_library.deg_blkt_inboard_poloidal_plasma + + blanket_library.deg_blkt_outboard_poloidal_plasma + ) + ) / 2.0 + def divtart( self, rmajor: float, From ea9c8562ae6465e2ff9862538b1904c4f7ca5b7c Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 12:42:58 +0100 Subject: [PATCH 08/17] Add divertor poloidal angle output and calculation updates Co-authored-by: Copilot --- process/models/build.py | 14 -------------- process/models/divertor.py | 1 + process/models/physics/physics.py | 7 +++++++ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/process/models/build.py b/process/models/build.py index 3eda097aab..36cd137695 100644 --- a/process/models/build.py +++ b/process/models/build.py @@ -1188,13 +1188,6 @@ def divgeom(self, output: bool): divht, "OP ", ) - po.ovarrf( - self.outfile, - "Divertor poloidal angle subtended by plasma (degrees)", - "(deg_div_poloidal_plasma)", - divertor_variables.deg_div_poloidal_plasma, - "OP ", - ) elif divertor_variables.n_divertors == 2: po.oheadr(self.outfile, "Divertor build and plasma position") @@ -1505,13 +1498,6 @@ def divgeom(self, output: bool): divht, "OP ", ) - po.ovarrf( - self.outfile, - "Divertor poloidal angle subtended by plasma (degrees)", - "(deg_div_poloidal_plasma)", - divertor_variables.deg_div_poloidal_plasma, - "OP ", - ) else: po.oheadr(self.outfile, "Divertor build and plasma position") po.ocmmnt( diff --git a/process/models/divertor.py b/process/models/divertor.py index 706ff9d0e7..52dc58a700 100644 --- a/process/models/divertor.py +++ b/process/models/divertor.py @@ -40,6 +40,7 @@ def run(self, output: bool = False): indicate whether output should be written to the output file, or not """ dv.deg_div_poloidal_plasma = self.single_divertor_angle + fwbs.f_ster_div_single = dv.deg_div_poloidal_plasma / 360.0 fwbs.p_div_nuclear_heat_total_mw = self.incident_neutron_power( p_plasma_neutron_mw=pv.p_plasma_neutron_mw, diff --git a/process/models/physics/physics.py b/process/models/physics/physics.py index 8f1e10ccc0..8143b0a2ca 100644 --- a/process/models/physics/physics.py +++ b/process/models/physics/physics.py @@ -2681,6 +2681,13 @@ def outplas(self): physics_variables.ptarmw, "OP ", ) + po.ovarrf( + self.outfile, + "Divertor poloidal angle subtended by plasma (degrees)", + "(deg_div_poloidal_plasma)", + divertor_variables.deg_div_poloidal_plasma, + "OP ", + ) po.ovarre( self.outfile, "Fraction of power to the lower divertor", From 1ee108619a10346773960ca402d2b0af13407c33 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 12:50:39 +0100 Subject: [PATCH 09/17] Remove major radius line plotting from blanket structure visualization Co-authored-by: Copilot --- process/core/io/plot/summary.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index 8a609889ed..d347a03b32 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13777,14 +13777,6 @@ def plot_blkt_structure( r_fw_outboard_in = r_blkt_outboard_out - dr_blkt_outboard - dr_fw_outboard r_fw_inboard_out = r_blkt_inboard_in + dr_blkt_inboard + dr_fw_inboard - # 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) ax.axhline( dz_blkt_half, From 73aba311a619769f1e7bc3c547a4fbb8ab2b04e0 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 12:51:57 +0100 Subject: [PATCH 10/17] Add fractions for outboard and inboard blanket poloidal angles subtended by plasma Co-authored-by: Copilot --- process/data_structure/blanket_library.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/process/data_structure/blanket_library.py b/process/data_structure/blanket_library.py index 5c29dad6b5..1d5e22f01c 100644 --- a/process/data_structure/blanket_library.py +++ b/process/data_structure/blanket_library.py @@ -239,9 +239,15 @@ deg_blkt_outboard_poloidal_plasma: float = None """Outboard blanket poloidal angle subtended by plasma (degrees)""" +f_deg_blkt_outboard_poloidal_plasma: float = None +"""Fraction of outboard blanket poloidal angle subtended by plasma (degrees)""" + deg_blkt_inboard_poloidal_plasma: float = None """Inboard blanket poloidal angle subtended by plasma (degrees)""" +f_deg_blkt_inboard_poloidal_plasma: float = None +"""Fraction of inboard blanket poloidal angle subtended by plasma (degrees)""" + def init_blanket_library(): global \ @@ -296,7 +302,9 @@ def init_blanket_library(): vfblkti, \ vfblkto, \ deg_blkt_outboard_poloidal_plasma, \ - deg_blkt_inboard_poloidal_plasma + deg_blkt_inboard_poloidal_plasma, \ + f_deg_blkt_outboard_poloidal_plasma, \ + f_deg_blkt_inboard_poloidal_plasma dz_blkt_half = 0.0 dz_shld_half = 0.0 @@ -350,3 +358,5 @@ def init_blanket_library(): vfblkto = 0.0 deg_blkt_outboard_poloidal_plasma = 0.0 deg_blkt_inboard_poloidal_plasma = 0.0 + f_deg_blkt_outboard_poloidal_plasma = 0.0 + f_deg_blkt_inboard_poloidal_plasma = 0.0 From eb7d8865dd0797a14b96fdd97d578baee7d1a1b6 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 13:07:12 +0100 Subject: [PATCH 11/17] Add calculations and output for blanket poloidal angles subtended by plasma Co-authored-by: Copilot --- process/core/io/plot/summary.py | 13 ++++++++++--- process/models/blankets/blanket_library.py | 17 +++++++++++++++++ process/models/blankets/hcpb.py | 7 +++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index d347a03b32..59ad976773 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13757,7 +13757,14 @@ def plot_blkt_structure( deg_blkt_inboard_poloidal_plasma = m_file.get( "deg_blkt_inboard_poloidal_plasma", scan=scan ) + f_deg_blkt_outboard_poloidal_plasma = m_file.get( + "f_deg_blkt_outboard_poloidal_plasma", scan=scan + ) + f_deg_blkt_inboard_poloidal_plasma = m_file.get( + "f_deg_blkt_inboard_poloidal_plasma", scan=scan + ) deg_div_poloidal_plasma = m_file.get("deg_div_poloidal_plasma", scan=scan) + f_ster_div_single = m_file.get("f_ster_div_single", scan=scan) plot_blanket(ax, m_file, scan, radial_build, colour_scheme) plot_plasma(ax, m_file, scan, colour_scheme) @@ -13829,7 +13836,7 @@ def plot_blkt_structure( ax.text( label_x, label_y, - f"{deg_blkt_outboard_poloidal_plasma:.1f}°", + f"{deg_blkt_outboard_poloidal_plasma:.1f}°\n({f_deg_blkt_outboard_poloidal_plasma * 100:.1f}%)", fontsize=8, color="purple", ha="center", @@ -13880,7 +13887,7 @@ def plot_blkt_structure( ax.text( label_x, label_y, - f"{deg_blkt_inboard_poloidal_plasma:.1f}°", + f"{deg_blkt_inboard_poloidal_plasma:.1f}°\n({f_deg_blkt_inboard_poloidal_plasma * 100:.1f}%)", fontsize=8, color="green", ha="center", @@ -13915,7 +13922,7 @@ def plot_blkt_structure( ax.text( label_x, label_y, - f"{deg_div_poloidal_plasma:.1f}°", + f"{deg_div_poloidal_plasma:.1f}°\n({f_ster_div_single * 100:.1f}%)", fontsize=8, color="black", ha="center", diff --git a/process/models/blankets/blanket_library.py b/process/models/blankets/blanket_library.py index 1648cd48cc..583c1780f7 100644 --- a/process/models/blankets/blanket_library.py +++ b/process/models/blankets/blanket_library.py @@ -650,12 +650,24 @@ def output_blkt_volumes_and_areas(self): "(deg_blkt_outboard_poloidal_plasma)", blanket_library.deg_blkt_outboard_poloidal_plasma, ) + po.ovarre( + self.outfile, + "Angle fraction of outboard blanket poloidal angle subtended by plasma", + "(f_deg_blkt_outboard_poloidal_plasma)", + blanket_library.f_deg_blkt_outboard_poloidal_plasma, + ) po.ovarre( self.outfile, "Inboard blanket poloidal angle subtended by plasma (degrees)", "(deg_blkt_inboard_poloidal_plasma)", blanket_library.deg_blkt_inboard_poloidal_plasma, ) + po.ovarre( + self.outfile, + "Angle fraction of inboard blanket poloidal angle subtended by plasma", + "(f_deg_blkt_inboard_poloidal_plasma)", + blanket_library.f_deg_blkt_inboard_poloidal_plasma, + ) def primary_coolant_properties(self, output: bool): """Calculates the fluid properties of the Primary Coolant in the FW and BZ. @@ -3695,6 +3707,11 @@ def blkt_outboard_poloidal_plasma_angle(self) -> float: """Calculate the poloidal angle subtended by the outboard blanket at the plasma mid-plane.""" return 180.0 + @property + def f_deg_blkt_outboard_poloidal_plasma(self) -> float: + """Calculate the poloidal angle subtended by the outboard blanket at the plasma mid-plane.""" + return self.blkt_outboard_poloidal_plasma_angle / 360.0 + @staticmethod def calculate_blkt_outboard_poloidal_plasma_angle( rminor: float, diff --git a/process/models/blankets/hcpb.py b/process/models/blankets/hcpb.py index ce1419dfc3..2231bad585 100644 --- a/process/models/blankets/hcpb.py +++ b/process/models/blankets/hcpb.py @@ -56,6 +56,9 @@ def run(self, output: bool = False): blanket_vars.deg_blkt_outboard_poloidal_plasma = ( self.blkt_outboard_poloidal_plasma_angle ) + blanket_vars.f_deg_blkt_outboard_poloidal_plasma = ( + self.f_deg_blkt_outboard_poloidal_plasma + ) blanket_vars.deg_blkt_inboard_poloidal_plasma = ( self.calculate_blkt_inboard_poloidal_plasma_angle( @@ -65,6 +68,10 @@ def run(self, output: bool = False): ) ) + blanket_vars.f_deg_blkt_inboard_poloidal_plasma = ( + blanket_vars.deg_blkt_inboard_poloidal_plasma / 360.0 + ) + dia_blkt_channel = self.pipe_hydraulic_diameter(i_channel_shape=1) fwbs_variables.radius_blkt_channel = dia_blkt_channel / 2 ( From 7dc5212e42f020aff5cf5ebc06e7873a90b0769d Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 13:12:01 +0100 Subject: [PATCH 12/17] Adjust font sizes and z-order for blanket and divertor angle labels in structure plot Co-authored-by: Copilot --- process/core/io/plot/summary.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index 59ad976773..7b3fa07308 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13837,7 +13837,7 @@ def plot_blkt_structure( label_x, label_y, f"{deg_blkt_outboard_poloidal_plasma:.1f}°\n({f_deg_blkt_outboard_poloidal_plasma * 100:.1f}%)", - fontsize=8, + fontsize=7, color="purple", ha="center", va="center", @@ -13888,7 +13888,7 @@ def plot_blkt_structure( label_x, label_y, f"{deg_blkt_inboard_poloidal_plasma:.1f}°\n({f_deg_blkt_inboard_poloidal_plasma * 100:.1f}%)", - fontsize=8, + fontsize=7, color="green", ha="center", va="center", @@ -13900,6 +13900,7 @@ def plot_blkt_structure( "edgecolor": "green", "linewidth": 1.5, }, + zorder=5, ) # Plot arc showing the angle between the two arrows (divertor angle) @@ -13923,7 +13924,7 @@ def plot_blkt_structure( label_x, label_y, f"{deg_div_poloidal_plasma:.1f}°\n({f_ster_div_single * 100:.1f}%)", - fontsize=8, + fontsize=7, color="black", ha="center", va="center", @@ -13935,6 +13936,7 @@ def plot_blkt_structure( "edgecolor": "black", "linewidth": 1.5, }, + zorder=5, ) # Plot vertical lines at the inner and outer radial boundaries of the blanket From 4a3fd63dfd9e86e4a874eeac17f16e3d2d895007 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 13:45:50 +0100 Subject: [PATCH 13/17] Enhance BLKT structure plotting by adding poloidal angle annotations for outboard, inboard, and divertor angles Co-authored-by: Copilot --- process/core/io/plot/summary.py | 57 ++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/process/core/io/plot/summary.py b/process/core/io/plot/summary.py index 7b3fa07308..3aff8460a3 100644 --- a/process/core/io/plot/summary.py +++ b/process/core/io/plot/summary.py @@ -13741,7 +13741,8 @@ def plot_blkt_structure( radial_build: dict[str, float], colour_scheme: Literal[1, 2], ): - """Plot the BLKT structure on the given axis.""" + """Plot the blkt structure and relevant angles""" + # MFILE variables needed to plot the blkt structure and angles rmajor = m_file.get("rmajor", scan=scan) rminor = m_file.get("rminor", scan=scan) dr_fw_plasma_gap_outboard = m_file.get("dr_fw_plasma_gap_outboard", scan=scan) @@ -13765,10 +13766,14 @@ def plot_blkt_structure( ) deg_div_poloidal_plasma = m_file.get("deg_div_poloidal_plasma", scan=scan) f_ster_div_single = m_file.get("f_ster_div_single", scan=scan) + i_single_null = m_file.get("i_single_null", scan=scan) + + # ====================== plot_blanket(ax, m_file, scan, radial_build, colour_scheme) plot_plasma(ax, m_file, scan, 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") @@ -13800,6 +13805,7 @@ def plot_blkt_structure( label="Blanket Half Height", ) + # Plot arrows for the outboard blanket angles ax.annotate( "", xy=(rmajor, 0), @@ -13816,7 +13822,7 @@ def plot_blkt_structure( zorder=5, ) - # Plot arc showing the angle between the two arrows + # Plot arc showing the angle between the two outboard blanket arrows arc_radius = 1.0 angle_start = -deg_blkt_outboard_poloidal_plasma / 2 angle_end = deg_blkt_outboard_poloidal_plasma / 2 @@ -13833,6 +13839,7 @@ def plot_blkt_structure( label_x = rmajor + label_radius * np.cos(mid_angle) label_y = label_radius * np.sin(mid_angle) + # Plot the info box for the outboard blanket ax.text( label_x, label_y, @@ -13851,6 +13858,7 @@ def plot_blkt_structure( }, ) + # Plot arrows for the inboard blanket angles ax.annotate( "", xy=(rmajor, 0), @@ -13867,7 +13875,7 @@ def plot_blkt_structure( zorder=5, ) - # Plot arc showing the angle between the two arrows + # Plot arc showing the angle between the two inboard blanket arrows arc_radius = 1.0 angle_start = -deg_blkt_inboard_poloidal_plasma / 2 angle_end = deg_blkt_inboard_poloidal_plasma / 2 @@ -13884,6 +13892,7 @@ def plot_blkt_structure( label_x = rmajor - label_radius * np.cos(mid_angle) label_y = label_radius * np.sin(mid_angle) + # Plot the info box for the inboard blanket ax.text( label_x, label_y, @@ -13903,7 +13912,46 @@ def plot_blkt_structure( zorder=5, ) - # Plot arc showing the angle between the two arrows (divertor angle) + # Plot arrows for the divertor angles + # If double null then plot the upper also + if i_single_null == 0: + # Plot arc showing the angle between the two arrows (divertor angle) + arc_radius = 1.5 + angle_start = deg_blkt_outboard_poloidal_plasma / 2 + deg_div_poloidal_plasma + angle_end = deg_blkt_inboard_poloidal_plasma / 2 + deg_div_poloidal_plasma + + theta = np.linspace(np.deg2rad(angle_start), np.deg2rad(angle_end), 50) + arc_x = rmajor + arc_radius * np.cos(theta) + arc_y = arc_radius * np.sin(theta) + + ax.plot(arc_x, arc_y, color="black", linewidth=2) + + # Add angle label at the arc + mid_angle = np.deg2rad((angle_start + angle_end) / 2) + label_radius = arc_radius * 1.8 + label_x = rmajor + label_radius * np.cos(mid_angle) + label_y = label_radius * np.sin(mid_angle) + + ax.text( + label_x, + label_y, + f"{deg_div_poloidal_plasma:.1f}°\n({f_ster_div_single * 100:.1f}%)", + fontsize=7, + color="black", + ha="center", + va="center", + weight="bold", + bbox={ + "boxstyle": "round", + "facecolor": "white", + "alpha": 0.8, + "edgecolor": "black", + "linewidth": 1.5, + }, + zorder=5, + ) + + # Plot arc showing the angle between the two arrows for the lower divertor (divertor angle) arc_radius = 1.5 angle_start = -deg_blkt_outboard_poloidal_plasma / 2 - deg_div_poloidal_plasma angle_end = -deg_blkt_inboard_poloidal_plasma / 2 - deg_div_poloidal_plasma @@ -13920,6 +13968,7 @@ def plot_blkt_structure( label_x = rmajor + label_radius * np.cos(mid_angle) label_y = label_radius * np.sin(mid_angle) + # Plot the info box for the lower divertor angle ax.text( label_x, label_y, From c3f823bda44f6821f92e5a351ec6d84e33917e38 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 14:49:04 +0100 Subject: [PATCH 14/17] Fix calculation of single divertor angle to use inboard blanket poloidal angle Co-authored-by: Copilot --- process/models/divertor.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/process/models/divertor.py b/process/models/divertor.py index 52dc58a700..06ebefa0cf 100644 --- a/process/models/divertor.py +++ b/process/models/divertor.py @@ -96,16 +96,10 @@ def run(self, output: bool = False): def single_divertor_angle(self): """ Calculate the angle subtended by a single divertor. - Angle is calculated as 360 degrees minus the sum of the inboard - and outboard blanket poloidal angles, divided by 2 (for two divertors). + Angle is calculated as 180 degrees minus the inboard + blanket poloidal angle, divided by 2 (for two divertors). """ - return ( - 360.0 - - ( - blanket_library.deg_blkt_inboard_poloidal_plasma - + blanket_library.deg_blkt_outboard_poloidal_plasma - ) - ) / 2.0 + return (180.0 - blanket_library.deg_blkt_inboard_poloidal_plasma) / 2.0 def divtart( self, From ff8b4ede8ac85714d47e18b112483f3536d494f4 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 14:53:39 +0100 Subject: [PATCH 15/17] Add unit test for calculating inboard blanket poloidal plasma angle Co-authored-by: Copilot --- .../models/blankets/test_blanket_library.py | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/unit/models/blankets/test_blanket_library.py b/tests/unit/models/blankets/test_blanket_library.py index 8020818736..d92fb833e0 100644 --- a/tests/unit/models/blankets/test_blanket_library.py +++ b/tests/unit/models/blankets/test_blanket_library.py @@ -12,7 +12,7 @@ from process.data_structure import build_variables as bv from process.data_structure import fwbs_variables as fwbs from process.data_structure import physics_variables as pv -from process.models.blankets.blanket_library import BlanketLibrary +from process.models.blankets.blanket_library import BlanketLibrary, InboardBlanket from process.models.fw import FirstWall @@ -1684,3 +1684,48 @@ def test_liquid_breeder_properties_part_3(monkeypatch, blanket_library_fixture): blanket_library_fixture.liquid_breeder_properties() assert pytest.approx(fwbs.den_liq, rel=1e-3) == 504.0 + + +class CalculateBlktInboardPoloidalPlasmaAngleParam(NamedTuple): + rminor: Any = None + dz_blkt_half: Any = None + dr_fw_plasma_gap_inboard: Any = None + expected_angle: Any = None + + +@pytest.mark.parametrize( + "calculate_blkt_inboard_poloidal_plasma_angle_param", + [ + CalculateBlktInboardPoloidalPlasmaAngleParam( + rminor=2.0, + dz_blkt_half=0.0, + dr_fw_plasma_gap_inboard=0.25, + expected_angle=0.0, + ), + CalculateBlktInboardPoloidalPlasmaAngleParam( + rminor=2.0, + dz_blkt_half=2.25, # dz = rminor + gap -> 2 * atan(1) = 90 deg + dr_fw_plasma_gap_inboard=0.25, + expected_angle=90.0, + ), + CalculateBlktInboardPoloidalPlasmaAngleParam( + rminor=2.0, + dz_blkt_half=np.sqrt(3.0) * 2.25, # dz = sqrt(3) * (rminor + gap) -> 120 deg + dr_fw_plasma_gap_inboard=0.25, + expected_angle=120.0, + ), + ], +) +def test_calculate_blkt_inboard_poloidal_plasma_angle( + calculate_blkt_inboard_poloidal_plasma_angle_param, +): + """Test for calculate_blkt_inboard_poloidal_plasma_angle.""" + result = InboardBlanket.calculate_blkt_inboard_poloidal_plasma_angle( + rminor=calculate_blkt_inboard_poloidal_plasma_angle_param.rminor, + dz_blkt_half=calculate_blkt_inboard_poloidal_plasma_angle_param.dz_blkt_half, + dr_fw_plasma_gap_inboard=calculate_blkt_inboard_poloidal_plasma_angle_param.dr_fw_plasma_gap_inboard, + ) + + assert result == pytest.approx( + calculate_blkt_inboard_poloidal_plasma_angle_param.expected_angle + ) From da28c9e9785df695b070ea0e32b876f3d373764d Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 15:03:13 +0100 Subject: [PATCH 16/17] Remove obsolete variable 'f_ster_div_single' from input variables and mark it as deprecated Co-authored-by: Copilot --- process/core/input.py | 3 --- process/core/io/obsolete_vars.py | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/process/core/input.py b/process/core/input.py index 825efef1df..338ef6ea18 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -764,9 +764,6 @@ def __post_init__(self): "fjohc0": InputVariable( data_structure.constraint_variables, float, range=(0.001, 1.0) ), - "f_ster_div_single": InputVariable( - data_structure.fwbs_variables, float, range=(0.0, 1.0) - ), "fdiva": InputVariable(data_structure.divertor_variables, float, range=(0.1, 2.0)), "fdivwet": InputVariable( data_structure.stellarator_variables, float, range=(0.01, 1.0) diff --git a/process/core/io/obsolete_vars.py b/process/core/io/obsolete_vars.py index 98525c1275..882681d47a 100644 --- a/process/core/io/obsolete_vars.py +++ b/process/core/io/obsolete_vars.py @@ -448,6 +448,7 @@ "vcool": "vel_cp_coolant_midplane", "rcool": "radius_cp_coolant_channel", "fl_h_threshold": None, + "f_ster_div_single": None, } OBS_VARS_HELP = { From d5eb5b7e429c637ef714c4e91d12e6c89718c144 Mon Sep 17 00:00:00 2001 From: mn3981 Date: Tue, 28 Apr 2026 16:05:46 +0100 Subject: [PATCH 17/17] Add calculations for blanket poloidal plasma angles in DCLL class --- process/models/blankets/dcll.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/process/models/blankets/dcll.py b/process/models/blankets/dcll.py index c951eb3e90..6935756f96 100644 --- a/process/models/blankets/dcll.py +++ b/process/models/blankets/dcll.py @@ -2,6 +2,7 @@ from process.core import ( process_output as po, ) +from process.data_structure import blanket_library as blanket_vars from process.data_structure import ( build_variables, current_drive_variables, @@ -94,6 +95,27 @@ def output(self): def run(self, output: bool = False): self.component_volumes() + + # If Shfranov shift is added, the angle formula can be used where the shift is added to the minor radius. For now, the shift is neglected and the angle is calculated using the minor radius only. + blanket_vars.deg_blkt_outboard_poloidal_plasma = ( + self.blkt_outboard_poloidal_plasma_angle + ) + blanket_vars.f_deg_blkt_outboard_poloidal_plasma = ( + self.f_deg_blkt_outboard_poloidal_plasma + ) + + blanket_vars.deg_blkt_inboard_poloidal_plasma = ( + self.calculate_blkt_inboard_poloidal_plasma_angle( + rminor=physics_variables.rminor, + dz_blkt_half=blanket_vars.dz_blkt_half, + dr_fw_plasma_gap_inboard=build_variables.dr_fw_plasma_gap_inboard, + ) + ) + + blanket_vars.f_deg_blkt_inboard_poloidal_plasma = ( + blanket_vars.deg_blkt_inboard_poloidal_plasma / 360.0 + ) + dia_blkt_channel = self.pipe_hydraulic_diameter(i_channel_shape=1) fwbs_variables.radius_blkt_channel = dia_blkt_channel / 2 (