From bf27a11276ea4bee0132ec8d9528b3253c654421 Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 12:13:58 +0000 Subject: [PATCH 01/12] now using center point instead of z_pos and added edge filleting --- .../port_cutters_circular.py | 23 +++++++++--------- .../port_cutters_rectangular.py | 24 ++++++++++++------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/paramak/parametric_components/port_cutters_circular.py b/paramak/parametric_components/port_cutters_circular.py index b6aa508d0..3591250fb 100644 --- a/paramak/parametric_components/port_cutters_circular.py +++ b/paramak/parametric_components/port_cutters_circular.py @@ -7,23 +7,22 @@ class PortCutterCircular(ExtrudeCircleShape): other components (eg. blanket, vessel,..) in order to create ports. Args: - z_pos (float): Z position (cm) of the port - height (float): height (cm) of the port - width (float): width (cm) of the port - distance (float): extruded distance (cm) of the cutter - stp_filename (str, optional): defaults to "PortCutterCircular.stp". - stl_filename (str, optional): defaults to "PortCutterCircular.stl". - name (str, optional): defaults to "circular_port_cutter". - material_tag (str, optional): defaults to "circular_port_cutter_mat". - extrusion_start_offset (float, optional): the distance between 0 and + center_point: center point of the port cutter. Defaults to (0, 0). + radius: radius (cm) of port cutter. + distance: extruded distance (cm) of the port cutter. + stp_filename: defaults to "PortCutterCircular.stp". + stl_filename: defaults to "PortCutterCircular.stl". + name: defaults to "circular_port_cutter". + material_tag: defaults to "circular_port_cutter_mat". + extrusion_start_offset: the distance between 0 and the start of the extrusion. Defaults to 1.. """ def __init__( self, - z_pos, radius, distance, + center_point=(0, 0), workplane="ZY", rotation_axis="Z", extrusion_start_offset=1., @@ -47,8 +46,8 @@ def __init__( **kwargs ) - self.z_pos = z_pos + self.center_point = center_point self.radius = radius def find_points(self): - self.points = [(0, self.z_pos)] + self.points = [self.center_point] diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 4ac5fc9b4..5b3d867bb 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -7,10 +7,10 @@ class PortCutterRectangular(ExtrudeStraightShape): other components (eg. blanket, vessel,..) in order to create ports. Args: - z_pos (float): Z position (cm) of the port - height (float): height (cm) of the port - width (float): width (cm) of the port - distance (float): extruded distance (cm) of the cutter + center_point: Center point of the port cutter. Defaults to (0, 0). + height: height (cm) of the port cutter. + width: width (cm) of the port cutter. + distance: extruded distance (cm) of the port cutter. fillet_radius (float, optional): If not None, radius (cm) of fillets added to edges orthogonal to the Z direction. Defaults to None. stp_filename (str, optional): defaults to "PortCutterRectangular.stp". @@ -24,10 +24,10 @@ class PortCutterRectangular(ExtrudeStraightShape): def __init__( self, - z_pos, height, width, distance, + center_point=(0, 0), workplane="ZY", rotation_axis="Z", extrusion_start_offset=1., @@ -52,7 +52,7 @@ def __init__( **kwargs ) - self.z_pos = z_pos + self.center_point = center_point self.height = height self.width = width self.fillet_radius = fillet_radius @@ -65,9 +65,17 @@ def find_points(self): (self.width / 2, self.height / 2), (-self.width / 2, self.height / 2), ] - points = [(e[0], e[1] + self.z_pos) for e in points] + points = [(e[0] + self.center_point[0], e[1] + + self.center_point[1]) for e in points] self.points = points def add_fillet(self): + if "X" not in self.workplane: + filleting_edge = "|X" + if "Y" not in self.workplane: + filleting_edge = "|Y" + if "Z" not in self.workplane: + filleting_edge = "|Z" + if self.fillet_radius is not None and self.fillet_radius != 0: - self.solid = self.solid.edges('#Z').fillet(self.fillet_radius) + self.solid = self.solid.edges(filleting_edge).fillet(self.fillet_radius) From 5ec94e584e58a9c6be936eb3179a2d56b9dbbd37 Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 12:19:25 +0000 Subject: [PATCH 02/12] added type hinting --- .../port_cutters_circular.py | 22 +++++++++------- .../port_cutters_rectangular.py | 26 ++++++++++--------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/paramak/parametric_components/port_cutters_circular.py b/paramak/parametric_components/port_cutters_circular.py index 3591250fb..bf3290590 100644 --- a/paramak/parametric_components/port_cutters_circular.py +++ b/paramak/parametric_components/port_cutters_circular.py @@ -1,6 +1,8 @@ from paramak import ExtrudeCircleShape +from typing import Optional + class PortCutterCircular(ExtrudeCircleShape): """Creates an extruded shape with a circular section that is used to cut @@ -20,16 +22,16 @@ class PortCutterCircular(ExtrudeCircleShape): def __init__( self, - radius, - distance, - center_point=(0, 0), - workplane="ZY", - rotation_axis="Z", - extrusion_start_offset=1., - stp_filename="PortCutterCircular.stp", - stl_filename="PortCutterCircular.stl", - name="circular_port_cutter", - material_tag="circular_port_cutter_mat", + radius: float, + distance: float, + center_point: Optional[tuple] = (0, 0), + workplane: Optional[str] = "ZY", + rotation_axis: Optional[str] = "Z", + extrusion_start_offset: Optional[float] = 1., + stp_filename: Optional[str] = "PortCutterCircular.stp", + stl_filename: Optional[str] = "PortCutterCircular.stl", + name: Optional[str] = "circular_port_cutter", + material_tag: Optional[str] = "circular_port_cutter_mat", **kwargs ): super().__init__( diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 5b3d867bb..6cfe28307 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -1,6 +1,8 @@ from paramak import ExtrudeStraightShape +from typing import Optional + class PortCutterRectangular(ExtrudeStraightShape): """Creates an extruded shape with a rectangular section that is used to cut @@ -24,18 +26,18 @@ class PortCutterRectangular(ExtrudeStraightShape): def __init__( self, - height, - width, - distance, - center_point=(0, 0), - workplane="ZY", - rotation_axis="Z", - extrusion_start_offset=1., - fillet_radius=None, - stp_filename="PortCutterRectangular.stp", - stl_filename="PortCutterRectangular.stl", - name="rectangular_port_cutter", - material_tag="rectangular_port_cutter_mat", + height: float, + width: float, + distance: float, + center_point: Optional[tuple] = (0, 0), + workplane: Optional[str] = "ZY", + rotation_axis: Optional[str] = "Z", + extrusion_start_offset: Optional[float] = 1., + fillet_radius: Optional[float] = None, + stp_filename: Optional[str] = "PortCutterRectangular.stp", + stl_filename: Optional[str] = "PortCutterRectangular.stl", + name: Optional[str] = "rectangular_port_cutter", + material_tag: Optional[str] = "rectangular_port_cutter_mat", **kwargs ): From 854fb54a2e858a40d0a77ad31620cb65c88fb8ee Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 12:22:33 +0000 Subject: [PATCH 03/12] added port cutter tests --- .../test_PortCutterCircular.py | 61 +++++++++++++++---- .../test_PortCutterRectangular.py | 58 ++++++++++++++---- 2 files changed, 96 insertions(+), 23 deletions(-) diff --git a/tests/test_parametric_components/test_PortCutterCircular.py b/tests/test_parametric_components/test_PortCutterCircular.py index a6d5e7197..09b8eac04 100644 --- a/tests/test_parametric_components/test_PortCutterCircular.py +++ b/tests/test_parametric_components/test_PortCutterCircular.py @@ -1,19 +1,56 @@ - +import math import unittest import paramak +import pytest + + +class test_component(unittest.TestCase): + + def setUp(self): + self.test_shape = paramak.PortCutterCircular( + distance=300, radius=20 + ) + + def test_default_parameters(self): + """Checks that the default parameters of a PortCutterCircular are correct.""" + + assert self.test_shape.center_point == (0, 0) + assert self.test_shape.workplane == "ZY" + assert self.test_shape.rotation_axis == "Z" + assert self.test_shape.extrusion_start_offset == 1 + assert self.test_shape.stp_filename == "PortCutterCircular.stp" + assert self.test_shape.stl_filename == "PortCutterCircular.stl" + assert self.test_shape.name == "circular_port_cutter" + assert self.test_shape.material_tag == "circular_port_cutter_mat" + + def test_creation(self): + """Creates a circular port cutter using the PortCutterCircular parametric + component and checks that a cadquery solid is created.""" + + assert self.test_shape.solid is not None + assert self.test_shape.volume > 1000 + + def test_relative_volume(self): + """Creates PortCutterCircular shapes and checks that their relative volumes + are correct.""" + + test_volume = self.test_shape.volume + + self.test_shape.extrusion_start_offset = 20 + self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] + + assert self.test_shape.volume == pytest.approx(test_volume * 4) + + def test_absolute_volume(self): + """Creates a PortCutterCircular shape and checks that its volume is correct.""" -# class test_component(unittest.TestCase): -# TODO: fix issue 548 -# def test_creation(self): -# """Checks a PortCutterCircular creation.""" + assert self.test_shape.volume == pytest.approx(math.pi * (20**2) * 300) -# test_component = paramak.PortCutterCircular( -# distance=3, -# z_pos=0.25, -# radius=0.1, -# azimuth_placement_angle=[0, 45, 90, 180] -# ) + self.test_shape.extrusion_start_offset = 20 + self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] + self.test_shape.radius = 10 -# assert test_component.solid is not None + assert self.test_shape.volume == pytest.approx( + math.pi * (10**2) * 300 * 4) \ No newline at end of file diff --git a/tests/test_parametric_components/test_PortCutterRectangular.py b/tests/test_parametric_components/test_PortCutterRectangular.py index 0f927ccc3..f1274d21e 100644 --- a/tests/test_parametric_components/test_PortCutterRectangular.py +++ b/tests/test_parametric_components/test_PortCutterRectangular.py @@ -3,19 +3,55 @@ import paramak +import pytest + class TestPortCutterRectangular(unittest.TestCase): - def test_creation(self): - """Checks a PortCutterRectangular creation.""" - - test_component = paramak.PortCutterRectangular( - distance=3, - z_pos=0, - height=0.2, - width=0.4, - fillet_radius=0.02, - azimuth_placement_angle=[0, 45, 90, 180] + def setUp(self): + self.test_shape = paramak.PortCutterRectangular( + width=40, height=40, distance=300 ) - assert test_component.solid is not None + def test_default_parameters(self): + """Checks that the default parameters of a PortCutterRectangular are correct.""" + + assert self.test_shape.center_point == (0, 0) + assert self.test_shape.workplane == "ZY" + assert self.test_shape.rotation_axis == "Z" + assert self.test_shape.extrusion_start_offset == 1 + assert self.test_shape.fillet_radius is None + assert self.test_shape.stp_filename == "PortCutterRectangular.stp" + assert self.test_shape.stl_filename == "PortCutterRectangular.stl" + assert self.test_shape.name == "rectangular_port_cutter" + assert self.test_shape.material_tag == "rectangular_port_cutter_mat" + + def test_creation(self): + """Creates a rectangular port cutter using the PortCutterRectangular parametric + component and checks that a cadquery solid is created.""" + + assert self.test_shape.solid is not None + assert self.test_shape.volume > 1000 + + def test_relative_volume(self): + """Creates PortCutterRectangular shapes and checks that their relative volumes + are correct.""" + + test_volume = self.test_shape.volume + + self.test_shape.extrusion_start_offset = 20 + self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] + + assert self.test_shape.volume == pytest.approx(test_volume * 4) + + def test_absolute_volume(self): + """Creates a PortCutterRectangular shape and checks that its volume is correct.""" + + assert self.test_shape.volume == pytest.approx(40 * 40 * 300) + + self.test_shape.extrusion_start_offset = 20 + self.test_shape.azimuth_placement_angle = [0, 90, 180, 270] + self.test_shape.width = 20 + self.test_shape.height = 20 + + assert self.test_shape.volume == pytest.approx(20 * 20 * 300 * 4) \ No newline at end of file From 31b726c241231ee91a945281c95e074535f0cb01 Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 12:24:21 +0000 Subject: [PATCH 04/12] moved point at which filleting is performed --- paramak/parametric_components/port_cutters_rectangular.py | 2 +- paramak/parametric_shapes/extruded_mixed_shape.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 6cfe28307..08c7cfcf6 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -58,7 +58,7 @@ def __init__( self.height = height self.width = width self.fillet_radius = fillet_radius - self.add_fillet() + # self.add_fillet() def find_points(self): points = [ diff --git a/paramak/parametric_shapes/extruded_mixed_shape.py b/paramak/parametric_shapes/extruded_mixed_shape.py index 0e19acc2c..22ae06f15 100644 --- a/paramak/parametric_shapes/extruded_mixed_shape.py +++ b/paramak/parametric_shapes/extruded_mixed_shape.py @@ -88,6 +88,11 @@ def create_solid(self): solid = wire.extrude( distance=extrusion_distance, both=self.extrude_both) + + # filleting rectangular port cutter edges + # must be done before azimuthal placement + if hasattr(self, "add_fillet"): + solid = self.add_fillet(solid) solid = self.rotate_solid(solid) cutting_wedge = calculate_wedge_cut(self) From 68802292fda437e36ed6f5bcfe02b3986ec53ca2 Mon Sep 17 00:00:00 2001 From: autopep8 Date: Thu, 4 Feb 2021 12:27:52 +0000 Subject: [PATCH 05/12] Automated autopep8 fixes --- paramak/parametric_components/port_cutters_rectangular.py | 3 ++- paramak/parametric_shapes/extruded_mixed_shape.py | 2 +- tests/test_parametric_components/test_PortCutterCircular.py | 2 +- tests/test_parametric_components/test_PortCutterRectangular.py | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 08c7cfcf6..2003862d3 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -80,4 +80,5 @@ def add_fillet(self): filleting_edge = "|Z" if self.fillet_radius is not None and self.fillet_radius != 0: - self.solid = self.solid.edges(filleting_edge).fillet(self.fillet_radius) + self.solid = self.solid.edges( + filleting_edge).fillet(self.fillet_radius) diff --git a/paramak/parametric_shapes/extruded_mixed_shape.py b/paramak/parametric_shapes/extruded_mixed_shape.py index 22ae06f15..027d5d362 100644 --- a/paramak/parametric_shapes/extruded_mixed_shape.py +++ b/paramak/parametric_shapes/extruded_mixed_shape.py @@ -88,7 +88,7 @@ def create_solid(self): solid = wire.extrude( distance=extrusion_distance, both=self.extrude_both) - + # filleting rectangular port cutter edges # must be done before azimuthal placement if hasattr(self, "add_fillet"): diff --git a/tests/test_parametric_components/test_PortCutterCircular.py b/tests/test_parametric_components/test_PortCutterCircular.py index 09b8eac04..a4d25af4a 100644 --- a/tests/test_parametric_components/test_PortCutterCircular.py +++ b/tests/test_parametric_components/test_PortCutterCircular.py @@ -53,4 +53,4 @@ def test_absolute_volume(self): self.test_shape.radius = 10 assert self.test_shape.volume == pytest.approx( - math.pi * (10**2) * 300 * 4) \ No newline at end of file + math.pi * (10**2) * 300 * 4) diff --git a/tests/test_parametric_components/test_PortCutterRectangular.py b/tests/test_parametric_components/test_PortCutterRectangular.py index f1274d21e..9b21016af 100644 --- a/tests/test_parametric_components/test_PortCutterRectangular.py +++ b/tests/test_parametric_components/test_PortCutterRectangular.py @@ -54,4 +54,4 @@ def test_absolute_volume(self): self.test_shape.width = 20 self.test_shape.height = 20 - assert self.test_shape.volume == pytest.approx(20 * 20 * 300 * 4) \ No newline at end of file + assert self.test_shape.volume == pytest.approx(20 * 20 * 300 * 4) From 7e3f4ee56dab31f0f8b8603179ab9c5159a4bb0a Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 12:38:47 +0000 Subject: [PATCH 06/12] using solid instead of self.solid --- paramak/parametric_components/port_cutters_rectangular.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 08c7cfcf6..1f6794aa7 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -71,7 +71,7 @@ def find_points(self): self.center_point[1]) for e in points] self.points = points - def add_fillet(self): + def add_fillet(self, solid): if "X" not in self.workplane: filleting_edge = "|X" if "Y" not in self.workplane: @@ -80,4 +80,5 @@ def add_fillet(self): filleting_edge = "|Z" if self.fillet_radius is not None and self.fillet_radius != 0: - self.solid = self.solid.edges(filleting_edge).fillet(self.fillet_radius) + solid = solid.edges(filleting_edge).fillet(self.fillet_radius) + return solid From 52f6d32011892c02fd6c0f16a66ec301f900fe5c Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 12:40:26 +0000 Subject: [PATCH 07/12] using solid instead of self.solid --- paramak/parametric_components/port_cutters_rectangular.py | 2 ++ paramak/parametric_shapes/extruded_mixed_shape.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 1f6794aa7..303130803 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -81,4 +81,6 @@ def add_fillet(self, solid): if self.fillet_radius is not None and self.fillet_radius != 0: solid = solid.edges(filleting_edge).fillet(self.fillet_radius) + return solid + diff --git a/paramak/parametric_shapes/extruded_mixed_shape.py b/paramak/parametric_shapes/extruded_mixed_shape.py index 22ae06f15..027d5d362 100644 --- a/paramak/parametric_shapes/extruded_mixed_shape.py +++ b/paramak/parametric_shapes/extruded_mixed_shape.py @@ -88,7 +88,7 @@ def create_solid(self): solid = wire.extrude( distance=extrusion_distance, both=self.extrude_both) - + # filleting rectangular port cutter edges # must be done before azimuthal placement if hasattr(self, "add_fillet"): From efcb4119f184b102eb8d06e4ea02003ccd033101 Mon Sep 17 00:00:00 2001 From: autopep8 Date: Thu, 4 Feb 2021 12:42:43 +0000 Subject: [PATCH 08/12] Automated autopep8 fixes --- paramak/parametric_components/port_cutters_rectangular.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/paramak/parametric_components/port_cutters_rectangular.py b/paramak/parametric_components/port_cutters_rectangular.py index 303130803..55ce4a741 100644 --- a/paramak/parametric_components/port_cutters_rectangular.py +++ b/paramak/parametric_components/port_cutters_rectangular.py @@ -81,6 +81,5 @@ def add_fillet(self, solid): if self.fillet_radius is not None and self.fillet_radius != 0: solid = solid.edges(filleting_edge).fillet(self.fillet_radius) - - return solid + return solid From dd4f6e7c7bca30eb9c5784d32ede19e28b857bbf Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 14:24:40 +0000 Subject: [PATCH 09/12] updated port arguments --- .../make_vacuum_vessel_with_ports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example_parametric_components/make_vacuum_vessel_with_ports.py b/examples/example_parametric_components/make_vacuum_vessel_with_ports.py index 9085eb41a..70ffdbca4 100644 --- a/examples/example_parametric_components/make_vacuum_vessel_with_ports.py +++ b/examples/example_parametric_components/make_vacuum_vessel_with_ports.py @@ -25,7 +25,7 @@ def main(): # makes the middle row of ports circular_ports = paramak.PortCutterCircular( distance=5, - z_pos=0, + center_point=(0, 0), radius=0.2, azimuth_placement_angle=angles_for_ports ) @@ -33,7 +33,7 @@ def main(): # makes the lower row of ports rectangular_ports = paramak.PortCutterRectangular( distance=5, - z_pos=-1, + center_point=(0, 0), height=0.3, width=0.4, fillet_radius=0.08, From db55b43c224dd116b2032b6706a9d5e88274023b Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Thu, 4 Feb 2021 14:43:00 +0000 Subject: [PATCH 10/12] updated port center points --- .../make_all_parametric_components.py | 4 ++-- .../make_vacuum_vessel_with_ports.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/example_parametric_components/make_all_parametric_components.py b/examples/example_parametric_components/make_all_parametric_components.py index bcee900e0..4160bc5eb 100644 --- a/examples/example_parametric_components/make_all_parametric_components.py +++ b/examples/example_parametric_components/make_all_parametric_components.py @@ -334,7 +334,7 @@ def main(): component = paramak.PortCutterRectangular( distance=3, - z_pos=0, + center_point=(0, 0), height=0.2, width=0.4, fillet_radius=0.02, @@ -344,7 +344,7 @@ def main(): component = paramak.PortCutterCircular( distance=3, - z_pos=0.25, + center_point=(0.25, 0), radius=0.1, # azimuth_placement_angle=[0, 45, 90, 180], # TODO: fix issue #548 azimuth_placement_angle=[0, 45, 90], diff --git a/examples/example_parametric_components/make_vacuum_vessel_with_ports.py b/examples/example_parametric_components/make_vacuum_vessel_with_ports.py index 70ffdbca4..16b3d2b61 100644 --- a/examples/example_parametric_components/make_vacuum_vessel_with_ports.py +++ b/examples/example_parametric_components/make_vacuum_vessel_with_ports.py @@ -33,7 +33,7 @@ def main(): # makes the lower row of ports rectangular_ports = paramak.PortCutterRectangular( distance=5, - center_point=(0, 0), + center_point=(-1, 0), height=0.3, width=0.4, fillet_radius=0.08, From 1a5d17eda9d17624038d22fa7e48b22a634daf30 Mon Sep 17 00:00:00 2001 From: billingsley-john Date: Fri, 5 Feb 2021 16:28:21 +0000 Subject: [PATCH 11/12] added ball reactor with ports --- paramak/__init__.py | 1 + paramak/parametric_reactors/ball_reactor.py | 4 ++ .../ball_reactor_with_ports.py | 69 +++++++++++++++++++ paramak/utils.py | 57 +++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 paramak/parametric_reactors/ball_reactor_with_ports.py diff --git a/paramak/__init__.py b/paramak/__init__.py index 52c7e4490..0229848c5 100644 --- a/paramak/__init__.py +++ b/paramak/__init__.py @@ -77,6 +77,7 @@ from .parametric_components.shell_fs import ShellFS from .parametric_reactors.ball_reactor import BallReactor +from .parametric_reactors.ball_reactor_with_ports import BallReactorWithPorts from .parametric_reactors.submersion_reactor import SubmersionTokamak from .parametric_reactors.single_null_submersion_reactor import SingleNullSubmersionTokamak from .parametric_reactors.single_null_ball_reactor import SingleNullBallReactor diff --git a/paramak/parametric_reactors/ball_reactor.py b/paramak/parametric_reactors/ball_reactor.py index 6cae0fb92..f157e5511 100644 --- a/paramak/parametric_reactors/ball_reactor.py +++ b/paramak/parametric_reactors/ball_reactor.py @@ -2,6 +2,7 @@ import warnings import paramak +from paramak.utils import perform_port_cutting class BallReactor(paramak.Reactor): @@ -423,6 +424,9 @@ def _make_blankets_layers(self): cut=[self._center_column_cutter], ) + self._firstwall, self._blanket, self._blanket_rear_wall = perform_port_cutting( + self, self._firstwall, self._blanket, self._blanket_rear_wall) + return [self._firstwall, self._blanket, self._blanket_rear_wall] def _make_divertor(self): diff --git a/paramak/parametric_reactors/ball_reactor_with_ports.py b/paramak/parametric_reactors/ball_reactor_with_ports.py new file mode 100644 index 000000000..ba3cb49d0 --- /dev/null +++ b/paramak/parametric_reactors/ball_reactor_with_ports.py @@ -0,0 +1,69 @@ + +import warnings +from typing import Optional + +import numpy as np +import paramak +from paramak.utils import perform_port_cutting + + +class BallReactorWithPorts(paramak.BallReactor): + """Creates geometry for a simple ball reactor including a plasma, + cylindrical center column shielding, square toroidal field coils + and ports. There is no inboard breeder blanket on this ball reactor + like most spherical reactors. + + Arguments: + port_type: type of port to be cut. Defaults to None. + port_center_point: position of port center point in the workplane + given. Defaults to (0, 0). + port_radius: radius of circular ports. Defaults to None. + port_height: height of rectangular ports. Defaults to None. + port_width: width of rectangular ports. Defaults to None. + port_distance: extrusion distance of port cutter. Defaults to None. + port_azimuth_placement_angle: azimuthal placement angle of each port. + Defaults to None if no ports are created. Defaults to list of + equally spaced floats between 0 and 360 of length equal to + number_of_ports if number_of_ports is provided but + port_azimuth_placement_angle is not. + port_start_radius: extrusion start point of port cutter. Defaults + to major_radius. + port_fillet_radius: fillet radius of rectangular ports. Defaults to 0. + """ + + def __init__( + self, + port_type: Optional[str] = None, + port_center_point: Optional[tuple] = (0, 0), + port_radius: Optional[float] = None, + port_height: Optional[float] = None, + port_width: Optional[float] = None, + port_distance: Optional[float] = None, + port_azimuth_placement_angle: Optional[list] = None, + port_start_radius: Optional[float] = None, + port_fillet_radius: Optional[float] = 0, + **kwargs + ): + + super().__init__(**kwargs) + + self.port_type=port_type + self.port_center_point=port_center_point + self.port_radius=port_radius + self.port_height=port_height + self.port_width=port_width + self.port_distance=port_distance + self.port_azimuth_placement_angle=port_azimuth_placement_angle + self.port_start_radius=port_start_radius + self.port_fillet_radius=port_fillet_radius + + @property + def port_start_radius(self): + return self._port_start_radius + + @port_start_radius.setter + def port_start_radius(self, value): + if value is None: + self._port_start_radius = self.major_radius + else: + self._port_start_radius = value diff --git a/paramak/utils.py b/paramak/utils.py index 7ea02bbdd..e00be3a1b 100644 --- a/paramak/utils.py +++ b/paramak/utils.py @@ -619,6 +619,63 @@ def export_wire_to_html( return fig +def perform_port_cutting(self, *args): + + components = [] + + if self.port_type is None: + for component in args: + components.append(component) + if len(args) == 1: + return component + return components + + else: + if self.port_type == "circular": + if self.port_height is not None or self.port_width is not None: + raise ValueError('only port_radius should be specified') + if self.port_radius is None: + raise ValueError('port_radius must be specified') + + port_cutter = paramak.PortCutterCircular( + center_point=self.port_center_point, + radius=self.port_radius, + distance=self.port_distance, + extrusion_start_offset=self.port_start_radius, + azimuth_placement_angle=self.port_azimuth_placement_angle + ) + + elif self.port_type == "rectangular": + if self.port_radius is not None: + raise ValueError( + 'only port_height and port_width should be specified') + if self.port_height is None or self.port_width is None: + raise ValueError( + 'port_height and port_width must be specified') + + port_cutter = paramak.PortCutterRectangular( + center_point=self.port_center_point, + height=self.port_height, + width=self.port_width, + distance=self.port_distance, + extrusion_start_offset=self.port_start_radius, + fillet_radius=self.port_fillet_radius, + azimuth_placement_angle=self.port_azimuth_placement_angle + ) + + else: + raise ValueError('invalid port type') + + for component in args: + if component.cut is None: + component.cut = [port_cutter] + else: + component.cut.insert(0, port_cutter) + components.append(component) + if len(args) == 1: + return component + return components + class FaceAreaSelector(cq.Selector): """A custom CadQuery selector the selects faces based on their area with a From fe5cd770300f316c7a59b6e923085076b6faa6ca Mon Sep 17 00:00:00 2001 From: autopep8 Date: Fri, 5 Feb 2021 16:32:44 +0000 Subject: [PATCH 12/12] Automated autopep8 fixes --- .../ball_reactor_with_ports.py | 28 +++++++++---------- paramak/utils.py | 9 +++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/paramak/parametric_reactors/ball_reactor_with_ports.py b/paramak/parametric_reactors/ball_reactor_with_ports.py index ba3cb49d0..151f91ab6 100644 --- a/paramak/parametric_reactors/ball_reactor_with_ports.py +++ b/paramak/parametric_reactors/ball_reactor_with_ports.py @@ -10,20 +10,20 @@ class BallReactorWithPorts(paramak.BallReactor): """Creates geometry for a simple ball reactor including a plasma, cylindrical center column shielding, square toroidal field coils - and ports. There is no inboard breeder blanket on this ball reactor + and ports. There is no inboard breeder blanket on this ball reactor like most spherical reactors. Arguments: port_type: type of port to be cut. Defaults to None. - port_center_point: position of port center point in the workplane + port_center_point: position of port center point in the workplane given. Defaults to (0, 0). port_radius: radius of circular ports. Defaults to None. port_height: height of rectangular ports. Defaults to None. port_width: width of rectangular ports. Defaults to None. port_distance: extrusion distance of port cutter. Defaults to None. - port_azimuth_placement_angle: azimuthal placement angle of each port. - Defaults to None if no ports are created. Defaults to list of - equally spaced floats between 0 and 360 of length equal to + port_azimuth_placement_angle: azimuthal placement angle of each port. + Defaults to None if no ports are created. Defaults to list of + equally spaced floats between 0 and 360 of length equal to number_of_ports if number_of_ports is provided but port_azimuth_placement_angle is not. port_start_radius: extrusion start point of port cutter. Defaults @@ -47,15 +47,15 @@ def __init__( super().__init__(**kwargs) - self.port_type=port_type - self.port_center_point=port_center_point - self.port_radius=port_radius - self.port_height=port_height - self.port_width=port_width - self.port_distance=port_distance - self.port_azimuth_placement_angle=port_azimuth_placement_angle - self.port_start_radius=port_start_radius - self.port_fillet_radius=port_fillet_radius + self.port_type = port_type + self.port_center_point = port_center_point + self.port_radius = port_radius + self.port_height = port_height + self.port_width = port_width + self.port_distance = port_distance + self.port_azimuth_placement_angle = port_azimuth_placement_angle + self.port_start_radius = port_start_radius + self.port_fillet_radius = port_fillet_radius @property def port_start_radius(self): diff --git a/paramak/utils.py b/paramak/utils.py index e00be3a1b..17e202c87 100644 --- a/paramak/utils.py +++ b/paramak/utils.py @@ -619,6 +619,7 @@ def export_wire_to_html( return fig + def perform_port_cutting(self, *args): components = [] @@ -629,7 +630,7 @@ def perform_port_cutting(self, *args): if len(args) == 1: return component return components - + else: if self.port_type == "circular": if self.port_height is not None or self.port_width is not None: @@ -644,7 +645,7 @@ def perform_port_cutting(self, *args): extrusion_start_offset=self.port_start_radius, azimuth_placement_angle=self.port_azimuth_placement_angle ) - + elif self.port_type == "rectangular": if self.port_radius is not None: raise ValueError( @@ -652,7 +653,7 @@ def perform_port_cutting(self, *args): if self.port_height is None or self.port_width is None: raise ValueError( 'port_height and port_width must be specified') - + port_cutter = paramak.PortCutterRectangular( center_point=self.port_center_point, height=self.port_height, @@ -662,7 +663,7 @@ def perform_port_cutting(self, *args): fillet_radius=self.port_fillet_radius, azimuth_placement_angle=self.port_azimuth_placement_angle ) - + else: raise ValueError('invalid port type')