From 81b73c94d4842cd31e1c530ff2fa42c64f156fde Mon Sep 17 00:00:00 2001 From: shimwell Date: Fri, 13 Jan 2023 23:32:57 +0000 Subject: [PATCH 01/16] started class refactor --- .../flf_system_code_reactor.py | 33 ++- src/paramak/reactor.py | 223 +++--------------- 2 files changed, 51 insertions(+), 205 deletions(-) diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py index 86680a0a5..396290193 100644 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ b/src/paramak/parametric_reactors/flf_system_code_reactor.py @@ -43,7 +43,14 @@ def __init__( rotation_angle: Optional[float] = 180.0, ): - super().__init__([]) + super().__init__( + obj = None, + loc = None, + name = None, + color = None, + metadata=None, + ) + self.rotation_angle = rotation_angle self.inner_blanket_radius = inner_blanket_radius @@ -57,18 +64,18 @@ def __init__( self.lower_vv_thickness = lower_vv_thickness # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_blanket_radius", - "blanket_thickness", - "blanket_height", - "lower_blanket_thickness", - "upper_blanket_thickness", - "blanket_vv_gap", - "upper_vv_thickness", - "vv_thickness", - "lower_vv_thickness", - "rotation_angle", - ] + # self.input_variable_names: List[str] = self.input_variable_names + [ + # "inner_blanket_radius", + # "blanket_thickness", + # "blanket_height", + # "lower_blanket_thickness", + # "upper_blanket_thickness", + # "blanket_vv_gap", + # "upper_vv_thickness", + # "vv_thickness", + # "lower_vv_thickness", + # "rotation_angle", + # ] def create_solids(self): """Creates a list of paramak.Shape for components and saves it in diff --git a/src/paramak/reactor.py b/src/paramak/reactor.py index 1d660284e..6c0d6a8e5 100644 --- a/src/paramak/reactor.py +++ b/src/paramak/reactor.py @@ -1,4 +1,4 @@ -from collections.abc import Iterable + from pathlib import Path from typing import List, Optional, Tuple, Union @@ -9,125 +9,46 @@ import paramak from paramak.utils import ( _replace, - get_hash, - get_bounding_box, - get_largest_dimension, export_solids_to_brep, export_solids_to_dagmc_h5m, ) +from typing import Union, Optional, List, Dict, Any +from cadquery.occ_impl.geom import Location +from cadquery.occ_impl.assembly import Color + +from cadquery import Workplane +from cadquery.occ_impl.shapes import Shape, Compound +AssemblyObjects = Union[Shape, Workplane, None] -class Reactor: - """The Reactor object allows shapes and components to be added and then - collective operations to be performed on them. Combining all the shapes is - required for creating images of the whole reactor. +class Reactor(cq.Assembly): + """The Reactor object is an extended CadQuery Assembly object. The + additional functionality allows shapes and components to be exported to + a variety of additional formats Args: shapes_and_components: list of paramak.Shape objects """ - + + def __init__( self, - shapes_and_components: List[paramak.Shape] = [], - ): - - self.shapes_and_components = shapes_and_components - - self.input_variable_names: List[str] = [ - # 'shapes_and_components', commented out to avoid calculating solids - ] - - self.stp_filenames: List[str] = [] - self.stl_filenames: List[str] = [] - - self.solid = None - self.reactor_hash_value = None - - @property - def input_variables(self): - all_input_variables = {} - for name in self.input_variable_names: - all_input_variables[name] = getattr(self, name) - return all_input_variables - - @property - def largest_dimension(self): - """Calculates a bounding box for the Reactor and returns the largest - absolute value of the largest dimension of the bounding box""" - - largest_dimension = get_largest_dimension(self.solid) - - return largest_dimension - - @largest_dimension.setter - def largest_dimension(self, value): - self._largest_dimension = value - - @property - def bounding_box(self): - """Calculates a bounding box for the Shape and returns the coordinates of - the corners lower-left and upper-right. This function is useful when - creating OpenMC mesh tallies as the bounding box is required in this form""" - - return get_bounding_box(self.solid) - - @bounding_box.setter - def bounding_box(self, value): - self._bounding_box = value - - @property - def shapes_and_components(self): - """Adds a list of parametric shape(s) and or parametric component(s) - to the Reactor object. This allows collective operations to be - performed on all the shapes in the reactor.""" - if hasattr(self, "create_solids"): - ignored_keys = ["reactor_hash_value"] - if get_hash(self, ignored_keys) != self.reactor_hash_value: - self.create_solids() - self.reactor_hash_value = get_hash(self, ignored_keys) - return self._shapes_and_components - - @shapes_and_components.setter - def shapes_and_components(self, value): - if not isinstance(value, (Iterable, str)): - raise ValueError("shapes_and_components must be a list") - self._shapes_and_components = value - - @property - def solid(self): - """This combines all the parametric shapes and components in the - reactor object. - """ - - list_of_cq_vals = [] - for shape_or_compound in self.shapes_and_components: - if isinstance( - shape_or_compound.solid, - (cq.occ_impl.shapes.Shape, cq.occ_impl.shapes.Compound), - ): - for solid in shape_or_compound.solid.Solids(): - list_of_cq_vals.append(solid) - else: - list_of_cq_vals.append(shape_or_compound.solid.val()) - - compound = cq.Compound.makeCompound(list_of_cq_vals) - - return compound - - @solid.setter - def solid(self, value): - self._solid = value - - @property - def name(self): - """Returns a list of names of the individual Shapes that make up the - reactor""" - - all_names = [] - for shape in self.shapes_and_components: - all_names.append(shape.name) - - return all_names + obj: AssemblyObjects = None, + loc: Optional[Location] = None, + name: Optional[str] = None, + color: Optional[Color] = None, + metadata: Optional[Dict[str, Any]] = None, + ): + + super().__init__( + obj, loc, name, color, metadata + ) + # def __init__( + # self + # ): + + # self.name="reactor" + # super().__init__() def show(self, **kwargs): """Shows / renders the CadQuery the 3d object in Jupyter Lab. Imports @@ -153,14 +74,7 @@ def show(self, **kwargs): ) raise ImportError(msg) - assembly = cq.Assembly(name="reactor") - for entry in self.shapes_and_components: - if entry.color is None: - assembly.add(entry.solid) - else: - assembly.add(entry.solid, color=cq.Color(*entry.color)) - - return show(assembly, **kwargs) + return show(self, **kwargs) def export_dagmc_h5m( self, @@ -428,63 +342,6 @@ def export_stl( return filename - def make_sector_wedge( - self, - height: Optional[float] = None, - radius: Optional[float] = None, - rotation_angle: Optional[float] = None, - ) -> Union[paramak.Shape, None]: - """Creates a rotated wedge shaped object that is useful for creating - sector models in DAGMC where reflecting surfaces are needed. If the - rotation - - Args: - height: The height of the rotated wedge. If None then the - largest_dimension of the model will be used. - radius: The radius of the rotated wedge. If None then the - largest_dimension of the model will be used - rotation_angle: The rotation angle of the wedge will be the - inverse of the sector - - Returns: - the paramak.Shape object created - """ - - if rotation_angle is None: - if hasattr(self, "rotation_angle"): - rotation_angle = self.rotation_angle - if rotation_angle is None: - Warning("No sector_wedge can be made as rotation_angle" " or Reactor.rotation_angle have not been set") - return None - - if rotation_angle > 360: - Warning("No wedge can be made for a rotation angle of 360 or above") - return None - - if rotation_angle == 360: - print("No sector wedge made as rotation angle is 360") - return None - - # todo this should be cetered around the center point - - if height is None: - height = self.largest_dimension * 2 - - if radius is None: - radius = self.largest_dimension * 2 - - sector_cutting_wedge = paramak.CuttingWedge( - height=height, - radius=radius, - rotation_angle=360 - rotation_angle, - surface_reflectivity=True, - azimuth_placement_angle=rotation_angle, - ) - - self.sector_wedge = sector_cutting_wedge - - return sector_cutting_wedge - def export_svg( self, filename: Optional[str] = "reactor.svg", @@ -664,21 +521,3 @@ def export_html( ) return fig - - def volume(self, split_compounds: bool = False) -> List[float]: - """Get the volumes of the Shapes in the Reactor. - - Args: - split_compounds: If the Shape is a compound of Shapes and therefore - contains multiple volumes. This option allows access to the separate - volumes of each component within a Shape (True) or the volumes of - compounds can be summed (False). - - Returns: - The the volumes of the Shapes - """ - - all_volumes = [] - for shape in self.shapes_and_components: - all_volumes.append(shape.volume(split_compounds=split_compounds)) - return all_volumes From 76af2b54d35895f6247c4d3b46b5d65a3b940c95 Mon Sep 17 00:00:00 2001 From: shimwell Date: Fri, 13 Jan 2023 23:33:30 +0000 Subject: [PATCH 02/16] [skip ci] Apply formatting changes --- .../flf_system_code_reactor.py | 9 ++++---- src/paramak/reactor.py | 23 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py index 396290193..07d48a6f2 100644 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ b/src/paramak/parametric_reactors/flf_system_code_reactor.py @@ -44,13 +44,12 @@ def __init__( ): super().__init__( - obj = None, - loc = None, - name = None, - color = None, + obj=None, + loc=None, + name=None, + color=None, metadata=None, ) - self.rotation_angle = rotation_angle self.inner_blanket_radius = inner_blanket_radius diff --git a/src/paramak/reactor.py b/src/paramak/reactor.py index 6c0d6a8e5..c07f37882 100644 --- a/src/paramak/reactor.py +++ b/src/paramak/reactor.py @@ -1,4 +1,3 @@ - from pathlib import Path from typing import List, Optional, Tuple, Union @@ -19,8 +18,10 @@ from cadquery import Workplane from cadquery.occ_impl.shapes import Shape, Compound + AssemblyObjects = Union[Shape, Workplane, None] + class Reactor(cq.Assembly): """The Reactor object is an extended CadQuery Assembly object. The additional functionality allows shapes and components to be exported to @@ -29,8 +30,7 @@ class Reactor(cq.Assembly): Args: shapes_and_components: list of paramak.Shape objects """ - - + def __init__( self, obj: AssemblyObjects = None, @@ -38,17 +38,16 @@ def __init__( name: Optional[str] = None, color: Optional[Color] = None, metadata: Optional[Dict[str, Any]] = None, - ): + ): + + super().__init__(obj, loc, name, color, metadata) - super().__init__( - obj, loc, name, color, metadata - ) - # def __init__( - # self - # ): + # def __init__( + # self + # ): - # self.name="reactor" - # super().__init__() + # self.name="reactor" + # super().__init__() def show(self, **kwargs): """Shows / renders the CadQuery the 3d object in Jupyter Lab. Imports From 549b38f4967de4c03e0498d668388ab368ea36b5 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sun, 15 Jan 2023 15:05:46 +0000 Subject: [PATCH 03/16] refactored dagc export method --- src/paramak/reactor.py | 47 ++---------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/src/paramak/reactor.py b/src/paramak/reactor.py index 6c0d6a8e5..04c6df20c 100644 --- a/src/paramak/reactor.py +++ b/src/paramak/reactor.py @@ -119,51 +119,8 @@ def export_dagmc_h5m( of neutronics codes that have specific DAGMC tag requirements. """ - shapes_to_convert = [] - - for shape in self.shapes_and_components: - # allows components like the plasma to be removed - if exclude: - if shape.name not in exclude: - shapes_to_convert.append(shape) - else: - shapes_to_convert.append(shape) - - assembly = cq.Assembly(name="reactor") - for solid in self.shapes_and_components: - assembly.add(solid.solid) - - if tags is None: - tags = [] - for shape in self.shapes_and_components: - tags.append(shape.name) - - expamded_tags = [] - - if len(tags) != len(self.shapes_and_components): - msg = ( - f"Number of tags {len(tags)} is not equal to the number of " - "shapes_and_components {len(self.shapes_and_components)}" - ) - raise ValueError(msg) - - for tag, s_c in zip(tags, self.shapes_and_components): - # solids could contain compounds - # before accessing the .val() check it exists - if hasattr(s_c.solid, "val"): - # if it is a compound then we may need more material tags - if isinstance(s_c.solid.val(), cq.occ_impl.shapes.Compound): - required_num_tags = len(s_c.solid.val().Solids()) - else: - required_num_tags = 1 - elif isinstance(s_c.solid, cq.occ_impl.shapes.Compound): - required_num_tags = len(s_c.solid.Solids()) - else: - required_num_tags = 1 - expamded_tags = expamded_tags + [tag] * required_num_tags - output_filename = export_solids_to_dagmc_h5m( - solids=assembly, + solids=self, filename=filename, min_mesh_size=min_mesh_size, max_mesh_size=max_mesh_size, @@ -171,7 +128,7 @@ def export_dagmc_h5m( volume_atol=volume_atol, center_atol=center_atol, bounding_box_atol=bounding_box_atol, - tags=expamded_tags, + tags=[child.name for child in self.children], ) return output_filename From e8531044f1ea829fca859cb0e05785de411152c0 Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 24 Jan 2023 21:27:41 +0000 Subject: [PATCH 04/16] added weblink --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 20e421ece..2cf9cbcd2 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,6 @@ STP, STL, BRep, HTML and DAGMC h5m. :point_right: [Docker images](https://github.com/fusion-energy/paramak/pkgs/container/paramak) +:point_right: [Web app](https://xsplot.com) + :point_right: Examples with Neutronics [1](https://github.com/fusion-energy/magnetic_fusion_openmc_dagmc_paramak_example), [2](https://github.com/fusion-energy/inertial_fusion_openmc_dagmc_paramak_example), [3](https://github.com/fusion-energy/neutronics-workshop) From ea1c0d611edff0223643972574d72af4f3200434 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 28 Jan 2023 22:50:06 +0000 Subject: [PATCH 05/16] function returning cq.assembly --- .../flf_system_code_reactor.py | 335 ++++++++---------- 1 file changed, 149 insertions(+), 186 deletions(-) diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py index 07d48a6f2..cd9a5fcdb 100644 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ b/src/paramak/parametric_reactors/flf_system_code_reactor.py @@ -1,9 +1,20 @@ -from typing import List, Optional -import paramak +import cadquery as cq +from paramak import RotateStraightShape, CenterColumnShieldCylinder -class FlfSystemCodeReactor(paramak.Reactor): +def FlfSystemCodeReactor( + inner_blanket_radius: float = 100.0, + blanket_thickness: float = 70.0, + blanket_height: float = 500.0, + lower_blanket_thickness: float = 50.0, + upper_blanket_thickness: float = 40.0, + blanket_vv_gap: float = 20.0, + upper_vv_thickness: float = 10.0, + vv_thickness: float = 10.0, + lower_vv_thickness: float = 10.0, + rotation_angle: float = 180.0, +): """Creates the 3D geometry for the a simplified FLF reactor model based on parameters. Model design was originally presented at University of York in 2019. Model shown at 50 mins 48 seconds in presentation @@ -29,192 +40,144 @@ class FlfSystemCodeReactor(paramak.Reactor): simulations and less when creating models for visualization. """ - def __init__( - self, - inner_blanket_radius: Optional[float] = 100.0, - blanket_thickness: Optional[float] = 70.0, - blanket_height: Optional[float] = 500.0, - lower_blanket_thickness: Optional[float] = 50.0, - upper_blanket_thickness: Optional[float] = 40.0, - blanket_vv_gap: Optional[float] = 20.0, - upper_vv_thickness: Optional[float] = 10.0, - vv_thickness: Optional[float] = 10.0, - lower_vv_thickness: Optional[float] = 10.0, - rotation_angle: Optional[float] = 180.0, - ): + inner_wall = inner_blanket_radius + blanket_thickness + blanket_vv_gap + lower_vv = RotateStraightShape( + points=[ + (inner_wall, 0), + ( + inner_wall, + lower_vv_thickness, + ), + ( + 0, + lower_vv_thickness, + ), + (0, 0), + ], + rotation_angle=rotation_angle, + color=(0.5, 0.5, 0.5), + name="lower_vessel", + ) - super().__init__( - obj=None, - loc=None, - name=None, - color=None, - metadata=None, - ) + lower_blanket = RotateStraightShape( + points=[ + (inner_wall, lower_vv_thickness), + (inner_wall, lower_vv_thickness + lower_blanket_thickness), + (0, lower_vv_thickness + lower_blanket_thickness), + (0, lower_vv_thickness), + ], + rotation_angle=rotation_angle, + color=(0.0, 1.0, 0.498), + name="lower_blanket", + ) - self.rotation_angle = rotation_angle - self.inner_blanket_radius = inner_blanket_radius - self.blanket_thickness = blanket_thickness - self.blanket_height = blanket_height - self.lower_blanket_thickness = lower_blanket_thickness - self.upper_blanket_thickness = upper_blanket_thickness - self.blanket_vv_gap = blanket_vv_gap - self.upper_vv_thickness = upper_vv_thickness - self.vv_thickness = vv_thickness - self.lower_vv_thickness = lower_vv_thickness + blanket = CenterColumnShieldCylinder( + height=blanket_height, + center_height=lower_vv_thickness + lower_blanket_thickness + 0.5 * blanket_height, + inner_radius=inner_blanket_radius, + outer_radius=blanket_thickness + inner_blanket_radius, + rotation_angle=rotation_angle, + cut=lower_blanket, + color=(0.0, 1.0, 0.498), + name="blanket", + ) - # adds self.input_variable_names from the Reactor class - # self.input_variable_names: List[str] = self.input_variable_names + [ - # "inner_blanket_radius", - # "blanket_thickness", - # "blanket_height", - # "lower_blanket_thickness", - # "upper_blanket_thickness", - # "blanket_vv_gap", - # "upper_vv_thickness", - # "vv_thickness", - # "lower_vv_thickness", - # "rotation_angle", - # ] + upper_vv = RotateStraightShape( + points=[ + (inner_wall, lower_vv_thickness + lower_blanket_thickness + blanket_height), + ( + inner_wall, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness, + ), + ( + 0, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness, + ), + (0, lower_vv_thickness + lower_blanket_thickness + blanket_height), + ], + rotation_angle=rotation_angle, + color=(0.5, 0.5, 0.5), + name="upper_vessel", + ) - def create_solids(self): - """Creates a list of paramak.Shape for components and saves it in - self.shapes_and_components - """ - inner_wall = self.inner_blanket_radius + self.blanket_thickness + self.blanket_vv_gap - lower_vv = paramak.RotateStraightShape( - points=[ - (inner_wall, 0), - ( - inner_wall, - self.lower_vv_thickness, - ), - ( - 0, - self.lower_vv_thickness, - ), - (0, 0), - ], - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="lower_vessel", - ) + upper_blanket = RotateStraightShape( + points=[ + ( + inner_wall, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness, + ), + ( + inner_wall, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness + + upper_blanket_thickness, + ), + ( + 0, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness + + upper_blanket_thickness, + ), + ( + 0, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness, + ), + ], + rotation_angle=rotation_angle, + color=(0.0, 1.0, 0.498), + name="upper_blanket", + ) - lower_blanket = paramak.RotateStraightShape( - points=[ - (inner_wall, self.lower_vv_thickness), - (inner_wall, self.lower_vv_thickness + self.lower_blanket_thickness), - (0, self.lower_vv_thickness + self.lower_blanket_thickness), - (0, self.lower_vv_thickness), - ], - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 0.498), - name="lower_blanket", - ) + vac_vessel = RotateStraightShape( + points=[ + (inner_wall, 0), + ( + inner_wall, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness + + upper_blanket_thickness, + ), + ( + inner_wall + vv_thickness, + lower_vv_thickness + + lower_blanket_thickness + + blanket_height + + upper_vv_thickness + + upper_blanket_thickness, + ), + (inner_wall + vv_thickness, 0), + ], + rotation_angle=rotation_angle, + color=(0.5, 0.5, 0.5), + name="vessel", + ) + + assembly = ( + cq.Assembly() + .add(blanket.solid,name='blanket') + .add(vac_vessel.solid,name='vac_vessel') + .add(upper_blanket.solid,name='upper_blanket') + .add(lower_blanket.solid,name='lower_blanket') + .add(lower_vv.solid,name='lower_vv') + .add(upper_vv.solid,name='upper_vv') + ) - blanket = paramak.CenterColumnShieldCylinder( - height=self.blanket_height, - center_height=self.lower_vv_thickness + self.lower_blanket_thickness + 0.5 * self.blanket_height, - inner_radius=self.inner_blanket_radius, - outer_radius=self.blanket_thickness + self.inner_blanket_radius, - rotation_angle=self.rotation_angle, - cut=lower_blanket, - color=(0.0, 1.0, 0.498), - name="blanket", - ) - - upper_vv = paramak.RotateStraightShape( - points=[ - (inner_wall, self.lower_vv_thickness + self.lower_blanket_thickness + self.blanket_height), - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - ( - 0, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - (0, self.lower_vv_thickness + self.lower_blanket_thickness + self.blanket_height), - ], - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="upper_vessel", - ) - - upper_blanket = paramak.RotateStraightShape( - points=[ - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - ( - 0, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - ( - 0, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness, - ), - ], - rotation_angle=self.rotation_angle, - color=(0.0, 1.0, 0.498), - name="upper_blanket", - ) - - vac_ves = paramak.RotateStraightShape( - points=[ - (inner_wall, 0), - ( - inner_wall, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - ( - inner_wall + self.vv_thickness, - self.lower_vv_thickness - + self.lower_blanket_thickness - + self.blanket_height - + self.upper_vv_thickness - + self.upper_blanket_thickness, - ), - (inner_wall + self.vv_thickness, 0), - ], - rotation_angle=self.rotation_angle, - color=(0.5, 0.5, 0.5), - name="vessel", - ) - - self.shapes_and_components = [ - blanket, - vac_ves, - upper_blanket, - lower_blanket, - lower_vv, - upper_vv, - ] + return assembly From f055574752b059609c6f2eba9960aa94b38748d0 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 28 Jan 2023 22:50:35 +0000 Subject: [PATCH 06/16] [skip ci] Apply formatting changes --- .../flf_system_code_reactor.py | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py index cd9a5fcdb..6d33be06d 100644 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ b/src/paramak/parametric_reactors/flf_system_code_reactor.py @@ -1,4 +1,3 @@ - import cadquery as cq from paramak import RotateStraightShape, CenterColumnShieldCylinder @@ -87,17 +86,11 @@ def FlfSystemCodeReactor( (inner_wall, lower_vv_thickness + lower_blanket_thickness + blanket_height), ( inner_wall, - lower_vv_thickness - + lower_blanket_thickness - + blanket_height - + upper_vv_thickness, + lower_vv_thickness + lower_blanket_thickness + blanket_height + upper_vv_thickness, ), ( 0, - lower_vv_thickness - + lower_blanket_thickness - + blanket_height - + upper_vv_thickness, + lower_vv_thickness + lower_blanket_thickness + blanket_height + upper_vv_thickness, ), (0, lower_vv_thickness + lower_blanket_thickness + blanket_height), ], @@ -110,10 +103,7 @@ def FlfSystemCodeReactor( points=[ ( inner_wall, - lower_vv_thickness - + lower_blanket_thickness - + blanket_height - + upper_vv_thickness, + lower_vv_thickness + lower_blanket_thickness + blanket_height + upper_vv_thickness, ), ( inner_wall, @@ -133,10 +123,7 @@ def FlfSystemCodeReactor( ), ( 0, - lower_vv_thickness - + lower_blanket_thickness - + blanket_height - + upper_vv_thickness, + lower_vv_thickness + lower_blanket_thickness + blanket_height + upper_vv_thickness, ), ], rotation_angle=rotation_angle, @@ -169,15 +156,15 @@ def FlfSystemCodeReactor( color=(0.5, 0.5, 0.5), name="vessel", ) - + assembly = ( cq.Assembly() - .add(blanket.solid,name='blanket') - .add(vac_vessel.solid,name='vac_vessel') - .add(upper_blanket.solid,name='upper_blanket') - .add(lower_blanket.solid,name='lower_blanket') - .add(lower_vv.solid,name='lower_vv') - .add(upper_vv.solid,name='upper_vv') + .add(blanket.solid, name="blanket") + .add(vac_vessel.solid, name="vac_vessel") + .add(upper_blanket.solid, name="upper_blanket") + .add(lower_blanket.solid, name="lower_blanket") + .add(lower_vv.solid, name="lower_vv") + .add(upper_vv.solid, name="upper_vv") ) return assembly From fc1d2b97259556cd6cef919997b052183fa037ad Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 28 Jan 2023 23:18:37 +0000 Subject: [PATCH 07/16] limited reactor import --- src/paramak/__init__.py | 56 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/paramak/__init__.py b/src/paramak/__init__.py index e0d89913b..40e3c0080 100644 --- a/src/paramak/__init__.py +++ b/src/paramak/__init__.py @@ -15,7 +15,7 @@ from .shape import Shape -from .reactor import Reactor +from .reactor import * from .utils import ( rotate, extend, @@ -136,27 +136,27 @@ from .parametric_components.hollow_cube import HollowCube from .parametric_components.shell_fs import ShellFS -from .parametric_reactors.eu_demo_2015_reactor import EuDemoFrom2015PaperDiagram -from .parametric_reactors.ball_reactor import BallReactor -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 -from .parametric_reactors.segmented_blanket_ball_reactor import ( - SegmentedBlanketBallReactor, -) -from .parametric_reactors.center_column_study_reactor import CenterColumnStudyReactor -from .parametric_reactors.sparc_paper_2020 import SparcFrom2020PaperDiagram -from .parametric_reactors.iter_paper_2020 import IterFrom2020PaperDiagram +# from .parametric_reactors.eu_demo_2015_reactor import EuDemoFrom2015PaperDiagram +# from .parametric_reactors.ball_reactor import BallReactor +# 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 +# from .parametric_reactors.segmented_blanket_ball_reactor import ( +# SegmentedBlanketBallReactor, +# ) +# from .parametric_reactors.center_column_study_reactor import CenterColumnStudyReactor +# from .parametric_reactors.sparc_paper_2020 import SparcFrom2020PaperDiagram +# from .parametric_reactors.iter_paper_2020 import IterFrom2020PaperDiagram from .parametric_reactors.flf_system_code_reactor import FlfSystemCodeReactor -from .parametric_reactors.negative_triangularity_reactor import ( - NegativeTriangularityReactor, -) +# from .parametric_reactors.negative_triangularity_reactor import ( +# NegativeTriangularityReactor, +# ) __all__ = [ Shape, - Reactor, + # Reactor, rotate, extend, distance_between_two_points, @@ -235,15 +235,15 @@ CapsuleVacuumVessel, HollowCube, ShellFS, - EuDemoFrom2015PaperDiagram, - BallReactor, - SubmersionTokamak, - SingleNullSubmersionTokamak, - SingleNullBallReactor, - SegmentedBlanketBallReactor, - CenterColumnStudyReactor, - SparcFrom2020PaperDiagram, - IterFrom2020PaperDiagram, + # EuDemoFrom2015PaperDiagram, + # BallReactor, + # SubmersionTokamak, + # SingleNullSubmersionTokamak, + # SingleNullBallReactor, + # SegmentedBlanketBallReactor, + # CenterColumnStudyReactor, + # SparcFrom2020PaperDiagram, + # IterFrom2020PaperDiagram, FlfSystemCodeReactor, - NegativeTriangularityReactor, + # NegativeTriangularityReactor, ] From dfc6760712fc1d04d3857345ac8655089fd4f9d6 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 28 Jan 2023 23:18:57 +0000 Subject: [PATCH 08/16] started adding color --- .../flf_system_code_reactor.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py index cd9a5fcdb..70b235bf1 100644 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ b/src/paramak/parametric_reactors/flf_system_code_reactor.py @@ -30,18 +30,18 @@ def FlfSystemCodeReactor( upper_blanket_thickness: The thickness (z axis direction) of the upper blanket pool (cm). blanket_vv_gap: The radial distance between the outer edge of the - blanket and the inner edge of the vaccum vessel (cm). + blanket and the inner edge of the vacuum vessel (cm). upper_vv_thickness: The thickness (z axis direction) of the - upper section of vaccum vessel (cm). - vv_thickness: The radial thickness of the vaccum vessel (cm) + upper section of vacuum vessel (cm). + vv_thickness: The radial thickness of the vacuum vessel (cm) lower_vv_thickness: The thickness (z axis direction) of the - lower section of vaccum vessel (cm). + lower section of vacuum vessel (cm). rotation_angle: The angle of the sector simulated. Set to 360 for simulations and less when creating models for visualization. """ inner_wall = inner_blanket_radius + blanket_thickness + blanket_vv_gap - lower_vv = RotateStraightShape( + lower_vac_vessel = RotateStraightShape( points=[ (inner_wall, 0), ( @@ -82,7 +82,7 @@ def FlfSystemCodeReactor( name="blanket", ) - upper_vv = RotateStraightShape( + upper_vac_vessel = RotateStraightShape( points=[ (inner_wall, lower_vv_thickness + lower_blanket_thickness + blanket_height), ( @@ -169,15 +169,16 @@ def FlfSystemCodeReactor( color=(0.5, 0.5, 0.5), name="vessel", ) - + colors=[(0.5, 0.5, 0.5)] + assembly = ( - cq.Assembly() - .add(blanket.solid,name='blanket') + cq.Assembly(name='FlfSystemCodeReactor') + .add(blanket.solid,name='blanket', color=cq.Color(*colors[0])) .add(vac_vessel.solid,name='vac_vessel') .add(upper_blanket.solid,name='upper_blanket') .add(lower_blanket.solid,name='lower_blanket') - .add(lower_vv.solid,name='lower_vv') - .add(upper_vv.solid,name='upper_vv') + .add(lower_vac_vessel.solid,name='lower_vac_vessel') + .add(upper_vac_vessel.solid,name='upper_vac_vessel') ) return assembly From d355bd81f0fb15f8ab3c380135e9b00bc55ee743 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 28 Jan 2023 23:19:13 +0000 Subject: [PATCH 09/16] patching cq assembly --- src/paramak/reactor.py | 508 +++++------------------------------------ 1 file changed, 52 insertions(+), 456 deletions(-) diff --git a/src/paramak/reactor.py b/src/paramak/reactor.py index c06a90934..e1979f72e 100644 --- a/src/paramak/reactor.py +++ b/src/paramak/reactor.py @@ -12,468 +12,64 @@ export_solids_to_dagmc_h5m, ) -from typing import Union, Optional, List, Dict, Any +import typing from cadquery.occ_impl.geom import Location from cadquery.occ_impl.assembly import Color -from cadquery import Workplane -from cadquery.occ_impl.shapes import Shape, Compound -AssemblyObjects = Union[Shape, Workplane, None] - -class Reactor(cq.Assembly): - """The Reactor object is an extended CadQuery Assembly object. The - additional functionality allows shapes and components to be exported to - a variety of additional formats +def export_dagmc_h5m( + self, + filename: str = "dagmc.h5m", + min_mesh_size: float = 5, + max_mesh_size: float = 20, + verbose: bool = False, + volume_atol: float = 0.000001, + center_atol: float = 0.000001, + bounding_box_atol: float = 0.000001, + tags: typing.Optional[typing.Iterable[str]] = None, +) -> str: + """Export a DAGMC compatible h5m file for use in neutronics simulations. + This method makes use of Gmsh to create a surface mesh of the geometry. + MOAB is used to convert the meshed geometry into a h5m with parts tagged by + using the reactor.shape_and_components.name properties. You will need + Gmsh installed and MOAB installed to use this function. Acceptable + tolerances may need increasing to match reactor parts with the parts + in the intermediate Brep file produced during the process Args: - shapes_and_components: list of paramak.Shape objects + filename: the filename of the DAGMC h5m file to write + min_mesh_size: the minimum mesh element size to use in Gmsh. Passed + into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size) + max_mesh_size: the maximum mesh element size to use in Gmsh. Passed + into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size) + volume_atol: the absolute volume tolerance to allow when matching + parts in the intermediate brep file with the cadquery parts + center_atol: the absolute center coordinates tolerance to allow + when matching parts in the intermediate brep file with the + cadquery parts + bounding_box_atol: the absolute volume tolerance to allow when + matching parts in the intermediate brep file with the cadquery + parts + tags: the dagmc tag to use in when naming the shape in the h5m file. + If left as None then the Shape.name will be used. This allows + the DAGMC geometry created to be compatible with a wider range + of neutronics codes that have specific DAGMC tag requirements. """ - def __init__( - self, - obj: AssemblyObjects = None, - loc: Optional[Location] = None, - name: Optional[str] = None, - color: Optional[Color] = None, - metadata: Optional[Dict[str, Any]] = None, - ): - - super().__init__(obj, loc, name, color, metadata) - - # def __init__( - # self - # ): - - # self.name="reactor" - # super().__init__() - - def show(self, **kwargs): - """Shows / renders the CadQuery the 3d object in Jupyter Lab. Imports - show from jupyter_cadquery and returns show(Reactor.solid, kwargs) - - Args: - kwargs: keyword arguments passed to jupyter-cadquery show() - function. See https://github.com/bernhard-42/jupyter-cadquery#usage - for more details on acceptable keywords - - - Returns: - jupyter_cadquery show object - """ - - try: - from jupyter_cadquery import show - except ImportError: - msg = ( - "To use Reactor.show() you must install jupyter_cadquery version " - '3.2.0 or above. To install jupyter_cadquery type "pip install ' - 'jupyter_cadquery" in the terminal' - ) - raise ImportError(msg) - - return show(self, **kwargs) - - def export_dagmc_h5m( - self, - filename: str = "dagmc.h5m", - min_mesh_size: float = 5, - max_mesh_size: float = 20, - exclude: List[str] = None, - verbose: bool = False, - volume_atol: float = 0.000001, - center_atol: float = 0.000001, - bounding_box_atol: float = 0.000001, - tags: Optional[List[str]] = None, - ) -> str: - """Export a DAGMC compatible h5m file for use in neutronics simulations. - This method makes use of Gmsh to create a surface mesh of the geometry. - MOAB is used to convert the meshed geometry into a h5m with parts tagged by - using the reactor.shape_and_components.name properties. You will need - Gmsh installed and MOAB installed to use this function. Acceptable - tolerances may need increasing to match reactor parts with the parts - in the intermediate Brep file produced during the process - - Args: - filename: the filename of the DAGMC h5m file to write - min_mesh_size: the minimum mesh element size to use in Gmsh. Passed - into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size) - max_mesh_size: the maximum mesh element size to use in Gmsh. Passed - into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size) - exclude: A list of shape names to not include in the exported - geometry. 'plasma' is often excluded as not many neutron - interactions occur within a low density plasma. - volume_atol: the absolute volume tolerance to allow when matching - parts in the intermediate brep file with the cadquery parts - center_atol: the absolute center coordinates tolerance to allow - when matching parts in the intermediate brep file with the - cadquery parts - bounding_box_atol: the absolute volume tolerance to allow when - matching parts in the intermediate brep file with the cadquery - parts - tags: the dagmc tag to use in when naming the shape in the h5m file. - If left as None then the Shape.name will be used. This allows - the DAGMC geometry created to be compatible with a wider range - of neutronics codes that have specific DAGMC tag requirements. - """ - - output_filename = export_solids_to_dagmc_h5m( - solids=self, - filename=filename, - min_mesh_size=min_mesh_size, - max_mesh_size=max_mesh_size, - verbose=verbose, - volume_atol=volume_atol, - center_atol=center_atol, - bounding_box_atol=bounding_box_atol, - tags=[child.name for child in self.children], - ) - - return output_filename - - def export_stp( - self, - filename: Union[List[str], str] = None, - mode: Optional[str] = "solid", - units: Optional[str] = "mm", - ) -> Union[List[str], str]: - """Exports the 3D reactor model as a stp file or files. - - Args: - filename: Accepts a single filename as a string which exports the - full reactor model to a single file. Alternativley filename can - also accept a list of strings where each string is the filename - of the the individual shapes that make it up. This will result - in separate files for each shape in the reactor. Defaults to - None which uses the Reactor.name with '.stp' appended to the end - of each entry. - mode: the object to export can be either 'solid' which exports 3D - solid shapes or the 'wire' which exports the wire edges of the - shape. - units: the units of the stp file, options are 'cm' or 'mm'. - Default is mm. - Returns: - The stp filename(s) created - """ - - if isinstance(filename, str): - - # exports a single file for the whole model - assembly = cq.Assembly(name="reactor") - for entry in self.shapes_and_components: - if entry.color is None: - assembly.add(entry.solid) - else: - assembly.add(entry.solid, color=cq.Color(*entry.color)) - - assembly.save(filename, exportType="STEP") - - if units == "cm": - _replace(filename, "SI_UNIT(.MILLI.,.METRE.)", "SI_UNIT(.CENTI.,.METRE.)") - - return [filename] - - if filename is None: - if None in self.name: - msg = ( - "Shape.name is None and therefore it can't be used " - "to name a stp file. Try setting Shape.name for all " - "shapes in the reactor" - ) - raise ValueError(msg) - filename = [f"{name}.stp" for name in self.name] - - # exports the reactor solid as a separate stp files - if len(filename) != len(self.shapes_and_components): - msg = ( - f"The Reactor contains {len(self.shapes_and_components)} " - f"Shapes and {len(filename)} filenames have be provided. " - f"The names of the shapes are {self.name}" - ) - raise ValueError(msg) - - for stp_filename, entry in zip(filename, self.shapes_and_components): - - entry.export_stp( - filename=stp_filename, - mode=mode, - units=units, - verbose=False, - ) - - if units == "cm": - _replace(stp_filename, "SI_UNIT(.MILLI.,.METRE.)", "SI_UNIT(.CENTI.,.METRE.)") - - return filename - - def export_brep( - self, - filename: str = "reactor.brep", - ) -> str: - """Exports a brep file for the Reactor. - - Args: - filename: the filename of exported the brep file. - - Returns: - filename of the brep created - """ - - geometry_to_save = [shape.solid for shape in self.shapes_and_components] - - output_filename = export_solids_to_brep( - solids=geometry_to_save, - filename=filename, - ) - - return output_filename - - def export_stl( - self, - filename: Union[List[str], str] = None, - tolerance: float = 0.001, - angular_tolerance: float = 0.1, - ) -> Union[str, List[str]]: - """Writes stl files (CAD geometry) for each Shape object in the reactor - - Args: - filename: Accepts a single filename as a string which exports the - full reactor model to a single file. Alternativley filename can - also accept a list of strings where each string is the filename - of the the individual shapes that make it up. This will result - in separate files for each shape in the reactor. Defaults to - None which uses the Reactor.name with '.stl' appended to the end - of each entry. - tolerance (float): the precision of the faceting - - Returns: - list: a list of stl filenames created - """ - - if isinstance(filename, str): - - path_filename = Path(filename) - - if path_filename.suffix != ".stl": - path_filename = path_filename.with_suffix(".stl") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - exporters.export( - self.solid, - str(path_filename), - exportType="STL", - tolerance=tolerance, - angularTolerance=angular_tolerance, - ) - return str(path_filename) - - if filename is None: - if None in self.name: - msg = ( - "Shape.name is None and therefore it can't be used " - "to name a stl file. Try setting Shape.name for all " - "shapes in the reactor" - ) - raise ValueError() - filename = [f"{name}.stl" for name in self.name] - - # exports the reactor solid as a separate stl files - if len(filename) != len(self.shapes_and_components): - msg = ( - f"The Reactor contains {len(self.shapes_and_components)} " - f"Shapes and {len(filename)} filenames have be provided. " - f"The names of the shapes are {self.name}" - ) - raise ValueError(msg) - - for stl_filename, entry in zip(filename, self.shapes_and_components): - - entry.export_stl( - filename=stl_filename, - tolerance=tolerance, - verbose=False, - ) - - return filename - - def export_svg( - self, - filename: Optional[str] = "reactor.svg", - projectionDir: Tuple[float, float, float] = (-1.75, 1.1, 5), - width: Optional[float] = 1000, - height: Optional[float] = 800, - marginLeft: Optional[float] = 120, - marginTop: Optional[float] = 100, - strokeWidth: Optional[float] = None, - strokeColor: Optional[Tuple[int, int, int]] = (0, 0, 0), - hiddenColor: Optional[Tuple[int, int, int]] = (100, 100, 100), - showHidden: Optional[bool] = False, - showAxes: Optional[bool] = False, - ) -> str: - """Exports an svg file for the Reactor.solid. If the filename provided - doesn't end with .svg it will be added. - - Args: - filename: the filename of the svg file to be exported. Defaults to - "reactor.svg". - projectionDir: The direction vector to view the geometry from - (x, y, z). Defaults to (-1.75, 1.1, 5) - width: the width of the svg image produced in pixels. Defaults to - 1000 - height: the height of the svg image produced in pixels. Defaults to - 800 - marginLeft: the number of pixels between the left edge of the image - and the start of the geometry. - marginTop: the number of pixels between the top edge of the image - and the start of the geometry. - strokeWidth: the width of the lines used to draw the geometry. - Defaults to None which automatically selects an suitable width. - strokeColor: the color of the lines used to draw the geometry in - RGB format with each value between 0 and 255. Defaults to - (0, 0, 0) which is black. - hiddenColor: the color of the lines used to draw the geometry in - RGB format with each value between 0 and 255. Defaults to - (100, 100, 100) which is light grey. - showHidden: If the edges obscured by geometry should be included in - the diagram. Defaults to False. - showAxes: If the x, y, z axis should be included in the image. - Defaults to False. - - Returns: - str: the svg filename created - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".svg": - path_filename = path_filename.with_suffix(".svg") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - opt = { - "width": width, - "height": height, - "marginLeft": marginLeft, - "marginTop": marginTop, - "showAxes": showAxes, - "projectionDir": projectionDir, - "strokeColor": strokeColor, - "hiddenColor": hiddenColor, - "showHidden": showHidden, - } - - if strokeWidth is not None: - opt["strokeWidth"] = strokeWidth - - exporters.export(self.solid, str(path_filename), exportType="SVG", opt=opt) - - print("Saved file as ", path_filename) - - return str(path_filename) - - def export_2d_image( - self, - filename: Optional[str] = "2d_slice.png", - xmin: Optional[float] = 0.0, - xmax: Optional[float] = 900.0, - ymin: Optional[float] = -600.0, - ymax: Optional[float] = 600.0, - ) -> str: - """Creates a 2D slice image (png) of the reactor. - - Args: - filename (str): output filename of the image created - - Returns: - str: png filename created - """ - - path_filename = Path(filename) - - if path_filename.suffix != ".png": - path_filename = path_filename.with_suffix(".png") - - path_filename.parents[0].mkdir(parents=True, exist_ok=True) - - fig, ax = plt.subplots() - - # creates indvidual patches for each Shape which are combined together - for entry in self.shapes_and_components: - patch = entry._create_patch() - ax.add_collection(patch) - - ax.axis("equal") - ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax)) - ax.set_aspect("equal", "box") - - Path(filename).parent.mkdir(parents=True, exist_ok=True) - plt.savefig(filename, dpi=100) - plt.close() - - print("\n saved 2d image to ", str(path_filename)) - - return str(path_filename) - - def export_html_3d(self, filename: Optional[str] = "reactor_3d.html", **kwargs) -> Optional[str]: - """Saves an interactive 3d html view of the Reactor to a html file. - - Args: - filename: the filename used to save the html graph. Defaults to - reactor_3d.html - kwargs: keyword arguments passed to jupyter-cadquery show() - function. See https://github.com/bernhard-42/jupyter-cadquery#usage - for more details on acceptable keywords - - Returns: - str: filename of the created html file - """ - - view = self.show(**kwargs) - - view.export_html(filename) - - return filename - - def export_html( - self, - filename: Optional[str] = "reactor.html", - facet_splines: Optional[bool] = True, - facet_circles: Optional[bool] = True, - tolerance: Optional[float] = 1.0, - view_plane: Optional[str] = "RZ", - ): - """Creates a html graph representation of the points for the Shape - objects that make up the reactor. Shapes are colored by their .color - property. Shapes are also labelled by their .name. If filename provided - doesn't end with .html then .html will be added. - - Args: - filename: the filename used to save the html graph. Defaults to - reactor.html - facet_splines: If True then spline edges will be faceted. Defaults - to True. - facet_circles: If True then circle edges will be faceted. Defaults - to True. - tolerance: faceting toleranceto use when faceting cirles and - splines. Defaults to 1e-3. - view_plane: The plane to project. Options are 'XZ', 'XY', 'YZ', - 'YX', 'ZY', 'ZX', 'RZ' and 'XYZ'. Defaults to 'RZ'. Defaults to - 'RZ'. - Returns: - plotly.Figure(): figure object - """ - - fig = paramak.utils.export_wire_to_html( - wires=self.solid.Edges(), - filename=filename, - view_plane=view_plane, - facet_splines=facet_splines, - facet_circles=facet_circles, - tolerance=tolerance, - title=f"coordinates of the {self.__class__.__name__} reactor, viewed from the {view_plane} plane", - mode="lines", - ) - - return fig + output_filename = export_solids_to_dagmc_h5m( + solids=self, + filename=filename, + min_mesh_size=min_mesh_size, + max_mesh_size=max_mesh_size, + verbose=verbose, + volume_atol=volume_atol, + center_atol=center_atol, + bounding_box_atol=bounding_box_atol, + tags=[child.name for child in self.children], + ) + + return output_filename + +# patches cadquery assembly to have this addtional function +cq.assembly.Assembly.export_dagmc_h5m = export_dagmc_h5m From 14b7e09f4790b21cadfc96b1a03fbb2648065044 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sat, 28 Jan 2023 23:20:33 +0000 Subject: [PATCH 10/16] [skip ci] Apply formatting changes --- src/paramak/__init__.py | 1 + .../flf_system_code_reactor.py | 16 ++++++++-------- src/paramak/reactor.py | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/paramak/__init__.py b/src/paramak/__init__.py index 40e3c0080..a959af385 100644 --- a/src/paramak/__init__.py +++ b/src/paramak/__init__.py @@ -150,6 +150,7 @@ # from .parametric_reactors.sparc_paper_2020 import SparcFrom2020PaperDiagram # from .parametric_reactors.iter_paper_2020 import IterFrom2020PaperDiagram from .parametric_reactors.flf_system_code_reactor import FlfSystemCodeReactor + # from .parametric_reactors.negative_triangularity_reactor import ( # NegativeTriangularityReactor, # ) diff --git a/src/paramak/parametric_reactors/flf_system_code_reactor.py b/src/paramak/parametric_reactors/flf_system_code_reactor.py index 642326c16..fc5a79feb 100644 --- a/src/paramak/parametric_reactors/flf_system_code_reactor.py +++ b/src/paramak/parametric_reactors/flf_system_code_reactor.py @@ -157,16 +157,16 @@ def FlfSystemCodeReactor( name="vessel", ) - colors=[(0.5, 0.5, 0.5)] + colors = [(0.5, 0.5, 0.5)] assembly = ( - cq.Assembly(name='FlfSystemCodeReactor') - .add(blanket.solid,name='blanket', color=cq.Color(*colors[0])) - .add(vac_vessel.solid,name='vac_vessel') - .add(upper_blanket.solid,name='upper_blanket') - .add(lower_blanket.solid,name='lower_blanket') - .add(lower_vac_vessel.solid,name='lower_vac_vessel') - .add(upper_vac_vessel.solid,name='upper_vac_vessel') + cq.Assembly(name="FlfSystemCodeReactor") + .add(blanket.solid, name="blanket", color=cq.Color(*colors[0])) + .add(vac_vessel.solid, name="vac_vessel") + .add(upper_blanket.solid, name="upper_blanket") + .add(lower_blanket.solid, name="lower_blanket") + .add(lower_vac_vessel.solid, name="lower_vac_vessel") + .add(upper_vac_vessel.solid, name="upper_vac_vessel") ) return assembly diff --git a/src/paramak/reactor.py b/src/paramak/reactor.py index e1979f72e..e7ee21f31 100644 --- a/src/paramak/reactor.py +++ b/src/paramak/reactor.py @@ -17,7 +17,6 @@ from cadquery.occ_impl.assembly import Color - def export_dagmc_h5m( self, filename: str = "dagmc.h5m", @@ -71,5 +70,6 @@ def export_dagmc_h5m( return output_filename + # patches cadquery assembly to have this addtional function cq.assembly.Assembly.export_dagmc_h5m = export_dagmc_h5m From 0c2d28af2085b09dfc52b1dbad393a52f8e660c1 Mon Sep 17 00:00:00 2001 From: shimwell Date: Sun, 29 Jan 2023 11:41:38 +0000 Subject: [PATCH 11/16] started converting ballreactor --- src/paramak/__init__.py | 2 +- .../parametric_reactors/ball_reactor.py | 671 +++++++----------- 2 files changed, 271 insertions(+), 402 deletions(-) diff --git a/src/paramak/__init__.py b/src/paramak/__init__.py index 40e3c0080..bb09b63af 100644 --- a/src/paramak/__init__.py +++ b/src/paramak/__init__.py @@ -137,7 +137,7 @@ from .parametric_components.shell_fs import ShellFS # from .parametric_reactors.eu_demo_2015_reactor import EuDemoFrom2015PaperDiagram -# from .parametric_reactors.ball_reactor import BallReactor +from .parametric_reactors.ball_reactor import BallReactor # from .parametric_reactors.submersion_reactor import SubmersionTokamak # from .parametric_reactors.single_null_submersion_reactor import ( # SingleNullSubmersionTokamak, diff --git a/src/paramak/parametric_reactors/ball_reactor.py b/src/paramak/parametric_reactors/ball_reactor.py index c42853103..3eb5b6221 100644 --- a/src/paramak/parametric_reactors/ball_reactor.py +++ b/src/paramak/parametric_reactors/ball_reactor.py @@ -1,10 +1,37 @@ -import warnings + from typing import List, Optional import paramak - - -class BallReactor(paramak.Reactor): +import cadquery as cq + + +def BallReactor( + inner_bore_radial_thickness: float = 10.0, + inboard_tf_leg_radial_thickness: float = 30.0, + center_column_shield_radial_thickness: float = 60.0, + divertor_radial_thickness: float = 150.0, + inner_plasma_gap_radial_thickness: float = 30.0, + plasma_radial_thickness: float = 300.0, + outer_plasma_gap_radial_thickness: float = 30.0, + firstwall_radial_thickness: float = 30.0, + blanket_radial_thickness: float = 50.0, + blanket_rear_wall_radial_thickness: float = 30.0, + elongation: float = 2.0, + triangularity: float = 0.55, + plasma_gap_vertical_thickness: float = 50.0, + divertor_to_tf_gap_vertical_thickness: Optional[float] = 0.0, + number_of_tf_coils: Optional[int] = 12, + rear_blanket_to_tf_gap: Optional[float] = None, + pf_coil_radial_thicknesses: List[float] = [], + pf_coil_vertical_thicknesses: List[float] = [], + pf_coil_radial_position: List[float] = [], + pf_coil_vertical_position: List[float] = [], + pf_coil_case_thicknesses: List[float] = [], + outboard_tf_coil_radial_thickness: float = None, + outboard_tf_coil_poloidal_thickness: float = None, + divertor_position: Optional[str] = "both", + rotation_angle: Optional[str] = 180.0, +): """Creates geometry for a simple ball reactor including a plasma, cylindrical center column shielding, square toroidal field coils. There is no inboard breeder blanket on this ball reactor like @@ -59,448 +86,161 @@ class BallReactor(paramak.Reactor): rotation_angle: the angle of the sector that is desired. """ - def __init__( - self, - inner_bore_radial_thickness: float = 10.0, - inboard_tf_leg_radial_thickness: float = 30.0, - center_column_shield_radial_thickness: float = 60.0, - divertor_radial_thickness: float = 150.0, - inner_plasma_gap_radial_thickness: float = 30.0, - plasma_radial_thickness: float = 300.0, - outer_plasma_gap_radial_thickness: float = 30.0, - firstwall_radial_thickness: float = 30.0, - blanket_radial_thickness: float = 50.0, - blanket_rear_wall_radial_thickness: float = 30.0, - elongation: float = 2.0, - triangularity: float = 0.55, - plasma_gap_vertical_thickness: float = 50.0, - divertor_to_tf_gap_vertical_thickness: Optional[float] = 0.0, - number_of_tf_coils: Optional[int] = 12, - rear_blanket_to_tf_gap: Optional[float] = None, - pf_coil_radial_thicknesses: List[float] = [], - pf_coil_vertical_thicknesses: List[float] = [], - pf_coil_radial_position: List[float] = [], - pf_coil_vertical_position: List[float] = [], - pf_coil_case_thicknesses: List[float] = [], - outboard_tf_coil_radial_thickness: float = None, - outboard_tf_coil_poloidal_thickness: float = None, - divertor_position: Optional[str] = "both", - rotation_angle: Optional[str] = 180.0, - ): - - super().__init__([]) - - self.inner_bore_radial_thickness = inner_bore_radial_thickness - self.inboard_tf_leg_radial_thickness = inboard_tf_leg_radial_thickness - self.center_column_shield_radial_thickness = center_column_shield_radial_thickness - self.divertor_radial_thickness = divertor_radial_thickness - self.inner_plasma_gap_radial_thickness = inner_plasma_gap_radial_thickness - self.plasma_radial_thickness = plasma_radial_thickness - self.outer_plasma_gap_radial_thickness = outer_plasma_gap_radial_thickness - self.firstwall_radial_thickness = firstwall_radial_thickness - self.blanket_radial_thickness = blanket_radial_thickness - self.blanket_rear_wall_radial_thickness = blanket_rear_wall_radial_thickness - - self.pf_coil_vertical_position = pf_coil_vertical_position - self.pf_coil_radial_position = pf_coil_radial_position - self.pf_coil_radial_thicknesses = pf_coil_radial_thicknesses - self.pf_coil_vertical_thicknesses = pf_coil_vertical_thicknesses - self.rear_blanket_to_tf_gap = rear_blanket_to_tf_gap - - self.pf_coil_case_thicknesses = pf_coil_case_thicknesses - self.outboard_tf_coil_radial_thickness = outboard_tf_coil_radial_thickness - self.outboard_tf_coil_poloidal_thickness = outboard_tf_coil_poloidal_thickness - self.divertor_position = divertor_position - self.rotation_angle = rotation_angle - - self.plasma_gap_vertical_thickness = plasma_gap_vertical_thickness - self.divertor_to_tf_gap_vertical_thickness = divertor_to_tf_gap_vertical_thickness - - self.elongation = elongation - self.triangularity = triangularity - - self.number_of_tf_coils = number_of_tf_coils - self.rotation_angle = rotation_angle - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_bore_radial_thickness", - "inboard_tf_leg_radial_thickness", - "center_column_shield_radial_thickness", - "divertor_radial_thickness", - "inner_plasma_gap_radial_thickness", - "plasma_radial_thickness", - "outer_plasma_gap_radial_thickness", - "firstwall_radial_thickness", - "blanket_radial_thickness", - "blanket_rear_wall_radial_thickness", - "elongation", - "triangularity", - "plasma_gap_vertical_thickness", - "divertor_to_tf_gap_vertical_thickness", - "number_of_tf_coils", - "rear_blanket_to_tf_gap", - "pf_coil_radial_thicknesses", - "pf_coil_vertical_thicknesses", - "pf_coil_radial_position", - "pf_coil_vertical_position", - "pf_coil_case_thicknesses", - "outboard_tf_coil_radial_thickness", - "outboard_tf_coil_poloidal_thickness", - "divertor_position", - "rotation_angle", - ] - - # set by make_plasma - self.major_radius = None - self.minor_radius = None - - # set during geometry creation - self._pf_coils = None - self._pf_coils_casing = None - self._divertor_lower = None - self._divertor_upper = None - - @property - def rotation_angle(self): - return self._rotation_angle - - @rotation_angle.setter - def rotation_angle(self, value): - if value == 360: - msg = "360 degree rotation may result in a " "Standard_ConstructionError or AttributeError" - warnings.warn(msg, UserWarning) - elif value > 360: - raise ValueError("rotation_angle can not be larger than 360") - self._rotation_angle = value - - @property - def pf_coil_vertical_position(self): - return self._pf_coil_vertical_position - - @pf_coil_vertical_position.setter - def pf_coil_vertical_position(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_vertical_position must be a list") - self._pf_coil_vertical_position = value - - @property - def pf_coil_radial_position(self): - return self._pf_coil_radial_position - - @pf_coil_radial_position.setter - def pf_coil_radial_position(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_radial_position must be a list") - self._pf_coil_radial_position = value - - @property - def pf_coil_radial_thicknesses(self): - return self._pf_coil_radial_thicknesses - - @pf_coil_radial_thicknesses.setter - def pf_coil_radial_thicknesses(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_radial_thicknesses must be a list") - self._pf_coil_radial_thicknesses = value - - @property - def pf_coil_vertical_thicknesses(self): - return self._pf_coil_vertical_thicknesses - - @pf_coil_vertical_thicknesses.setter - def pf_coil_vertical_thicknesses(self, value): - if not isinstance(value, list): - raise ValueError("pf_coil_vertical_thicknesses must be a list") - self._pf_coil_vertical_thicknesses = value - - @property - def divertor_position(self): - return self._divertor_position - - @divertor_position.setter - def divertor_position(self, value): - acceptable_values = ["upper", "lower", "both"] - if value in acceptable_values: - self._divertor_position = value - else: - msg = "divertor_position must be 'upper', 'lower' or 'both'" - raise ValueError(msg) - - def create_solids(self): - """Creates a list of paramak.Shape for components and saves it in - self.shapes_and_components - """ - - uncut_shapes = [] - - uncut_shapes.append(self._make_plasma()) - self._make_radial_build() - self._make_vertical_build() - uncut_shapes.append(self._make_inboard_tf_coils()) - uncut_shapes.append(self._make_center_column_shield()) - uncut_shapes += self._make_blankets_layers() - uncut_shapes += self._make_divertor() - uncut_shapes += self._make_tf_coils() - pf_coils = self._make_pf_coils() - - if pf_coils is None: - shapes_and_components = uncut_shapes - else: - for shape in uncut_shapes: - for pf_coil in pf_coils: - shape.solid = shape.solid.cut(pf_coil.solid) - shapes_and_components = uncut_shapes + pf_coils - - self.shapes_and_components = shapes_and_components - - def _make_plasma(self): - - inner_equatorial_point = ( - self.inner_bore_radial_thickness - + self.inboard_tf_leg_radial_thickness - + self.center_column_shield_radial_thickness - + self.inner_plasma_gap_radial_thickness - ) - outer_equatorial_point = inner_equatorial_point + self.plasma_radial_thickness - - # sets major radius and minor radius from equatorial_points to allow a - # radial build. This helps avoid the plasma overlapping the center - # column and other components - self.major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 - self.minor_radius = self.major_radius - inner_equatorial_point - - plasma = paramak.Plasma( - major_radius=self.major_radius, - minor_radius=self.minor_radius, - elongation=self.elongation, - triangularity=self.triangularity, - rotation_angle=self.rotation_angle, - ) - - self._plasma = plasma - return self._plasma - - def _make_radial_build(self): - - # this is the radial build sequence, where one component stops and - # another starts - - self._inner_bore_start_radius = 0 - self._inner_bore_end_radius = self._inner_bore_start_radius + self.inner_bore_radial_thickness - - self._inboard_tf_coils_start_radius = self._inner_bore_end_radius - self._inboard_tf_coils_end_radius = self._inboard_tf_coils_start_radius + self.inboard_tf_leg_radial_thickness - - self._center_column_shield_start_radius = self._inboard_tf_coils_end_radius - self._center_column_shield_end_radius = ( - self._center_column_shield_start_radius + self.center_column_shield_radial_thickness - ) - - self._divertor_start_radius = self._center_column_shield_end_radius - self._divertor_end_radius = self._center_column_shield_end_radius + self.divertor_radial_thickness - - self._firstwall_start_radius = ( - self._center_column_shield_end_radius - + self.inner_plasma_gap_radial_thickness - + self.plasma_radial_thickness - + self.outer_plasma_gap_radial_thickness - ) - self._firstwall_end_radius = self._firstwall_start_radius + self.firstwall_radial_thickness - - self._blanket_start_radius = self._firstwall_end_radius - self._blanket_end_radius = self._blanket_start_radius + self.blanket_radial_thickness - - self._blanket_rear_wall_start_radius = self._blanket_end_radius - self._blanket_rear_wall_end_radius = ( - self._blanket_rear_wall_start_radius + self.blanket_rear_wall_radial_thickness - ) - - def _make_vertical_build(self): - - # this is the vertical build sequence, components build on each other - # in a similar manner to the radial build - - self._firstwall_start_height = self._plasma.high_point[1] + self.plasma_gap_vertical_thickness - self._firstwall_end_height = self._firstwall_start_height + self.firstwall_radial_thickness - - self._blanket_start_height = self._firstwall_end_height - self._blanket_end_height = self._blanket_start_height + self.blanket_radial_thickness + def _make_inboard_tf_coils(): - self._blanket_rear_wall_start_height = self._blanket_end_height - self._blanket_rear_wall_end_height = ( - self._blanket_rear_wall_start_height + self.blanket_rear_wall_radial_thickness - ) - - self._tf_coil_start_height = self._blanket_rear_wall_end_height + self.divertor_to_tf_gap_vertical_thickness - - self._center_column_shield_height = self._blanket_rear_wall_end_height * 2 - - if self.rear_blanket_to_tf_gap is not None: - self._tf_coil_start_radius = self._blanket_rear_wall_end_radius + self.rear_blanket_to_tf_gap - self._tf_coil_end_radius = self._tf_coil_start_radius + self.outboard_tf_coil_radial_thickness - - def _make_inboard_tf_coils(self): - - self._inboard_tf_coils = paramak.CenterColumnShieldCylinder( - height=self._tf_coil_start_height * 2, - inner_radius=self._inboard_tf_coils_start_radius, - outer_radius=self._inboard_tf_coils_end_radius, - rotation_angle=self.rotation_angle, + _inboard_tf_coils = paramak.CenterColumnShieldCylinder( + height=_tf_coil_start_height * 2, + inner_radius=_inboard_tf_coils_start_radius, + outer_radius=_inboard_tf_coils_end_radius, + rotation_angle=rotation_angle, name="inboard_tf_coils", color=(0, 0, 1), ) - return self._inboard_tf_coils + return _inboard_tf_coils - def _make_center_column_shield(self): + def _make_center_column_shield(): - self._center_column_shield = paramak.CenterColumnShieldCylinder( - height=self._center_column_shield_height, - inner_radius=self._center_column_shield_start_radius, - outer_radius=self._center_column_shield_end_radius, - rotation_angle=self.rotation_angle, + _center_column_shield = paramak.CenterColumnShieldCylinder( + height=_center_column_shield_height, + inner_radius=_center_column_shield_start_radius, + outer_radius=_center_column_shield_end_radius, + rotation_angle=rotation_angle, color=(0.0, 0.333, 0.0), name="center_column_shield", ) - return self._center_column_shield + return _center_column_shield - def _make_blankets_layers(self): + def _make_blankets_layers(): offset_from_plasma = [ - self.major_radius - self.minor_radius, - self.plasma_gap_vertical_thickness, - self.outer_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.major_radius - self.minor_radius, + major_radius - minor_radius, + plasma_gap_vertical_thickness, + outer_plasma_gap_radial_thickness, + plasma_gap_vertical_thickness, + major_radius - minor_radius, ] - self._center_column_cutter = paramak.CenterColumnShieldCylinder( + _center_column_cutter = paramak.CenterColumnShieldCylinder( # extra 0.5 to ensure overlap, - height=self._center_column_shield_height * 1.5, + height=_center_column_shield_height * 1.5, inner_radius=0, - outer_radius=self._center_column_shield_end_radius, + outer_radius=_center_column_shield_end_radius, rotation_angle=360, color=(0.0, 0.0, 1.0), ) - self._firstwall = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.firstwall_radial_thickness, + _firstwall = paramak.BlanketFP( + plasma=plasma, + thickness=firstwall_radial_thickness, offset_from_plasma=offset_from_plasma, start_angle=-180, stop_angle=180, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, color=(0.5, 0.5, 0.5), name="firstwall", - cut=[self._center_column_cutter], + cut=[_center_column_cutter], allow_overlapping_shape=True, ) - self._blanket = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.blanket_radial_thickness, - offset_from_plasma=[e + self.firstwall_radial_thickness for e in offset_from_plasma], + _blanket = paramak.BlanketFP( + plasma=plasma, + thickness=blanket_radial_thickness, + offset_from_plasma=[e + firstwall_radial_thickness for e in offset_from_plasma], start_angle=-180, stop_angle=180, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, color=(0.0, 1.0, 0.498), name="blanket", - cut=[self._center_column_cutter], + cut=[_center_column_cutter], allow_overlapping_shape=True, ) - self._blanket_rear_wall = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.blanket_rear_wall_radial_thickness, + _blanket_rear_wall = paramak.BlanketFP( + plasma=plasma, + thickness=blanket_rear_wall_radial_thickness, offset_from_plasma=[ - e + self.firstwall_radial_thickness + self.blanket_radial_thickness for e in offset_from_plasma + e + firstwall_radial_thickness + blanket_radial_thickness for e in offset_from_plasma ], start_angle=-180, stop_angle=180, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, color=(0.0, 1.0, 1.0), name="blanket_rear_wall", - cut=[self._center_column_cutter], + cut=[_center_column_cutter], allow_overlapping_shape=True, ) - return [self._firstwall, self._blanket, self._blanket_rear_wall] + return _firstwall, _blanket, _blanket_rear_wall - def _make_divertor(self): + def _make_divertor(): offset_from_plasma = [ - self.major_radius - self.minor_radius, - self.plasma_gap_vertical_thickness, - self.outer_plasma_gap_radial_thickness, - self.plasma_gap_vertical_thickness, - self.major_radius - self.minor_radius, + major_radius - minor_radius, + plasma_gap_vertical_thickness, + outer_plasma_gap_radial_thickness, + plasma_gap_vertical_thickness, + major_radius - minor_radius, ] # used as an intersect when making the divertor - self._blanket_fw_rear_wall_envelope = paramak.BlanketFP( - plasma=self._plasma, - thickness=self.firstwall_radial_thickness - + self.blanket_radial_thickness - + self.blanket_rear_wall_radial_thickness, + _blanket_fw_rear_wall_envelope = paramak.BlanketFP( + plasma=plasma, + thickness=firstwall_radial_thickness + + blanket_radial_thickness + + blanket_rear_wall_radial_thickness, offset_from_plasma=offset_from_plasma, start_angle=-180, stop_angle=180, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, allow_overlapping_shape=True, ) - divertor_height = self._blanket_rear_wall_end_height * 2 + divertor_height = _blanket_rear_wall_end_height * 2 divertor_height_top = divertor_height divertor_height_bottom = -divertor_height - if self.divertor_position in ["lower", "both"]: - self._divertor_lower = paramak.RotateStraightShape( + if divertor_position in ["lower", "both"]: + _divertor_lower = paramak.RotateStraightShape( points=[ - (self._divertor_start_radius, divertor_height_bottom), - (self._divertor_end_radius, divertor_height_bottom), - (self._divertor_end_radius, 0), - (self._divertor_start_radius, 0), + (_divertor_start_radius, divertor_height_bottom), + (_divertor_end_radius, divertor_height_bottom), + (_divertor_end_radius, 0), + (_divertor_start_radius, 0), ], - intersect=self._blanket_fw_rear_wall_envelope, + intersect=_blanket_fw_rear_wall_envelope, name="divertor_lower", color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - if self.divertor_position in ["upper", "both"]: - self._divertor_upper = paramak.RotateStraightShape( + if divertor_position in ["upper", "both"]: + _divertor_upper = paramak.RotateStraightShape( points=[ - (self._divertor_start_radius, 0), - (self._divertor_end_radius, 0), - (self._divertor_end_radius, divertor_height_top), - (self._divertor_start_radius, divertor_height_top), + (_divertor_start_radius, 0), + (_divertor_end_radius, 0), + (_divertor_end_radius, divertor_height_top), + (_divertor_start_radius, divertor_height_top), ], - intersect=self._blanket_fw_rear_wall_envelope, + intersect=_blanket_fw_rear_wall_envelope, name="divertor_upper", color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - for component in [self._firstwall, self._blanket, self._blanket_rear_wall]: - if self.divertor_position in ["upper", "both"]: - component.cut.append(self._divertor_upper) - if self.divertor_position in ["lower", "both"]: - component.cut.append(self._divertor_lower) + if divertor_position == "upper": + return [_divertor_upper] + if divertor_position == "lower": + return [_divertor_lower] + if divertor_position == "both": + return [_divertor_upper, _divertor_lower] - if self.divertor_position == "upper": - return [self._divertor_upper] - if self.divertor_position == "lower": - return [self._divertor_lower] - if self.divertor_position == "both": - return [self._divertor_upper, self._divertor_lower] - - def _make_pf_coils(self): + def _make_pf_coils(): pf_input_lists = [ - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, - self.pf_coil_vertical_position, - self.pf_coil_radial_position, + pf_coil_vertical_thicknesses, + pf_coil_radial_thicknesses, + pf_coil_vertical_position, + pf_coil_radial_position, ] # checks if lists are all the same length @@ -509,14 +249,14 @@ def _make_pf_coils(self): if number_of_pf_coils == 0: return None - center_points = [(x, y) for x, y in zip(self.pf_coil_radial_position, self.pf_coil_vertical_position)] + center_points = [(x, y) for x, y in zip(pf_coil_radial_position, pf_coil_vertical_position)] - self._pf_coils = [] + _pf_coils = [] for counter, (center_point, pf_coil_vertical_thickness, pf_coil_radial_thickness,) in enumerate( zip( center_points, - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, + pf_coil_vertical_thicknesses, + pf_coil_radial_thicknesses, ), 1, ): @@ -524,26 +264,26 @@ def _make_pf_coils(self): height=pf_coil_vertical_thickness, width=pf_coil_radial_thickness, center_point=center_point, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, name=f"pf_coil_{counter}", ) - self._pf_coils.append(pf_coil) + _pf_coils.append(pf_coil) - if self.pf_coil_case_thicknesses == []: - return self._pf_coils + if pf_coil_case_thicknesses == []: + return _pf_coils - self._pf_coils_casing = [] - if len(self.pf_coil_case_thicknesses) == number_of_pf_coils: + _pf_coils_casing = [] + if len(pf_coil_case_thicknesses) == number_of_pf_coils: for counter, (pf_coil_case_thickness, pf_coil) in enumerate( - zip(self.pf_coil_case_thicknesses, self._pf_coils), 1 + zip(pf_coil_case_thicknesses, _pf_coils), 1 ): pf_coils_casing = paramak.PoloidalFieldCoilCaseFC( pf_coil=pf_coil, casing_thickness=pf_coil_case_thickness, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, name=f"pf_coil_case_{counter}", ) - self._pf_coils_casing.append(pf_coils_casing) + _pf_coils_casing.append(pf_coils_casing) else: raise ValueError( "pf_coil_case_thicknesses is not the same length as the other " @@ -552,7 +292,7 @@ def _make_pf_coils(self): "pf_coil_vertical_position) so can not make pf coils cases" ) - return self._pf_coils + self._pf_coils_casing + return _pf_coils + _pf_coils_casing raise ValueError( "pf_coil_vertical_thicknesses, pf_coil_radial_thicknesses, " @@ -560,32 +300,161 @@ def _make_pf_coils(self): "the same length so can not make PF coils" ) - def _make_tf_coils(self): + def _make_tf_coils(): comp = [] # checks that all the required information has been input by the user if ( None not in [ - self.rear_blanket_to_tf_gap, - self.outboard_tf_coil_radial_thickness, - self.outboard_tf_coil_poloidal_thickness, - self.number_of_tf_coils, + rear_blanket_to_tf_gap, + outboard_tf_coil_radial_thickness, + outboard_tf_coil_poloidal_thickness, + number_of_tf_coils, ] - and self.number_of_tf_coils > 1 + and number_of_tf_coils > 1 ): - self._tf_coil = paramak.ToroidalFieldCoilRectangle( + _tf_coil = paramak.ToroidalFieldCoilRectangle( with_inner_leg=False, horizontal_start_point=( - self._inboard_tf_coils_start_radius, - self._tf_coil_start_height, + _inboard_tf_coils_start_radius, + _tf_coil_start_height, ), - vertical_mid_point=(self._tf_coil_start_radius, 0), - thickness=self.outboard_tf_coil_radial_thickness, - number_of_coils=self.number_of_tf_coils, - distance=self.outboard_tf_coil_poloidal_thickness, + vertical_mid_point=(_tf_coil_start_radius, 0), + thickness=outboard_tf_coil_radial_thickness, + number_of_coils=number_of_tf_coils, + distance=outboard_tf_coil_poloidal_thickness, name="tf_coil", - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - comp = [self._tf_coil] + comp = [_tf_coil] return comp + + uncut_shapes = [] + + inner_equatorial_point = ( + inner_bore_radial_thickness + + inboard_tf_leg_radial_thickness + + center_column_shield_radial_thickness + + inner_plasma_gap_radial_thickness + ) + outer_equatorial_point = inner_equatorial_point + plasma_radial_thickness + + # sets major radius and minor radius from equatorial_points to allow a + # radial build. This helps avoid the plasma overlapping the center + # column and other components + major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 + minor_radius = major_radius - inner_equatorial_point + + plasma = paramak.Plasma( + major_radius=major_radius, + minor_radius=minor_radius, + elongation=elongation, + triangularity=triangularity, + rotation_angle=rotation_angle, + ) + + uncut_shapes.append(plasma) + + + + # this is the radial build sequence, where one component stops and + # another starts + + _inner_bore_start_radius = 0 + _inner_bore_end_radius = _inner_bore_start_radius + inner_bore_radial_thickness + + _inboard_tf_coils_start_radius = _inner_bore_end_radius + _inboard_tf_coils_end_radius = _inboard_tf_coils_start_radius + inboard_tf_leg_radial_thickness + + _center_column_shield_start_radius = _inboard_tf_coils_end_radius + _center_column_shield_end_radius = ( + _center_column_shield_start_radius + center_column_shield_radial_thickness + ) + + _divertor_start_radius = _center_column_shield_end_radius + _divertor_end_radius = _center_column_shield_end_radius + divertor_radial_thickness + + _firstwall_start_radius = ( + _center_column_shield_end_radius + + inner_plasma_gap_radial_thickness + + plasma_radial_thickness + + outer_plasma_gap_radial_thickness + ) + _firstwall_end_radius = _firstwall_start_radius + firstwall_radial_thickness + + _blanket_start_radius = _firstwall_end_radius + _blanket_end_radius = _blanket_start_radius + blanket_radial_thickness + + _blanket_rear_wall_start_radius = _blanket_end_radius + _blanket_rear_wall_end_radius = ( + _blanket_rear_wall_start_radius + blanket_rear_wall_radial_thickness + ) + + + # this is the vertical build sequence, components build on each other + # in a similar manner to the radial build + + _firstwall_start_height = plasma.high_point[1] + plasma_gap_vertical_thickness + _firstwall_end_height = _firstwall_start_height + firstwall_radial_thickness + + _blanket_start_height = _firstwall_end_height + _blanket_end_height = _blanket_start_height + blanket_radial_thickness + + _blanket_rear_wall_start_height = _blanket_end_height + _blanket_rear_wall_end_height = ( + _blanket_rear_wall_start_height + blanket_rear_wall_radial_thickness + ) + + _tf_coil_start_height = _blanket_rear_wall_end_height + divertor_to_tf_gap_vertical_thickness + + _center_column_shield_height = _blanket_rear_wall_end_height * 2 + + if rear_blanket_to_tf_gap is not None: + _tf_coil_start_radius = _blanket_rear_wall_end_radius + rear_blanket_to_tf_gap + _tf_coil_end_radius = _tf_coil_start_radius + outboard_tf_coil_radial_thickness + + + inboard_tf_coils = _make_inboard_tf_coils() + uncut_shapes.append(inboard_tf_coils) + center_column_shield = _make_center_column_shield() + firstwall, blanket, blanket_rear_wall = _make_blankets_layers() + divertors = _make_divertor() + + for divertor in divertors: + for component in [firstwall, blanket, blanket_rear_wall]: + component.solid.cut(divertor.solid) + + uncut_shapes.append(divertor) + uncut_shapes += [firstwall, blanket, blanket_rear_wall] + + uncut_shapes += _make_tf_coils() + pf_coils = _make_pf_coils() + + if pf_coils is None: + shapes_and_components = uncut_shapes + else: + for shape in uncut_shapes: + for pf_coil in pf_coils: + shape.solid = shape.solid.cut(pf_coil.solid) + shapes_and_components = uncut_shapes + pf_coils + + shapes_and_components = shapes_and_components + + colors=[(0.5, 0.5, 0.5)] + + assembly = cq.Assembly(name='BallReactor') + + for i, shape in enumerate(shapes_and_components): + assembly.add(shape.solid, name=str(i)) + + + # .add(blanket.solid,name='blanket', color=cq.Color(*colors[0])) + # .add(vac_vessel.solid,name='vac_vessel') + # .add(upper_blanket.solid,name='upper_blanket') + # .add(lower_blanket.solid,name='lower_blanket') + # .add(lower_vac_vessel.solid,name='lower_vac_vessel') + # .add(upper_vac_vessel.solid,name='upper_vac_vessel') + # ) + + return assembly \ No newline at end of file From cd66d31e21569fc5f77f9269662027c8ed5ced9e Mon Sep 17 00:00:00 2001 From: shimwell Date: Sun, 29 Jan 2023 11:42:27 +0000 Subject: [PATCH 12/16] [skip ci] Apply formatting changes --- src/paramak/__init__.py | 1 + .../parametric_reactors/ball_reactor.py | 48 +++++++------------ 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/paramak/__init__.py b/src/paramak/__init__.py index bea66ea10..6f959129d 100644 --- a/src/paramak/__init__.py +++ b/src/paramak/__init__.py @@ -138,6 +138,7 @@ # from .parametric_reactors.eu_demo_2015_reactor import EuDemoFrom2015PaperDiagram from .parametric_reactors.ball_reactor import BallReactor + # from .parametric_reactors.submersion_reactor import SubmersionTokamak # from .parametric_reactors.single_null_submersion_reactor import ( # SingleNullSubmersionTokamak, diff --git a/src/paramak/parametric_reactors/ball_reactor.py b/src/paramak/parametric_reactors/ball_reactor.py index 3eb5b6221..1dd839597 100644 --- a/src/paramak/parametric_reactors/ball_reactor.py +++ b/src/paramak/parametric_reactors/ball_reactor.py @@ -1,4 +1,3 @@ - from typing import List, Optional import paramak @@ -158,9 +157,7 @@ def _make_blankets_layers(): _blanket_rear_wall = paramak.BlanketFP( plasma=plasma, thickness=blanket_rear_wall_radial_thickness, - offset_from_plasma=[ - e + firstwall_radial_thickness + blanket_radial_thickness for e in offset_from_plasma - ], + offset_from_plasma=[e + firstwall_radial_thickness + blanket_radial_thickness for e in offset_from_plasma], start_angle=-180, stop_angle=180, rotation_angle=rotation_angle, @@ -185,9 +182,7 @@ def _make_divertor(): # used as an intersect when making the divertor _blanket_fw_rear_wall_envelope = paramak.BlanketFP( plasma=plasma, - thickness=firstwall_radial_thickness - + blanket_radial_thickness - + blanket_rear_wall_radial_thickness, + thickness=firstwall_radial_thickness + blanket_radial_thickness + blanket_rear_wall_radial_thickness, offset_from_plasma=offset_from_plasma, start_angle=-180, stop_angle=180, @@ -353,10 +348,8 @@ def _make_tf_coils(): triangularity=triangularity, rotation_angle=rotation_angle, ) - + uncut_shapes.append(plasma) - - # this is the radial build sequence, where one component stops and # another starts @@ -368,9 +361,7 @@ def _make_tf_coils(): _inboard_tf_coils_end_radius = _inboard_tf_coils_start_radius + inboard_tf_leg_radial_thickness _center_column_shield_start_radius = _inboard_tf_coils_end_radius - _center_column_shield_end_radius = ( - _center_column_shield_start_radius + center_column_shield_radial_thickness - ) + _center_column_shield_end_radius = _center_column_shield_start_radius + center_column_shield_radial_thickness _divertor_start_radius = _center_column_shield_end_radius _divertor_end_radius = _center_column_shield_end_radius + divertor_radial_thickness @@ -387,10 +378,7 @@ def _make_tf_coils(): _blanket_end_radius = _blanket_start_radius + blanket_radial_thickness _blanket_rear_wall_start_radius = _blanket_end_radius - _blanket_rear_wall_end_radius = ( - _blanket_rear_wall_start_radius + blanket_rear_wall_radial_thickness - ) - + _blanket_rear_wall_end_radius = _blanket_rear_wall_start_radius + blanket_rear_wall_radial_thickness # this is the vertical build sequence, components build on each other # in a similar manner to the radial build @@ -402,9 +390,7 @@ def _make_tf_coils(): _blanket_end_height = _blanket_start_height + blanket_radial_thickness _blanket_rear_wall_start_height = _blanket_end_height - _blanket_rear_wall_end_height = ( - _blanket_rear_wall_start_height + blanket_rear_wall_radial_thickness - ) + _blanket_rear_wall_end_height = _blanket_rear_wall_start_height + blanket_rear_wall_radial_thickness _tf_coil_start_height = _blanket_rear_wall_end_height + divertor_to_tf_gap_vertical_thickness @@ -414,20 +400,19 @@ def _make_tf_coils(): _tf_coil_start_radius = _blanket_rear_wall_end_radius + rear_blanket_to_tf_gap _tf_coil_end_radius = _tf_coil_start_radius + outboard_tf_coil_radial_thickness - inboard_tf_coils = _make_inboard_tf_coils() uncut_shapes.append(inboard_tf_coils) center_column_shield = _make_center_column_shield() firstwall, blanket, blanket_rear_wall = _make_blankets_layers() divertors = _make_divertor() - - for divertor in divertors: + + for divertor in divertors: for component in [firstwall, blanket, blanket_rear_wall]: component.solid.cut(divertor.solid) - + uncut_shapes.append(divertor) uncut_shapes += [firstwall, blanket, blanket_rear_wall] - + uncut_shapes += _make_tf_coils() pf_coils = _make_pf_coils() @@ -441,20 +426,19 @@ def _make_tf_coils(): shapes_and_components = shapes_and_components - colors=[(0.5, 0.5, 0.5)] + colors = [(0.5, 0.5, 0.5)] + + assembly = cq.Assembly(name="BallReactor") - assembly = cq.Assembly(name='BallReactor') - for i, shape in enumerate(shapes_and_components): assembly.add(shape.solid, name=str(i)) - - + # .add(blanket.solid,name='blanket', color=cq.Color(*colors[0])) - # .add(vac_vessel.solid,name='vac_vessel') + # .add(vac_vessel.solid,name='vac_vessel') # .add(upper_blanket.solid,name='upper_blanket') # .add(lower_blanket.solid,name='lower_blanket') # .add(lower_vac_vessel.solid,name='lower_vac_vessel') # .add(upper_vac_vessel.solid,name='upper_vac_vessel') # ) - return assembly \ No newline at end of file + return assembly From c116b73fe63df909b8b17d59f905e66cde8da8d4 Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 13 Feb 2023 00:06:05 +0000 Subject: [PATCH 13/16] ball reactor names assigned correctly --- .../parametric_reactors/ball_reactor.py | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/paramak/parametric_reactors/ball_reactor.py b/src/paramak/parametric_reactors/ball_reactor.py index 1dd839597..35ecde842 100644 --- a/src/paramak/parametric_reactors/ball_reactor.py +++ b/src/paramak/parametric_reactors/ball_reactor.py @@ -223,11 +223,11 @@ def _make_divertor(): ) if divertor_position == "upper": - return [_divertor_upper] + return [(_divertor_upper, 'divertor_upper')] if divertor_position == "lower": - return [_divertor_lower] + return [(_divertor_lower, 'divertor_lower')] if divertor_position == "both": - return [_divertor_upper, _divertor_lower] + return [(_divertor_lower, 'divertor_lower'),(_divertor_upper, 'divertor_upper')] def _make_pf_coils(): @@ -262,7 +262,7 @@ def _make_pf_coils(): rotation_angle=rotation_angle, name=f"pf_coil_{counter}", ) - _pf_coils.append(pf_coil) + _pf_coils.append((pf_coil, 'pf_coils')) if pf_coil_case_thicknesses == []: return _pf_coils @@ -278,7 +278,7 @@ def _make_pf_coils(): rotation_angle=rotation_angle, name=f"pf_coil_case_{counter}", ) - _pf_coils_casing.append(pf_coils_casing) + _pf_coils_casing.append((pf_coils_casing, 'pf_coils_casing')) else: raise ValueError( "pf_coil_case_thicknesses is not the same length as the other " @@ -296,7 +296,7 @@ def _make_pf_coils(): ) def _make_tf_coils(): - comp = [] + comp = None # checks that all the required information has been input by the user if ( None @@ -322,7 +322,7 @@ def _make_tf_coils(): name="tf_coil", rotation_angle=rotation_angle, ) - comp = [_tf_coil] + comp = (_tf_coil, 'tf_coil') return comp uncut_shapes = [] @@ -349,7 +349,7 @@ def _make_tf_coils(): rotation_angle=rotation_angle, ) - uncut_shapes.append(plasma) + uncut_shapes.append((plasma, 'plasma')) # this is the radial build sequence, where one component stops and # another starts @@ -401,44 +401,40 @@ def _make_tf_coils(): _tf_coil_end_radius = _tf_coil_start_radius + outboard_tf_coil_radial_thickness inboard_tf_coils = _make_inboard_tf_coils() - uncut_shapes.append(inboard_tf_coils) + uncut_shapes.append((inboard_tf_coils, 'inboard_tf_coils')) center_column_shield = _make_center_column_shield() firstwall, blanket, blanket_rear_wall = _make_blankets_layers() divertors = _make_divertor() - for divertor in divertors: + for (divertor, name) in divertors: for component in [firstwall, blanket, blanket_rear_wall]: component.solid.cut(divertor.solid) - uncut_shapes.append(divertor) - uncut_shapes += [firstwall, blanket, blanket_rear_wall] + uncut_shapes.append((divertor, name)) - uncut_shapes += _make_tf_coils() + uncut_shapes.append((firstwall, 'firstwall')) + uncut_shapes.append((blanket, 'blanket')) + uncut_shapes.append((blanket_rear_wall, 'blanket_rear_wall')) + + tf_coils = _make_tf_coils() + if tf_coils: + uncut_shapes.append((tf_coils, 'tf_coils')) + pf_coils = _make_pf_coils() if pf_coils is None: shapes_and_components = uncut_shapes else: - for shape in uncut_shapes: + for (shape, name) in uncut_shapes: for pf_coil in pf_coils: shape.solid = shape.solid.cut(pf_coil.solid) shapes_and_components = uncut_shapes + pf_coils - shapes_and_components = shapes_and_components - colors = [(0.5, 0.5, 0.5)] assembly = cq.Assembly(name="BallReactor") - for i, shape in enumerate(shapes_and_components): - assembly.add(shape.solid, name=str(i)) - - # .add(blanket.solid,name='blanket', color=cq.Color(*colors[0])) - # .add(vac_vessel.solid,name='vac_vessel') - # .add(upper_blanket.solid,name='upper_blanket') - # .add(lower_blanket.solid,name='lower_blanket') - # .add(lower_vac_vessel.solid,name='lower_vac_vessel') - # .add(upper_vac_vessel.solid,name='upper_vac_vessel') - # ) + for (shape, name) in shapes_and_components: + assembly.add(shape.solid, name=name) return assembly From f9b52d9e003ef5f4e906cd933c8cd2f510cba712 Mon Sep 17 00:00:00 2001 From: shimwell Date: Mon, 13 Feb 2023 00:07:27 +0000 Subject: [PATCH 14/16] [skip ci] Apply formatting changes --- .../parametric_reactors/ball_reactor.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/paramak/parametric_reactors/ball_reactor.py b/src/paramak/parametric_reactors/ball_reactor.py index 35ecde842..7cd6c380a 100644 --- a/src/paramak/parametric_reactors/ball_reactor.py +++ b/src/paramak/parametric_reactors/ball_reactor.py @@ -223,11 +223,11 @@ def _make_divertor(): ) if divertor_position == "upper": - return [(_divertor_upper, 'divertor_upper')] + return [(_divertor_upper, "divertor_upper")] if divertor_position == "lower": - return [(_divertor_lower, 'divertor_lower')] + return [(_divertor_lower, "divertor_lower")] if divertor_position == "both": - return [(_divertor_lower, 'divertor_lower'),(_divertor_upper, 'divertor_upper')] + return [(_divertor_lower, "divertor_lower"), (_divertor_upper, "divertor_upper")] def _make_pf_coils(): @@ -262,7 +262,7 @@ def _make_pf_coils(): rotation_angle=rotation_angle, name=f"pf_coil_{counter}", ) - _pf_coils.append((pf_coil, 'pf_coils')) + _pf_coils.append((pf_coil, "pf_coils")) if pf_coil_case_thicknesses == []: return _pf_coils @@ -278,7 +278,7 @@ def _make_pf_coils(): rotation_angle=rotation_angle, name=f"pf_coil_case_{counter}", ) - _pf_coils_casing.append((pf_coils_casing, 'pf_coils_casing')) + _pf_coils_casing.append((pf_coils_casing, "pf_coils_casing")) else: raise ValueError( "pf_coil_case_thicknesses is not the same length as the other " @@ -322,7 +322,7 @@ def _make_tf_coils(): name="tf_coil", rotation_angle=rotation_angle, ) - comp = (_tf_coil, 'tf_coil') + comp = (_tf_coil, "tf_coil") return comp uncut_shapes = [] @@ -349,7 +349,7 @@ def _make_tf_coils(): rotation_angle=rotation_angle, ) - uncut_shapes.append((plasma, 'plasma')) + uncut_shapes.append((plasma, "plasma")) # this is the radial build sequence, where one component stops and # another starts @@ -401,7 +401,7 @@ def _make_tf_coils(): _tf_coil_end_radius = _tf_coil_start_radius + outboard_tf_coil_radial_thickness inboard_tf_coils = _make_inboard_tf_coils() - uncut_shapes.append((inboard_tf_coils, 'inboard_tf_coils')) + uncut_shapes.append((inboard_tf_coils, "inboard_tf_coils")) center_column_shield = _make_center_column_shield() firstwall, blanket, blanket_rear_wall = _make_blankets_layers() divertors = _make_divertor() @@ -412,14 +412,14 @@ def _make_tf_coils(): uncut_shapes.append((divertor, name)) - uncut_shapes.append((firstwall, 'firstwall')) - uncut_shapes.append((blanket, 'blanket')) - uncut_shapes.append((blanket_rear_wall, 'blanket_rear_wall')) + uncut_shapes.append((firstwall, "firstwall")) + uncut_shapes.append((blanket, "blanket")) + uncut_shapes.append((blanket_rear_wall, "blanket_rear_wall")) tf_coils = _make_tf_coils() if tf_coils: - uncut_shapes.append((tf_coils, 'tf_coils')) - + uncut_shapes.append((tf_coils, "tf_coils")) + pf_coils = _make_pf_coils() if pf_coils is None: From 91d3159c462f0858f71a066180210cd8768fa651 Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 14 Feb 2023 23:15:56 +0000 Subject: [PATCH 15/16] save --- .../parametric_reactors/submersion_reactor.py | 788 ++++++++---------- 1 file changed, 327 insertions(+), 461 deletions(-) diff --git a/src/paramak/parametric_reactors/submersion_reactor.py b/src/paramak/parametric_reactors/submersion_reactor.py index 5c6144396..a27f0afda 100644 --- a/src/paramak/parametric_reactors/submersion_reactor.py +++ b/src/paramak/parametric_reactors/submersion_reactor.py @@ -6,7 +6,34 @@ import paramak -class SubmersionTokamak(paramak.Reactor): +def SubmersionTokamak( + inner_bore_radial_thickness: float = 30.0, + inboard_tf_leg_radial_thickness: float = 30, + center_column_shield_radial_thickness: float = 30, + inboard_blanket_radial_thickness: float = 80, + firstwall_radial_thickness: float = 20, + inner_plasma_gap_radial_thickness: float = 50, + plasma_radial_thickness: float = 200, + divertor_radial_thickness: float = 80, + support_radial_thickness: float = 90, + outer_plasma_gap_radial_thickness: float = 50, + outboard_blanket_radial_thickness: float = 30, + blanket_rear_wall_radial_thickness: float = 30, + elongation: float = 2.0, + triangularity: float = 0.5, + number_of_tf_coils: int = 16, + rotation_angle: float = 180.0, + outboard_tf_coil_radial_thickness: Optional[float] = None, + rear_blanket_to_tf_gap: Optional[float] = None, + outboard_tf_coil_poloidal_thickness: Optional[float] = None, + pf_coil_radial_thicknesses: List[float] = [], + pf_coil_vertical_thicknesses: List[float] = [], + pf_coil_radial_position: List[float] = [], + pf_coil_vertical_position: List[float] = [], + pf_coil_case_thicknesses: List[float] = [], + divertor_position: Optional[str] = "both", + support_position: Optional[str] = "both", +): """Creates geometry for a simple submersion reactor including a plasma, cylindrical center column shielding, inboard and outboard breeder blanket, divertor (upper and lower), support legs. Optional coat hanger shaped @@ -54,557 +81,282 @@ class SubmersionTokamak(paramak.Reactor): "both". Defaults to "both". """ - def __init__( - self, - inner_bore_radial_thickness: float = 30.0, - inboard_tf_leg_radial_thickness: float = 30, - center_column_shield_radial_thickness: float = 30, - inboard_blanket_radial_thickness: float = 80, - firstwall_radial_thickness: float = 20, - inner_plasma_gap_radial_thickness: float = 50, - plasma_radial_thickness: float = 200, - divertor_radial_thickness: float = 80, - support_radial_thickness: float = 90, - outer_plasma_gap_radial_thickness: float = 50, - outboard_blanket_radial_thickness: float = 30, - blanket_rear_wall_radial_thickness: float = 30, - elongation: float = 2.0, - triangularity: float = 0.5, - number_of_tf_coils: int = 16, - rotation_angle: float = 180.0, - outboard_tf_coil_radial_thickness: Optional[float] = None, - rear_blanket_to_tf_gap: Optional[float] = None, - outboard_tf_coil_poloidal_thickness: Optional[float] = None, - pf_coil_radial_thicknesses: List[float] = [], - pf_coil_vertical_thicknesses: List[float] = [], - pf_coil_radial_position: List[float] = [], - pf_coil_vertical_position: List[float] = [], - pf_coil_case_thicknesses: List[float] = [], - divertor_position: Optional[str] = "both", - support_position: Optional[str] = "both", - ): - - super().__init__([]) - - self.inner_bore_radial_thickness = inner_bore_radial_thickness - self.inboard_tf_leg_radial_thickness = inboard_tf_leg_radial_thickness - self.center_column_shield_radial_thickness = center_column_shield_radial_thickness - self.inboard_blanket_radial_thickness = inboard_blanket_radial_thickness - self.firstwall_radial_thickness = firstwall_radial_thickness - self.inner_plasma_gap_radial_thickness = inner_plasma_gap_radial_thickness - self.plasma_radial_thickness = plasma_radial_thickness - self.outer_plasma_gap_radial_thickness = outer_plasma_gap_radial_thickness - self.outboard_blanket_radial_thickness = outboard_blanket_radial_thickness - self.blanket_rear_wall_radial_thickness = blanket_rear_wall_radial_thickness - self.pf_coil_radial_thicknesses = pf_coil_radial_thicknesses - self.outboard_tf_coil_radial_thickness = outboard_tf_coil_radial_thickness - self.outboard_tf_coil_poloidal_thickness = outboard_tf_coil_poloidal_thickness - self.divertor_radial_thickness = divertor_radial_thickness - self.support_radial_thickness = support_radial_thickness - self.elongation = elongation - self.triangularity = triangularity - self.rear_blanket_to_tf_gap = rear_blanket_to_tf_gap - self.pf_coil_vertical_thicknesses = pf_coil_vertical_thicknesses - self.pf_coil_case_thicknesses = pf_coil_case_thicknesses - self.number_of_tf_coils = number_of_tf_coils - self.rotation_angle = rotation_angle - self.divertor_position = divertor_position - self.support_position = support_position - self.pf_coil_vertical_position = pf_coil_vertical_position - self.pf_coil_radial_position = pf_coil_radial_position - - # adds self.input_variable_names from the Reactor class - self.input_variable_names: List[str] = self.input_variable_names + [ - "inner_bore_radial_thickness", - "inboard_tf_leg_radial_thickness", - "center_column_shield_radial_thickness", - "inboard_blanket_radial_thickness", - "firstwall_radial_thickness", - "inner_plasma_gap_radial_thickness", - "plasma_radial_thickness", - "divertor_radial_thickness", - "support_radial_thickness", - "outer_plasma_gap_radial_thickness", - "outboard_blanket_radial_thickness", - "blanket_rear_wall_radial_thickness", - "elongation", - "triangularity", - "number_of_tf_coils", - "rotation_angle", - "outboard_tf_coil_radial_thickness", - "rear_blanket_to_tf_gap", - "outboard_tf_coil_poloidal_thickness", - "pf_coil_vertical_thicknesses", - "pf_coil_radial_thicknesses", - "pf_coil_radial_position", - "pf_coil_vertical_position", - "pf_coil_case_thicknesses", - "divertor_position", - "support_position", - ] + def _rotation_angle_check(): - # set by make_plasma - self.major_radius = None - self.minor_radius = None - - # set during geometry creation - self._pf_coils = None - self._pf_coils_casing = None - self._divertor_lower = None - self._divertor_upper = None - - @property - def pf_coil_radial_position(self): - return self._pf_coil_radial_position - - @pf_coil_radial_position.setter - def pf_coil_radial_position(self, value): - if not isinstance(value, list) and value is not None: - raise ValueError("pf_coil_radial_position must be a list") - self._pf_coil_radial_position = value - - @property - def pf_coil_radial_thicknesses(self): - return self._pf_coil_radial_thicknesses - - @pf_coil_radial_thicknesses.setter - def pf_coil_radial_thicknesses(self, value): - if not isinstance(value, list) and value is not None: - raise ValueError("pf_coil_radial_thicknesses must be a list") - self._pf_coil_radial_thicknesses = value - - @property - def pf_coil_vertical_thicknesses(self): - return self._pf_coil_vertical_thicknesses - - @pf_coil_vertical_thicknesses.setter - def pf_coil_vertical_thicknesses(self, value): - if not isinstance(value, list) and value is not None: - raise ValueError("pf_coil_vertical_thicknesses must be a list") - self._pf_coil_vertical_thicknesses = value - - @property - def divertor_position(self): - return self._divertor_position - - @divertor_position.setter - def divertor_position(self, value): - acceptable_values = ["upper", "lower", "both"] - if value in acceptable_values: - self._divertor_position = value - else: - msg = "divertor_position must be 'upper', 'lower' or 'both'" - raise ValueError(msg) - - @property - def support_position(self): - return self._support_position - - @support_position.setter - def support_position(self, value): - acceptable_values = ["upper", "lower", "both"] - if value in acceptable_values: - self._support_position = value - else: - msg = "support_position must be 'upper', 'lower' or 'both'" - raise ValueError(msg) - - def create_solids(self): - """Creates a list of paramak.Shape for components and saves it in - self.shapes_and_components - """ - - uncut_shapes = [] - - self._rotation_angle_check() - uncut_shapes.append(self._make_plasma()) - self._make_radial_build() - self._make_vertical_build() - uncut_shapes.append(self._make_center_column_shield()) - uncut_shapes.append(self._make_firstwall()) - uncut_shapes.append(self._make_blanket()) - uncut_shapes += self._make_divertor() - uncut_shapes.append(self._make_supports()) - uncut_shapes.append(self._make_rear_blanket_wall()) - uncut_shapes += self._make_tf_coils() - pf_coils = self._make_pf_coils() - - if pf_coils is None: - shapes_and_components = uncut_shapes - else: - for shape in uncut_shapes: - print(shape, shape.name) - for pf_coil in pf_coils: - shape.solid = shape.solid.cut(pf_coil.solid) - shapes_and_components = pf_coils + uncut_shapes - - self.shapes_and_components = shapes_and_components - - def _rotation_angle_check(self): - - if self.rotation_angle == 360: + if rotation_angle == 360: msg = "360 degree rotation may result" + " in a Standard_ConstructionError or AttributeError" warnings.warn(msg, UserWarning) - def _make_radial_build(self): - - # this is the radial build sequence, where one component stops and - # another starts - - self._inner_bore_start_radius = 0 - self._inner_bore_end_radius = self._inner_bore_start_radius + self.inner_bore_radial_thickness - - self._inboard_tf_coils_start_radius = self._inner_bore_end_radius - self._inboard_tf_coils_end_radius = self._inboard_tf_coils_start_radius + self.inboard_tf_leg_radial_thickness - - self._center_column_shield_start_radius = self._inboard_tf_coils_end_radius - self._center_column_shield_end_radius = ( - self._center_column_shield_start_radius + self.center_column_shield_radial_thickness - ) - - self._inboard_blanket_start_radius = self._center_column_shield_end_radius - self._inboard_blanket_end_radius = self._inboard_blanket_start_radius + self.inboard_blanket_radial_thickness - - self._inboard_firstwall_start_radius = self._inboard_blanket_end_radius - self._inboard_firstwall_end_radius = self._inboard_firstwall_start_radius + self.firstwall_radial_thickness - - self._inner_plasma_gap_start_radius = self._inboard_firstwall_end_radius - self._inner_plasma_gap_end_radius = self._inner_plasma_gap_start_radius + self.inner_plasma_gap_radial_thickness - - self._plasma_start_radius = self._inner_plasma_gap_end_radius - self._plasma_end_radius = self._plasma_start_radius + self.plasma_radial_thickness - - self._outer_plasma_gap_start_radius = self._plasma_end_radius - self._outer_plasma_gap_end_radius = self._outer_plasma_gap_start_radius + self.outer_plasma_gap_radial_thickness - - self._outboard_firstwall_start_radius = self._outer_plasma_gap_end_radius - self._outboard_firstwall_end_radius = self._outboard_firstwall_start_radius + self.firstwall_radial_thickness - - self._outboard_blanket_start_radius = self._outboard_firstwall_end_radius - self._outboard_blanket_end_radius = self._outboard_blanket_start_radius + self.outboard_blanket_radial_thickness - - self._blanket_rear_wall_start_radius = self._outboard_blanket_end_radius - self._blanket_rear_wall_end_radius = ( - self._blanket_rear_wall_start_radius + self.blanket_rear_wall_radial_thickness - ) - - self._tf_info_provided = False - if ( - self.outboard_tf_coil_radial_thickness is not None - and self.rear_blanket_to_tf_gap is not None - and self.outboard_tf_coil_poloidal_thickness is not None - ): - self._tf_info_provided = True - self._outboard_tf_coil_start_radius = self._blanket_rear_wall_end_radius + self.rear_blanket_to_tf_gap - self._outboard_tf_coil_end_radius = ( - self._outboard_tf_coil_start_radius + self.outboard_tf_coil_radial_thickness - ) - - self._divertor_start_radius = self._plasma.high_point[0] - 0.5 * self.divertor_radial_thickness - self._divertor_end_radius = self._plasma.high_point[0] + 0.5 * self.divertor_radial_thickness - - self._support_start_radius = self._plasma.high_point[0] - 0.5 * self.support_radial_thickness - self._support_end_radius = self._plasma.high_point[0] + 0.5 * self.support_radial_thickness - - def _make_vertical_build(self): - - # this is the vertical build sequence, componets build on each other in - # a similar manner to the radial build - - self._plasma_start_height = 0 - self._plasma_end_height = self._plasma.high_point[1] - - self._plasma_to_divertor_gap_start_height = self._plasma_end_height - self._plasma_to_divertor_gap_end_height = ( - self._plasma_to_divertor_gap_start_height + self.outer_plasma_gap_radial_thickness - ) - - # the firstwall is cut by the divertor but uses the same control points - self._firstwall_start_height = self._plasma_to_divertor_gap_end_height - self._firstwall_end_height = self._firstwall_start_height + self.firstwall_radial_thickness - - self._blanket_start_height = self._firstwall_end_height - self._blanket_end_height = self._blanket_start_height + self.outboard_blanket_radial_thickness - - self._blanket_rear_wall_start_height = self._blanket_end_height - self._blanket_rear_wall_end_height = ( - self._blanket_rear_wall_start_height + self.blanket_rear_wall_radial_thickness - ) - - if self._tf_info_provided: - self._outboard_tf_coils_vertical_height = self._blanket_rear_wall_end_height * 1.5 - self._outboard_tf_coils_horizontal_length = self._blanket_rear_wall_end_radius * 0.75 - - def _make_center_column_shield(self): + def _make_center_column_shield(): - self._center_column_shield = paramak.CenterColumnShieldCylinder( - height=self._blanket_rear_wall_end_height * 2, - inner_radius=self._center_column_shield_start_radius, - outer_radius=self._center_column_shield_end_radius, - rotation_angle=self.rotation_angle, + _center_column_shield = paramak.CenterColumnShieldCylinder( + height=_blanket_rear_wall_end_height * 2, + inner_radius=_center_column_shield_start_radius, + outer_radius=_center_column_shield_end_radius, + rotation_angle=rotation_angle, name="center_column_shield", ) - return self._center_column_shield + return _center_column_shield - def _make_plasma(self): + def _make_plasma(): # sets major radius and minor radius from equatorial_points to allow a # radial build this helps avoid the plasma overlapping the center # column and other components inner_equatorial_point = ( - self.inner_bore_radial_thickness - + self.inboard_tf_leg_radial_thickness - + self.center_column_shield_radial_thickness - + self.inboard_blanket_radial_thickness - + self.firstwall_radial_thickness - + self.inner_plasma_gap_radial_thickness + inner_bore_radial_thickness + + inboard_tf_leg_radial_thickness + + center_column_shield_radial_thickness + + inboard_blanket_radial_thickness + + firstwall_radial_thickness + + inner_plasma_gap_radial_thickness ) - outer_equatorial_point = inner_equatorial_point + self.plasma_radial_thickness - self.major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 - self.minor_radius = self.major_radius - inner_equatorial_point + outer_equatorial_point = inner_equatorial_point + plasma_radial_thickness + major_radius = (outer_equatorial_point + inner_equatorial_point) / 2 + minor_radius = major_radius - inner_equatorial_point plasma = paramak.Plasma( - major_radius=self.major_radius, - minor_radius=self.minor_radius, - elongation=self.elongation, - triangularity=self.triangularity, - rotation_angle=self.rotation_angle, + major_radius=major_radius, + minor_radius=minor_radius, + elongation=elongation, + triangularity=triangularity, + rotation_angle=rotation_angle, ) - self._plasma = plasma - return self._plasma + _plasma = plasma + return _plasma - def _make_firstwall(self): + def _make_firstwall(): # this is used to cut the inboard blanket and then fused / unioned with # the firstwall - self._inboard_firstwall = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.inner_plasma_gap_radial_thickness, + _inboard_firstwall = paramak.BlanketFP( + plasma=_plasma, + offset_from_plasma=inner_plasma_gap_radial_thickness, start_angle=90, stop_angle=270, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, + thickness=firstwall_radial_thickness, + rotation_angle=rotation_angle, color=(0.5, 0.5, 0.5), ) - self._firstwall = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.outer_plasma_gap_radial_thickness, + _firstwall = paramak.BlanketFP( + plasma=_plasma, + offset_from_plasma=outer_plasma_gap_radial_thickness, start_angle=90, stop_angle=-90, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, + thickness=firstwall_radial_thickness, + rotation_angle=rotation_angle, name="outboard_firstwall", - union=self._inboard_firstwall, + union=_inboard_firstwall, color=(0.5, 0.5, 0.5), ) - return self._firstwall + return _firstwall - def _make_divertor(self): + def _make_divertor(): fw_envelope_inboard = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.inner_plasma_gap_radial_thickness, + plasma=_plasma, + offset_from_plasma=inner_plasma_gap_radial_thickness, start_angle=90, stop_angle=270, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, + thickness=firstwall_radial_thickness, + rotation_angle=rotation_angle, ) fw_envelope = paramak.BlanketFP( - plasma=self._plasma, - offset_from_plasma=self.outer_plasma_gap_radial_thickness, + plasma=_plasma, + offset_from_plasma=outer_plasma_gap_radial_thickness, start_angle=90, stop_angle=-90, - thickness=self.firstwall_radial_thickness, - rotation_angle=self.rotation_angle, + thickness=firstwall_radial_thickness, + rotation_angle=rotation_angle, name="outboard_firstwall", union=fw_envelope_inboard, ) - divertor_height = self._blanket_rear_wall_end_height + divertor_height = _blanket_rear_wall_end_height divertor_height_top = divertor_height divertor_height_bottom = -divertor_height - if self.divertor_position in ["lower", "both"]: - self._divertor_lower = paramak.RotateStraightShape( + if divertor_position in ["lower", "both"]: + _divertor_lower = paramak.RotateStraightShape( points=[ - (self._divertor_start_radius, divertor_height_bottom), - (self._divertor_end_radius, divertor_height_bottom), - (self._divertor_end_radius, 0), - (self._divertor_start_radius, 0), + (_divertor_start_radius, divertor_height_bottom), + (_divertor_end_radius, divertor_height_bottom), + (_divertor_end_radius, 0), + (_divertor_start_radius, 0), ], intersect=fw_envelope, name="divertor_lower", color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - if self.divertor_position in ["upper", "both"]: - self._divertor_upper = paramak.RotateStraightShape( + if divertor_position in ["upper", "both"]: + _divertor_upper = paramak.RotateStraightShape( points=[ - (self._divertor_start_radius, 0), - (self._divertor_end_radius, 0), - (self._divertor_end_radius, divertor_height_top), - (self._divertor_start_radius, divertor_height_top), + (_divertor_start_radius, 0), + (_divertor_end_radius, 0), + (_divertor_end_radius, divertor_height_top), + (_divertor_start_radius, divertor_height_top), ], intersect=fw_envelope, name="divertor_upper", color=(1.0, 0.667, 0.0), - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - if self.divertor_position == "upper": - cut_list = [self._divertor_upper] - if self.divertor_position == "lower": - cut_list = [self._divertor_lower] - if self.divertor_position == "both": - cut_list = [self._divertor_lower, self._divertor_upper] - self._firstwall.cut = cut_list - self._inboard_firstwall.cut = cut_list - - if self.divertor_position == "upper": - return [self._divertor_upper] - if self.divertor_position == "lower": - return [self._divertor_lower] - if self.divertor_position == "both": - return [self._divertor_upper, self._divertor_lower] - - def _make_blanket(self): - self._inboard_blanket = paramak.CenterColumnShieldCylinder( - height=self._blanket_end_height * 2, - inner_radius=self._inboard_blanket_start_radius, - outer_radius=max(self._inboard_firstwall.points)[0], - rotation_angle=self.rotation_angle, - cut=self._inboard_firstwall, + if divertor_position == "upper": + cut_list = [_divertor_upper] + if divertor_position == "lower": + cut_list = [_divertor_lower] + if divertor_position == "both": + cut_list = [_divertor_lower, _divertor_upper] + _firstwall.cut = cut_list + _inboard_firstwall.cut = cut_list + + if divertor_position == "upper": + return [_divertor_upper] + if divertor_position == "lower": + return [_divertor_lower] + if divertor_position == "both": + return [_divertor_upper, _divertor_lower] + + def _make_blanket(): + _inboard_blanket = paramak.CenterColumnShieldCylinder( + height=_blanket_end_height * 2, + inner_radius=_inboard_blanket_start_radius, + outer_radius=max(_inboard_firstwall.points)[0], + rotation_angle=rotation_angle, + cut=_inboard_firstwall, ) # this takes a single solid from a compound of solids by finding the # solid nearest to a point # TODO: find alternative - self._inboard_blanket.solid = self._inboard_blanket.solid.solids(cq.selectors.NearestToPointSelector((0, 0, 0))) + _inboard_blanket.solid = _inboard_blanket.solid.solids(cq.selectors.NearestToPointSelector((0, 0, 0))) # this is the outboard fused /unioned with the inboard blanket - self._blanket = paramak.BlanketFP( - plasma=self._plasma, + _blanket = paramak.BlanketFP( + plasma=_plasma, start_angle=90, stop_angle=-90, - offset_from_plasma=self.outer_plasma_gap_radial_thickness + self.firstwall_radial_thickness, - thickness=self.outboard_blanket_radial_thickness, - rotation_angle=self.rotation_angle, + offset_from_plasma=outer_plasma_gap_radial_thickness + firstwall_radial_thickness, + thickness=outboard_blanket_radial_thickness, + rotation_angle=rotation_angle, name="blanket", color=(0.0, 1.0, 0.498), - union=self._inboard_blanket, + union=_inboard_blanket, ) - return self._blanket + return _blanket - def _make_supports(self): + def _make_supports(): blanket_envelope = paramak.BlanketFP( - plasma=self._plasma, + plasma=_plasma, start_angle=90, stop_angle=-90, - offset_from_plasma=self.outer_plasma_gap_radial_thickness + self.firstwall_radial_thickness, - thickness=self.outboard_blanket_radial_thickness, - rotation_angle=self.rotation_angle, - union=self._inboard_blanket, + offset_from_plasma=outer_plasma_gap_radial_thickness + firstwall_radial_thickness, + thickness=outboard_blanket_radial_thickness, + rotation_angle=rotation_angle, + union=_inboard_blanket, ) - support_height = self._blanket_rear_wall_end_height + support_height = _blanket_rear_wall_end_height support_height_top = support_height support_height_bottom = -support_height - if self.support_position == "lower": + if support_position == "lower": support_height_top = 0 - elif self.support_position == "upper": + elif support_position == "upper": support_height_bottom = 0 - self._supports = paramak.RotateStraightShape( + _supports = paramak.RotateStraightShape( points=[ - (self._support_start_radius, support_height_bottom), - (self._support_end_radius, support_height_bottom), - (self._support_end_radius, support_height_top), - (self._support_start_radius, support_height_top), + (_support_start_radius, support_height_bottom), + (_support_end_radius, support_height_bottom), + (_support_end_radius, support_height_top), + (_support_start_radius, support_height_top), ], - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, name="supports", color=(0.0, 0.0, 0.0), intersect=blanket_envelope, ) - self._blanket.solid = self._blanket.solid.cut(self._supports.solid) + _blanket.solid = _blanket.solid.cut(_supports.solid) - return self._supports + return _supports - def _make_rear_blanket_wall(self): - self._outboard_rear_blanket_wall_upper = paramak.RotateStraightShape( + def _make_rear_blanket_wall(): + _outboard_rear_blanket_wall_upper = paramak.RotateStraightShape( points=[ ( - self._center_column_shield_end_radius, - self._blanket_rear_wall_start_height, + _center_column_shield_end_radius, + _blanket_rear_wall_start_height, ), ( - self._center_column_shield_end_radius, - self._blanket_rear_wall_end_height, + _center_column_shield_end_radius, + _blanket_rear_wall_end_height, ), ( - max(self._inboard_firstwall.points)[0], - self._blanket_rear_wall_end_height, + max(_inboard_firstwall.points)[0], + _blanket_rear_wall_end_height, ), ( - max(self._inboard_firstwall.points)[0], - self._blanket_rear_wall_start_height, + max(_inboard_firstwall.points)[0], + _blanket_rear_wall_start_height, ), ], - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - self._outboard_rear_blanket_wall_lower = paramak.RotateStraightShape( + _outboard_rear_blanket_wall_lower = paramak.RotateStraightShape( points=[ ( - self._center_column_shield_end_radius, - -self._blanket_rear_wall_start_height, + _center_column_shield_end_radius, + -_blanket_rear_wall_start_height, ), ( - self._center_column_shield_end_radius, - -self._blanket_rear_wall_end_height, + _center_column_shield_end_radius, + -_blanket_rear_wall_end_height, ), ( - max(self._inboard_firstwall.points)[0], - -self._blanket_rear_wall_end_height, + max(_inboard_firstwall.points)[0], + -_blanket_rear_wall_end_height, ), ( - max(self._inboard_firstwall.points)[0], - -self._blanket_rear_wall_start_height, + max(_inboard_firstwall.points)[0], + -_blanket_rear_wall_start_height, ), ], - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, ) - self._outboard_rear_blanket_wall = paramak.BlanketFP( - plasma=self._plasma, + _outboard_rear_blanket_wall = paramak.BlanketFP( + plasma=_plasma, start_angle=90, stop_angle=-90, - offset_from_plasma=self.outer_plasma_gap_radial_thickness - + self.firstwall_radial_thickness - + self.outboard_blanket_radial_thickness, - thickness=self.blanket_rear_wall_radial_thickness, - rotation_angle=self.rotation_angle, + offset_from_plasma=outer_plasma_gap_radial_thickness + + firstwall_radial_thickness + + outboard_blanket_radial_thickness, + thickness=blanket_rear_wall_radial_thickness, + rotation_angle=rotation_angle, name="outboard_rear_blanket_wall", color=(0.0, 1.0, 1.0), union=[ - self._outboard_rear_blanket_wall_upper, - self._outboard_rear_blanket_wall_lower, + _outboard_rear_blanket_wall_upper, + _outboard_rear_blanket_wall_lower, ], ) - return self._outboard_rear_blanket_wall + return _outboard_rear_blanket_wall - def _make_pf_coils(self): + def _make_pf_coils(): pf_input_lists = [ - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, - self.pf_coil_vertical_position, - self.pf_coil_radial_position, + pf_coil_vertical_thicknesses, + pf_coil_radial_thicknesses, + pf_coil_vertical_position, + pf_coil_radial_position, ] # checks if lists are all the same length @@ -613,14 +365,14 @@ def _make_pf_coils(self): if number_of_pf_coils == 0: return None - center_points = [(x, y) for x, y in zip(self.pf_coil_radial_position, self.pf_coil_vertical_position)] + center_points = [(x, y) for x, y in zip(pf_coil_radial_position, pf_coil_vertical_position)] - self._pf_coils = [] + _pf_coils = [] for counter, (center_point, pf_coil_vertical_thickness, pf_coil_radial_thickness,) in enumerate( zip( center_points, - self.pf_coil_vertical_thicknesses, - self.pf_coil_radial_thicknesses, + pf_coil_vertical_thicknesses, + pf_coil_radial_thicknesses, ), 1, ): @@ -628,26 +380,26 @@ def _make_pf_coils(self): height=pf_coil_vertical_thickness, width=pf_coil_radial_thickness, center_point=center_point, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, name=f"pf_coil_{counter}", ) - self._pf_coils.append(pf_coil) + _pf_coils.append(pf_coil) - if self.pf_coil_case_thicknesses == []: - return self._pf_coils + if pf_coil_case_thicknesses == []: + return _pf_coils - self._pf_coils_casing = [] - if len(self.pf_coil_case_thicknesses) == number_of_pf_coils: + _pf_coils_casing = [] + if len(pf_coil_case_thicknesses) == number_of_pf_coils: for counter, (pf_coil_case_thickness, pf_coil) in enumerate( - zip(self.pf_coil_case_thicknesses, self._pf_coils), 1 + zip(pf_coil_case_thicknesses, _pf_coils), 1 ): pf_coils_casing = paramak.PoloidalFieldCoilCaseFC( pf_coil=pf_coil, casing_thickness=pf_coil_case_thickness, - rotation_angle=self.rotation_angle, + rotation_angle=rotation_angle, name=f"pf_coil_case_{counter}", ) - self._pf_coils_casing.append(pf_coils_casing) + _pf_coils_casing.append(pf_coils_casing) else: raise ValueError( "pf_coil_case_thicknesses is not the same length as the other " @@ -656,48 +408,162 @@ def _make_pf_coils(self): "pf_coil_vertical_position) so can not make pf coils cases" ) - return self._pf_coils + self._pf_coils_casing + return _pf_coils + _pf_coils_casing - def _make_tf_coils(self): + def _make_tf_coils(): list_of_components = [] - self._inboard_tf_coils = paramak.CenterColumnShieldCylinder( - height=self._blanket_rear_wall_end_height * 2, - inner_radius=self._inboard_tf_coils_start_radius, - outer_radius=self._inboard_tf_coils_end_radius, - rotation_angle=self.rotation_angle, + _inboard_tf_coils = paramak.CenterColumnShieldCylinder( + height=_blanket_rear_wall_end_height * 2, + inner_radius=_inboard_tf_coils_start_radius, + outer_radius=_inboard_tf_coils_end_radius, + rotation_angle=rotation_angle, name="inboard_tf_coils", color=(0, 0, 1), ) - list_of_components.append(self._inboard_tf_coils) + list_of_components.append(_inboard_tf_coils) if ( None not in [ - self.rear_blanket_to_tf_gap, - self.outboard_tf_coil_radial_thickness, - self.outboard_tf_coil_poloidal_thickness, - self.number_of_tf_coils, + rear_blanket_to_tf_gap, + outboard_tf_coil_radial_thickness, + outboard_tf_coil_poloidal_thickness, + number_of_tf_coils, ] - and self.number_of_tf_coils > 1 + and number_of_tf_coils > 1 ): - if self._tf_info_provided: - self._tf_coil = paramak.ToroidalFieldCoilCoatHanger( + if _tf_info_provided: + _tf_coil = paramak.ToroidalFieldCoilCoatHanger( with_inner_leg=False, horizontal_start_point=( - self._inboard_tf_coils_start_radius, - self._blanket_rear_wall_end_height, + _inboard_tf_coils_start_radius, + _blanket_rear_wall_end_height, ), - vertical_mid_point=(self._outboard_tf_coil_start_radius, 0), - thickness=self.outboard_tf_coil_radial_thickness, - number_of_coils=self.number_of_tf_coils, - distance=self.outboard_tf_coil_poloidal_thickness, - rotation_angle=self.rotation_angle, - horizontal_length=self._outboard_tf_coils_horizontal_length, - vertical_length=self._outboard_tf_coils_vertical_height, + vertical_mid_point=(_outboard_tf_coil_start_radius, 0), + thickness=outboard_tf_coil_radial_thickness, + number_of_coils=number_of_tf_coils, + distance=outboard_tf_coil_poloidal_thickness, + rotation_angle=rotation_angle, + horizontal_length=_outboard_tf_coils_horizontal_length, + vertical_length=_outboard_tf_coils_vertical_height, name="tf_coils", ) - list_of_components.append(self._tf_coil) + list_of_components.append(_tf_coil) return list_of_components + + uncut_shapes = [] + + _rotation_angle_check() + _plasma = uncut_shapes.append(_make_plasma()) + + # this is the radial build sequence, where one component stops and + # another starts + + _inner_bore_start_radius = 0 + _inner_bore_end_radius = _inner_bore_start_radius + inner_bore_radial_thickness + + _inboard_tf_coils_start_radius = _inner_bore_end_radius + _inboard_tf_coils_end_radius = _inboard_tf_coils_start_radius + inboard_tf_leg_radial_thickness + + _center_column_shield_start_radius = _inboard_tf_coils_end_radius + _center_column_shield_end_radius = ( + _center_column_shield_start_radius + center_column_shield_radial_thickness + ) + + _inboard_blanket_start_radius = _center_column_shield_end_radius + _inboard_blanket_end_radius = _inboard_blanket_start_radius + inboard_blanket_radial_thickness + + _inboard_firstwall_start_radius = _inboard_blanket_end_radius + _inboard_firstwall_end_radius = _inboard_firstwall_start_radius + firstwall_radial_thickness + + _inner_plasma_gap_start_radius = _inboard_firstwall_end_radius + _inner_plasma_gap_end_radius = _inner_plasma_gap_start_radius + inner_plasma_gap_radial_thickness + + _plasma_start_radius = _inner_plasma_gap_end_radius + _plasma_end_radius = _plasma_start_radius + plasma_radial_thickness + + _outer_plasma_gap_start_radius = _plasma_end_radius + _outer_plasma_gap_end_radius = _outer_plasma_gap_start_radius + outer_plasma_gap_radial_thickness + + _outboard_firstwall_start_radius = _outer_plasma_gap_end_radius + _outboard_firstwall_end_radius = _outboard_firstwall_start_radius + firstwall_radial_thickness + + _outboard_blanket_start_radius = _outboard_firstwall_end_radius + _outboard_blanket_end_radius = _outboard_blanket_start_radius + outboard_blanket_radial_thickness + + _blanket_rear_wall_start_radius = _outboard_blanket_end_radius + _blanket_rear_wall_end_radius = ( + _blanket_rear_wall_start_radius + blanket_rear_wall_radial_thickness + ) + + _tf_info_provided = False + if ( + outboard_tf_coil_radial_thickness is not None + and rear_blanket_to_tf_gap is not None + and outboard_tf_coil_poloidal_thickness is not None + ): + _tf_info_provided = True + _outboard_tf_coil_start_radius = _blanket_rear_wall_end_radius + rear_blanket_to_tf_gap + _outboard_tf_coil_end_radius = ( + _outboard_tf_coil_start_radius + outboard_tf_coil_radial_thickness + ) + + _divertor_start_radius = _plasma.high_point[0] - 0.5 * divertor_radial_thickness + _divertor_end_radius = _plasma.high_point[0] + 0.5 * divertor_radial_thickness + + _support_start_radius = _plasma.high_point[0] - 0.5 * support_radial_thickness + _support_end_radius = _plasma.high_point[0] + 0.5 * support_radial_thickness + + + + # this is the vertical build sequence, componets build on each other in + # a similar manner to the radial build + + # _plasma_start_height = 0 + _plasma_end_height = _plasma.high_point[1] + + _plasma_to_divertor_gap_start_height = _plasma_end_height + _plasma_to_divertor_gap_end_height = ( + _plasma_to_divertor_gap_start_height + outer_plasma_gap_radial_thickness + ) + + # the firstwall is cut by the divertor but uses the same control points + _firstwall_start_height = _plasma_to_divertor_gap_end_height + _firstwall_end_height = _firstwall_start_height + firstwall_radial_thickness + + _blanket_start_height = _firstwall_end_height + _blanket_end_height = _blanket_start_height + outboard_blanket_radial_thickness + + _blanket_rear_wall_start_height = _blanket_end_height + _blanket_rear_wall_end_height = ( + _blanket_rear_wall_start_height + blanket_rear_wall_radial_thickness + ) + + if _tf_info_provided: + _outboard_tf_coils_vertical_height = _blanket_rear_wall_end_height * 1.5 + _outboard_tf_coils_horizontal_length = _blanket_rear_wall_end_radius * 0.75 + + + uncut_shapes.append(_make_center_column_shield()) + uncut_shapes.append(_make_firstwall()) + uncut_shapes.append(_make_blanket()) + uncut_shapes += _make_divertor() + uncut_shapes.append(_make_supports()) + uncut_shapes.append(_make_rear_blanket_wall()) + uncut_shapes += _make_tf_coils() + pf_coils = _make_pf_coils() + + if pf_coils is None: + shapes_and_components = uncut_shapes + else: + for shape in uncut_shapes: + print(shape, shape.name) + for pf_coil in pf_coils: + shape.solid = shape.solid.cut(pf_coil.solid) + shapes_and_components = pf_coils + uncut_shapes + + shapes_and_components = shapes_and_components + From c0eb01657cb28db218e7a4e704cc8b0d572fd2a9 Mon Sep 17 00:00:00 2001 From: shimwell Date: Tue, 14 Feb 2023 23:16:23 +0000 Subject: [PATCH 16/16] [skip ci] Apply formatting changes --- .../parametric_reactors/submersion_reactor.py | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/paramak/parametric_reactors/submersion_reactor.py b/src/paramak/parametric_reactors/submersion_reactor.py index a27f0afda..7ea3ff4d7 100644 --- a/src/paramak/parametric_reactors/submersion_reactor.py +++ b/src/paramak/parametric_reactors/submersion_reactor.py @@ -469,9 +469,7 @@ def _make_tf_coils(): _inboard_tf_coils_end_radius = _inboard_tf_coils_start_radius + inboard_tf_leg_radial_thickness _center_column_shield_start_radius = _inboard_tf_coils_end_radius - _center_column_shield_end_radius = ( - _center_column_shield_start_radius + center_column_shield_radial_thickness - ) + _center_column_shield_end_radius = _center_column_shield_start_radius + center_column_shield_radial_thickness _inboard_blanket_start_radius = _center_column_shield_end_radius _inboard_blanket_end_radius = _inboard_blanket_start_radius + inboard_blanket_radial_thickness @@ -495,9 +493,7 @@ def _make_tf_coils(): _outboard_blanket_end_radius = _outboard_blanket_start_radius + outboard_blanket_radial_thickness _blanket_rear_wall_start_radius = _outboard_blanket_end_radius - _blanket_rear_wall_end_radius = ( - _blanket_rear_wall_start_radius + blanket_rear_wall_radial_thickness - ) + _blanket_rear_wall_end_radius = _blanket_rear_wall_start_radius + blanket_rear_wall_radial_thickness _tf_info_provided = False if ( @@ -507,9 +503,7 @@ def _make_tf_coils(): ): _tf_info_provided = True _outboard_tf_coil_start_radius = _blanket_rear_wall_end_radius + rear_blanket_to_tf_gap - _outboard_tf_coil_end_radius = ( - _outboard_tf_coil_start_radius + outboard_tf_coil_radial_thickness - ) + _outboard_tf_coil_end_radius = _outboard_tf_coil_start_radius + outboard_tf_coil_radial_thickness _divertor_start_radius = _plasma.high_point[0] - 0.5 * divertor_radial_thickness _divertor_end_radius = _plasma.high_point[0] + 0.5 * divertor_radial_thickness @@ -517,8 +511,6 @@ def _make_tf_coils(): _support_start_radius = _plasma.high_point[0] - 0.5 * support_radial_thickness _support_end_radius = _plasma.high_point[0] + 0.5 * support_radial_thickness - - # this is the vertical build sequence, componets build on each other in # a similar manner to the radial build @@ -526,9 +518,7 @@ def _make_tf_coils(): _plasma_end_height = _plasma.high_point[1] _plasma_to_divertor_gap_start_height = _plasma_end_height - _plasma_to_divertor_gap_end_height = ( - _plasma_to_divertor_gap_start_height + outer_plasma_gap_radial_thickness - ) + _plasma_to_divertor_gap_end_height = _plasma_to_divertor_gap_start_height + outer_plasma_gap_radial_thickness # the firstwall is cut by the divertor but uses the same control points _firstwall_start_height = _plasma_to_divertor_gap_end_height @@ -538,15 +528,12 @@ def _make_tf_coils(): _blanket_end_height = _blanket_start_height + outboard_blanket_radial_thickness _blanket_rear_wall_start_height = _blanket_end_height - _blanket_rear_wall_end_height = ( - _blanket_rear_wall_start_height + blanket_rear_wall_radial_thickness - ) + _blanket_rear_wall_end_height = _blanket_rear_wall_start_height + blanket_rear_wall_radial_thickness if _tf_info_provided: _outboard_tf_coils_vertical_height = _blanket_rear_wall_end_height * 1.5 _outboard_tf_coils_horizontal_length = _blanket_rear_wall_end_radius * 0.75 - uncut_shapes.append(_make_center_column_shield()) uncut_shapes.append(_make_firstwall()) uncut_shapes.append(_make_blanket()) @@ -566,4 +553,3 @@ def _make_tf_coils(): shapes_and_components = pf_coils + uncut_shapes shapes_and_components = shapes_and_components -