Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added new method of performing ordered boolean operations #770

Open
wants to merge 29 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b7080ea
added new method of performing ordered boolean operations
billingsley-john Mar 8, 2021
c28fae5
Automated autopep8 fixes
Mar 8, 2021
9234dd4
updated tests to use new boolean operation method
billingsley-john Mar 8, 2021
9c63210
Merge branch 'update_boolean_operations' of https://github.com/ukaea/…
billingsley-john Mar 8, 2021
03cf4ec
Automated autopep8 fixes
Mar 8, 2021
ecb7e9b
updated boolean operations
billingsley-john Mar 8, 2021
8889057
Merge branch 'update_boolean_operations' of https://github.com/ukaea/…
billingsley-john Mar 8, 2021
9aa350b
Automated autopep8 fixes
Mar 8, 2021
95c2be3
fix syntax error
billingsley-john Mar 8, 2021
c9efa10
Merge branch 'update_boolean_operations' of https://github.com/ukaea/…
billingsley-john Mar 8, 2021
3cdcbff
Automated autopep8 fixes
Mar 8, 2021
fb61e62
updated tests to use new boolean operations method
billingsley-john Mar 8, 2021
8eb8013
Merge branch 'update_boolean_operations' of https://github.com/ukaea/…
billingsley-john Mar 8, 2021
066fd18
Automated autopep8 fixes
Mar 8, 2021
58db06a
fixed syntax error
billingsley-john Mar 8, 2021
84ac4fc
Merge branch 'update_boolean_operations' of https://github.com/ukaea/…
billingsley-john Mar 8, 2021
03abc55
fixed typos
billingsley-john Mar 9, 2021
f192e20
updated boolean operations
billingsley-john Mar 9, 2021
c5d89d7
updated appending to cut
billingsley-john Mar 9, 2021
042e30f
Automated autopep8 fixes
Mar 9, 2021
0415230
fixed typo and tidied up if else
billingsley-john Mar 9, 2021
02d62b2
fixed merge conflict
billingsley-john Mar 9, 2021
59da389
Automated autopep8 fixes
Mar 9, 2021
5930dc5
updated if else
billingsley-john Mar 9, 2021
a79a505
fixed merge conflict
billingsley-john Mar 9, 2021
e8f6e01
Automated autopep8 fixes
Mar 9, 2021
45c4303
fixed typo
billingsley-john Mar 9, 2021
8c1d734
using new boolean opeartions syntax
billingsley-john Mar 9, 2021
5ba6869
fixed typo
billingsley-john Mar 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions paramak/parametric_components/blanket_poloidal_segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def create_segment_cutters(self):
cutting_shape = RotateStraightShape(
rotation_angle=self.rotation_angle,
azimuth_placement_angle=self.azimuth_placement_angle,
union=[])
boolean_operations={"union": []})
# add points to the shape to avoid void solid
cutting_shape.points = [
(self.major_radius,
Expand Down Expand Up @@ -188,7 +188,7 @@ def create_segment_cutters(self):
angle=np.pi / 2)]
cutter.points = points_cutter
# add cutter to global cutting shape
cutting_shape.union.append(cutter)
cutting_shape.boolean_operations["union"].append(cutter)

self.segments_cutters = cutting_shape

Expand Down
24 changes: 18 additions & 6 deletions paramak/parametric_components/inboard_firstwall_fccs.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,22 @@ def find_points(self):
points = firstwall.points[:-1] # remove last point
self.points = points

# add to cut attribute
if self.cut is None:
self.cut = self.central_column_shield
elif isinstance(self.cut, Iterable):
self.cut = [*self.cut, self.central_column_shield]
if self.boolean_operations is None:
self.boolean_operations = {"cut": self.central_column_shield}
elif "cut" not in self.boolean_operations:
self.boolean_operations["cut"] = self.central_column_shield
elif isinstance(self.boolean_operations["cut"], Iterable):
self.boolean_operations["cut"] = [
*self.boolean_operations["cut"],
self.central_column_shield]
else:
self.cut = [*[self.cut], self.central_column_shield]
self.boolean_operations["cut"] = [
*[self.boolean_operations["cut"]], self.central_column_shield]

# add to cut attribute
# if self.cut is None:
# self.cut = self.central_column_shield
# elif isinstance(self.cut, Iterable):
# self.cut = [*self.cut, self.central_column_shield]
# else:
# self.cut = [*[self.cut], self.central_column_shield]
11 changes: 6 additions & 5 deletions paramak/parametric_reactors/ball_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def _make_blankets_layers(self):
material_tag="firstwall_mat",
stp_filename="firstwall.stp",
stl_filename="firstwall.stl",
cut=[self._center_column_cutter]
boolean_operations={"cut": [self._center_column_cutter]}
)

self._blanket = paramak.BlanketFP(
Expand All @@ -406,7 +406,8 @@ def _make_blankets_layers(self):
material_tag="blanket_mat",
stp_filename="blanket.stp",
stl_filename="blanket.stl",
cut=[self._center_column_cutter])
boolean_operations={"cut": [self._center_column_cutter]}
)

self._blanket_rear_wall = paramak.BlanketFP(
plasma=self._plasma,
Expand All @@ -420,7 +421,7 @@ def _make_blankets_layers(self):
material_tag="blanket_rear_wall_mat",
stp_filename="blanket_rear_wall.stp",
stl_filename="blanket_rear_wall.stl",
cut=[self._center_column_cutter],
boolean_operations={"cut": [self._center_column_cutter]}
)

return [self._firstwall, self._blanket, self._blanket_rear_wall]
Expand Down Expand Up @@ -454,7 +455,7 @@ def _make_divertor(self):
(self._divertor_end_radius, divertor_height_top),
(self._divertor_start_radius, divertor_height_top)
],
intersect=self._blanket_fw_rear_wall_envelope,
boolean_operations={"intersect": self._blanket_fw_rear_wall_envelope},
stp_filename="divertor.stp",
stl_filename="divertor.stl",
name="divertor",
Expand All @@ -466,7 +467,7 @@ def _make_divertor(self):
self._firstwall,
self._blanket,
self._blanket_rear_wall]:
component.cut.append(self._divertor)
component.boolean_operations["cut"].append(self._divertor)

return self._divertor

Expand Down
10 changes: 5 additions & 5 deletions paramak/parametric_reactors/center_column_study_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,12 @@ def _make_outboard_blanket(self):
start_angle=-180,
stop_angle=180,
rotation_angle=self.rotation_angle,
cut=[self._center_column_cutter]
boolean_operations={"cut": [self._center_column_cutter]}
)
return self._blanket

def _make_divertor(self):
self._blanket_enveloppe = paramak.BlanketFP(
self._blanket_envelope = paramak.BlanketFP(
plasma=self._plasma,
thickness=100.,
offset_from_plasma=[
Expand All @@ -285,7 +285,7 @@ def _make_divertor(self):
start_angle=-180,
stop_angle=180,
rotation_angle=self.rotation_angle,
cut=[self._center_column_cutter]
boolean_operations={"cut": [self._center_column_cutter]}
)

self._divertor = paramak.CenterColumnShieldCylinder(
Expand All @@ -298,7 +298,7 @@ def _make_divertor(self):
stl_filename="divertor.stl",
name="divertor",
material_tag="divertor_mat",
intersect=self._blanket_enveloppe,
boolean_operations={"intersect": self._blanket_envelope}
)
self._blanket.cut.append(self._divertor)
self._blanket.boolean_operations["cut"].append(self._divertor)
return self._divertor
6 changes: 3 additions & 3 deletions paramak/parametric_reactors/eu_demo_2015_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def create_tf_coils(self, vac_vessel_inner, vac_vessel) -> list:
(375.4508992805756, 755, "straight"),
],
distance=200,
cut=[vac_vessel_inner, vac_vessel],
boolean_operations={"cut": [vac_vessel_inner, vac_vessel]},
# azimuth placement angle can't start at
# zero nor end at 360 until #757 is solved
azimuth_placement_angle=np.linspace(
Expand Down Expand Up @@ -220,7 +220,7 @@ def create_vessel_components(self) -> list:
],
rotation_angle=self.rotation_angle,
# avoid overlap between VV and blanket divertor
union=[blanket, divertor]
boolean_operations={"union": [blanket, divertor]}
)
vac_vessel = paramak.RotateSplineShape(
points=[
Expand Down Expand Up @@ -276,7 +276,7 @@ def create_vessel_components(self) -> list:
(516.7486775621876, -175.64585325476332),
(516.7486775621876, -107.40944903301386),
],
cut=vac_vessel_inner, # hollow shape
boolean_operations={"cut": vac_vessel_inner},
rotation_angle=self.rotation_angle,
stp_filename='vacvessel.stp',
stl_filename='vacvessel.stl',
Expand Down
7 changes: 4 additions & 3 deletions paramak/parametric_reactors/segmented_blanket_ball_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ def _make_blankets_layers(self):
2 * self.firstwall_radial_thickness,
azimuth_placement_angle=azimuth_placement_angles)

self._blanket.cut = [self._center_column_cutter, thick_cutter]
self._blanket.boolean_operations = {
"cut": [self._center_column_cutter, thick_cutter]}

if self.blanket_fillet_radius != 0:
# tried firstwall start radius here already
Expand All @@ -90,10 +91,10 @@ def _make_blankets_layers(self):
paramak.EdgeLengthSelector(front_edge_length_b)).fillet(
self.blanket_fillet_radius)
self._firstwall.thickness += self.blanket_radial_thickness
self._firstwall.cut = [
self._firstwall.boolean_operations = {"cut": [
self._center_column_cutter,
thin_cutter,
self._blanket]
self._blanket]}

# TODO this segfaults at the moment but works as an opperation on the
# reactor after construction in jupyter
Expand Down
2 changes: 1 addition & 1 deletion paramak/parametric_reactors/sparc_paper_2020.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def create_vessel_components(self, vs_coils):
],
rotation_angle=self.rotation_angle,
stp_filename='inner_vessel.stp',
cut=[vac_vessel, vs_coils, antenna]
boolean_operations={"cut": [vac_vessel, vs_coils, antenna]}
)

return [antenna, vac_vessel, inner_vessel]
Expand Down
25 changes: 13 additions & 12 deletions paramak/parametric_reactors/submersion_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ def _make_firstwall(self):
stl_filename="outboard_firstwall.stl",
name="outboard_firstwall",
material_tag="firstwall_mat",
union=self._inboard_firstwall,
boolean_operations={"union": self._inboard_firstwall}
)
return self._firstwall

Expand All @@ -469,7 +469,7 @@ def _make_divertor(self):
stl_filename="outboard_firstwall.stl",
name="outboard_firstwall",
material_tag="firstwall_mat",
union=fw_enveloppe_inboard,
boolean_operations={"union": fw_enveloppe_inboard}
)
divertor_height = self._blanket_rear_wall_end_height

Expand All @@ -488,16 +488,16 @@ def _make_divertor(self):
(self._divertor_end_radius, divertor_height_top),
(self._divertor_start_radius, divertor_height_top)
],
intersect=fw_enveloppe,
boolean_operations={"intersect": fw_enveloppe},
rotation_angle=self.rotation_angle,
stp_filename="divertor.stp",
stl_filename="divertor.stl",
name="divertor",
material_tag="divertor_mat"
)

self._firstwall.cut = self._divertor
self._inboard_firstwall.cut = self._divertor
self._firstwall.boolean_operations["cut"] = self._divertor
self._inboard_firstwall.boolean_operations = {"cut": self._divertor}
return self._divertor

def _make_blanket(self):
Expand All @@ -506,7 +506,7 @@ def _make_blanket(self):
inner_radius=self._inboard_blanket_start_radius,
outer_radius=max(self._inboard_firstwall.points)[0],
rotation_angle=self.rotation_angle,
cut=self._inboard_firstwall,
boolean_operations={"cut": self._inboard_firstwall}
)

# this takes a single solid from a compound of solids by finding the
Expand All @@ -529,7 +529,7 @@ def _make_blanket(self):
stl_filename="blanket.stl",
name="blanket",
material_tag="blanket_mat",
union=self._inboard_blanket,
boolean_operations={"union": self._inboard_blanket}
)
return self._blanket

Expand All @@ -542,7 +542,7 @@ def _make_supports(self):
+ self.firstwall_radial_thickness,
thickness=self.outboard_blanket_radial_thickness,
rotation_angle=self.rotation_angle,
union=self._inboard_blanket,
boolean_operations={"union": self._inboard_blanket}
)
support_height = self._blanket_rear_wall_end_height
support_height_top = support_height
Expand All @@ -565,9 +565,9 @@ def _make_supports(self):
stl_filename="supports.stl",
name="supports",
material_tag="supports_mat",
intersect=blanket_enveloppe,
boolean_operations={"intersect": blanket_enveloppe}
)
self._blanket.cut = self._supports
self._blanket.boolean_operations["cut"] = self._supports

return self._supports

Expand Down Expand Up @@ -629,9 +629,10 @@ def _make_rear_blanket_wall(self):
stl_filename="outboard_rear_blanket_wall.stl",
name="outboard_rear_blanket_wall",
material_tag="blanket_rear_wall_mat",
union=[
boolean_operations={"union": [
self._outboard_rear_blanket_wall_upper,
self._outboard_rear_blanket_wall_lower],
self._outboard_rear_blanket_wall_lower
]},
)

return self._outboard_rear_blanket_wall
Expand Down
47 changes: 16 additions & 31 deletions paramak/shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,9 @@ class Shape:
description output. Defaults to None.
physical_groups (dict, optional): contains information on physical
groups (volumes and surfaces). Defaults to None.
cut (paramak.shape or list, optional): If set, the current solid will
be cut with the provided solid or iterable in cut. Defaults to
None.
intersect (paramak.shape or list, optional): If set, the current solid
will be interested with the provided solid or iterable of solids.
Defaults to None.
union (paramak.shape or list, optional): If set, the current solid
will be united with the provided solid or iterable of solids.
Defaults to None.
boolean_operations (dict, optional): dictionary of boolean operations
(cut, union, intersect) and the associated shapes with which the
operations will be performed with. Defaults to None.
"""

def __init__(
Expand All @@ -87,9 +81,7 @@ def __init__(
surface_reflectivity: Optional[bool] = False,
physical_groups=None,
# TODO defining Shape types as paramak.Shape results in circular import
cut=None,
intersect=None,
union=None,
boolean_operations: Optional[dict] = None
):

self.connection_type = connection_type
Expand All @@ -99,9 +91,7 @@ def __init__(
self.color = color
self.name = name

self.cut = cut
self.intersect = intersect
self.union = union
self.boolean_operations = boolean_operations

self.azimuth_placement_angle = azimuth_placement_angle
self.workplane = workplane
Expand Down Expand Up @@ -1129,28 +1119,23 @@ def neutronics_description(self) -> dict:
return neutronics_description

def perform_boolean_operations(self, solid: cq.Workplane, **kwargs):
"""Performs boolean cut, intersect and union operations if shapes are
provided"""

# If a cut solid is provided then perform a boolean cut
if self.cut is not None:
solid = cut_solid(solid, self.cut)
if self.boolean_operations is not None:
for operation, shapes in self.boolean_operations.items():
if shapes is not None:
if operation == 'cut':
solid = cut_solid(solid, shapes)

if operation == 'union':
solid = union_solid(solid, shapes)

if operation == 'intersect':
solid = intersect_solid(solid, shapes)

# If a wedge cut is provided then perform a boolean cut
# Performed independantly to avoid use of self.cut
# Prevents repetition of 'outdated' wedge cuts
if 'wedge_cut' in kwargs:
if kwargs['wedge_cut'] is not None:
solid = cut_solid(solid, kwargs['wedge_cut'])

# If an intersect is provided then perform a boolean intersect
if self.intersect is not None:
solid = intersect_solid(solid, self.intersect)

# If an intersect is provided then perform a boolean intersect
if self.union is not None:
solid = union_solid(solid, self.union)

return solid

def make_graveyard(
Expand Down
4 changes: 2 additions & 2 deletions tests/test_parametric_components/test_InboardFirstwallFCCS.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def test_boolean_union(self):
thickness=20,
rotation_angle=180,
azimuth_placement_angle=180,
union=b)
boolean_operations={"union": b})
assert np.isclose(c.volume, 2 * b.volume)

def test_azimuth_placement_angle(self):
Expand All @@ -171,7 +171,7 @@ def test_azimuth_placement_angle(self):
thickness=20,
rotation_angle=180,
azimuth_placement_angle=90,
cut=b)
boolean_operations={"cut": b})
assert np.isclose(c.volume, 0.5 * b.volume)

def test_cut_attribute(self):
Expand Down
Loading