cad-to-dagmc 0.3.1__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cad-to-dagmc might be problematic. Click here for more details.
- _version.py +2 -2
- cad_to_dagmc/brep_part_finder.py +17 -309
- cad_to_dagmc/brep_to_h5m.py +5 -52
- cad_to_dagmc/core.py +68 -61
- cad_to_dagmc/vertices_to_h5m.py +2 -0
- cad_to_dagmc-0.4.0.dist-info/METADATA +114 -0
- cad_to_dagmc-0.4.0.dist-info/RECORD +11 -0
- cad_to_dagmc-0.3.1.dist-info/METADATA +0 -95
- cad_to_dagmc-0.3.1.dist-info/RECORD +0 -11
- {cad_to_dagmc-0.3.1.dist-info → cad_to_dagmc-0.4.0.dist-info}/LICENSE +0 -0
- {cad_to_dagmc-0.3.1.dist-info → cad_to_dagmc-0.4.0.dist-info}/WHEEL +0 -0
- {cad_to_dagmc-0.3.1.dist-info → cad_to_dagmc-0.4.0.dist-info}/top_level.txt +0 -0
_version.py
CHANGED
cad_to_dagmc/brep_part_finder.py
CHANGED
|
@@ -1,39 +1,6 @@
|
|
|
1
|
-
from turtle import shape
|
|
2
|
-
import warnings
|
|
3
|
-
from collections.abc import Iterable
|
|
4
|
-
from typing import Tuple, Union
|
|
5
|
-
from os import PathLike
|
|
6
|
-
import numpy as np
|
|
7
|
-
from cadquery import *
|
|
8
|
-
from cadquery.occ_impl.shapes import Shape
|
|
9
1
|
import cadquery as cq
|
|
10
2
|
|
|
11
3
|
|
|
12
|
-
def get_part_properties_from_shape(shape: Shape) -> dict:
|
|
13
|
-
"""Accepts a cadquery solid object and returns the unique
|
|
14
|
-
identify details of the solid
|
|
15
|
-
|
|
16
|
-
Args:
|
|
17
|
-
filename: the filename of the brep file
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
part_details = {}
|
|
21
|
-
part_details["center_x"] = shape.Center().x
|
|
22
|
-
part_details["center_y"] = shape.Center().y
|
|
23
|
-
part_details["center_z"] = shape.Center().z
|
|
24
|
-
|
|
25
|
-
part_details["volume"] = shape.Volume()
|
|
26
|
-
|
|
27
|
-
part_details["bounding_box_xmin"] = shape.BoundingBox().xmin
|
|
28
|
-
part_details["bounding_box_ymin"] = shape.BoundingBox().ymin
|
|
29
|
-
part_details["bounding_box_zmin"] = shape.BoundingBox().zmin
|
|
30
|
-
part_details["bounding_box_xmax"] = shape.BoundingBox().xmax
|
|
31
|
-
part_details["bounding_box_ymax"] = shape.BoundingBox().ymax
|
|
32
|
-
part_details["bounding_box_zmax"] = shape.BoundingBox().zmax
|
|
33
|
-
|
|
34
|
-
return part_details
|
|
35
|
-
|
|
36
|
-
|
|
37
4
|
def convert_shape_to_iterable_of_shapes(shapes):
|
|
38
5
|
if isinstance(shapes, cq.occ_impl.shapes.Compound):
|
|
39
6
|
# brep route
|
|
@@ -47,283 +14,24 @@ def convert_shape_to_iterable_of_shapes(shapes):
|
|
|
47
14
|
return iterable_solids
|
|
48
15
|
|
|
49
16
|
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
filename: the filename of the brep file
|
|
56
|
-
"""
|
|
57
|
-
|
|
58
|
-
if not isinstance(shapes, Iterable):
|
|
59
|
-
iterable_of_shapes = convert_shape_to_iterable_of_shapes(shapes)
|
|
60
|
-
else:
|
|
61
|
-
# if a list of workplanes or other shapes is passed (e.g paramak) then
|
|
62
|
-
# we iterate through the list and convert to solids that have the
|
|
63
|
-
# expected properties (e.g. .Center.x)
|
|
64
|
-
iterable_of_shapes = []
|
|
65
|
-
for shape in shapes:
|
|
66
|
-
more_shapes = convert_shape_to_iterable_of_shapes(shape)
|
|
67
|
-
iterable_of_shapes = iterable_of_shapes + more_shapes
|
|
68
|
-
|
|
69
|
-
all_part_details = {}
|
|
70
|
-
for counter, part in enumerate(iterable_of_shapes, 1):
|
|
71
|
-
part_details = get_part_properties_from_shape(part)
|
|
72
|
-
all_part_details[counter] = part_details
|
|
73
|
-
|
|
74
|
-
return all_part_details
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def get_part_properties_from_file(filename: Union[str, PathLike]):
|
|
78
|
-
"""Imports a Brep CAD file and returns the unique identify details of each Solid
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
filename: the filename of the brep file
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
shapes = Shape.importBrep(filename)
|
|
85
|
-
|
|
86
|
-
my_brep_part_details = get_part_properties_from_shapes(shapes)
|
|
87
|
-
|
|
88
|
-
return my_brep_part_details
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def get_matching_part_id(
|
|
92
|
-
brep_part_properties: dict,
|
|
93
|
-
center_x: float = None,
|
|
94
|
-
center_y: float = None,
|
|
95
|
-
center_z: float = None,
|
|
96
|
-
volume: float = None,
|
|
97
|
-
bounding_box_xmin: float = None,
|
|
98
|
-
bounding_box_ymin: float = None,
|
|
99
|
-
bounding_box_zmin: float = None,
|
|
100
|
-
bounding_box_xmax: float = None,
|
|
101
|
-
bounding_box_ymax: float = None,
|
|
102
|
-
bounding_box_zmax: float = None,
|
|
103
|
-
volume_atol: float = 1e-6,
|
|
104
|
-
center_atol: float = 1e-6,
|
|
105
|
-
bounding_box_atol: float = 1e-6,
|
|
106
|
-
verbose=True,
|
|
107
|
-
):
|
|
108
|
-
"""Finds the key within a dictionary of parts that matches the user
|
|
109
|
-
specified arguments for volume, center, bounding_box within the provided
|
|
110
|
-
tolerances
|
|
111
|
-
|
|
112
|
-
Arguments:
|
|
113
|
-
brep_part_properties: a dictionary with the part id number as the key
|
|
114
|
-
and a dictionary of values for the part properties. For example
|
|
115
|
-
{1: {'Center.x':0, 'Center.y':0, 'Center.z':0, 'Volume':10, ....}}
|
|
116
|
-
volume: the volume of the part to find.
|
|
117
|
-
center: a tuple of x,y,z coordinates
|
|
118
|
-
bounding_box: a tuple of two coordinates where the coordinates are the
|
|
119
|
-
lower left and upper right corners of the bounding box.
|
|
120
|
-
volume_atol: absolute tolerance acceptable on the volume comparison
|
|
121
|
-
center_atol: absolute tolerance acceptable on the center comparison
|
|
122
|
-
bounding_box_atol: absolute tolerance acceptable on the bounding box comparison
|
|
123
|
-
"""
|
|
124
|
-
|
|
125
|
-
part_ids_matching = {}
|
|
126
|
-
|
|
127
|
-
properties = [
|
|
128
|
-
center_x,
|
|
129
|
-
center_y,
|
|
130
|
-
center_z,
|
|
131
|
-
volume,
|
|
132
|
-
bounding_box_xmin,
|
|
133
|
-
bounding_box_ymin,
|
|
134
|
-
bounding_box_zmin,
|
|
135
|
-
bounding_box_xmax,
|
|
136
|
-
bounding_box_ymax,
|
|
137
|
-
bounding_box_zmax,
|
|
138
|
-
]
|
|
139
|
-
properties_names = [
|
|
140
|
-
"center_x",
|
|
141
|
-
"center_y",
|
|
142
|
-
"center_z",
|
|
143
|
-
"volume",
|
|
144
|
-
"bounding_box_xmin",
|
|
145
|
-
"bounding_box_ymin",
|
|
146
|
-
"bounding_box_zmin",
|
|
147
|
-
"bounding_box_xmax",
|
|
148
|
-
"bounding_box_ymax",
|
|
149
|
-
"bounding_box_zmax",
|
|
150
|
-
]
|
|
151
|
-
tolerances = [
|
|
152
|
-
center_atol,
|
|
153
|
-
center_atol,
|
|
154
|
-
center_atol,
|
|
155
|
-
volume_atol,
|
|
156
|
-
bounding_box_atol,
|
|
157
|
-
bounding_box_atol,
|
|
158
|
-
bounding_box_atol,
|
|
159
|
-
bounding_box_atol,
|
|
160
|
-
bounding_box_atol,
|
|
161
|
-
bounding_box_atol,
|
|
162
|
-
]
|
|
163
|
-
if verbose:
|
|
164
|
-
print(f"checking new shape against {len(brep_part_properties)} parts")
|
|
165
|
-
for i, (property, names, tolerance) in enumerate(
|
|
166
|
-
zip(properties, properties_names, tolerances)
|
|
167
|
-
):
|
|
168
|
-
if verbose:
|
|
169
|
-
print(f" checking shape against brep part {i+1}")
|
|
170
|
-
if property is not None:
|
|
171
|
-
part_ids_matching_property = []
|
|
172
|
-
for key, value in brep_part_properties.items():
|
|
173
|
-
if np.isclose(value[names], property, atol=tolerance):
|
|
174
|
-
part_ids_matching_property.append(key)
|
|
175
|
-
if len(part_ids_matching_property) == 0:
|
|
176
|
-
warnings.warn(
|
|
177
|
-
f"No parts matching the specified {names} +/- tolerances were found"
|
|
178
|
-
)
|
|
179
|
-
else:
|
|
180
|
-
part_ids_matching[names] = part_ids_matching_property
|
|
181
|
-
|
|
182
|
-
lists_of_matching_parts_separate = list(part_ids_matching.values())
|
|
183
|
-
|
|
184
|
-
if verbose:
|
|
185
|
-
if lists_of_matching_parts_separate == []:
|
|
186
|
-
warnings.warn("No single part found that matches all criteria")
|
|
187
|
-
print("search criteria are:")
|
|
188
|
-
print(" volume", volume)
|
|
189
|
-
print(" center_x", center_x)
|
|
190
|
-
print(" center_y", center_y)
|
|
191
|
-
print(" center_z", center_z)
|
|
192
|
-
print(" bounding_box_xmin", bounding_box_xmin)
|
|
193
|
-
print(" bounding_box_ymin", bounding_box_ymin)
|
|
194
|
-
print(" bounding_box_zmin", bounding_box_zmin)
|
|
195
|
-
print(" bounding_box_xmax", bounding_box_xmax)
|
|
196
|
-
print(" bounding_box_ymax", bounding_box_ymax)
|
|
197
|
-
print(" bounding_box_zmax", bounding_box_zmax)
|
|
198
|
-
print(" with tolerances")
|
|
199
|
-
print(" volume_atol", volume_atol)
|
|
200
|
-
print(" center_atol", center_atol)
|
|
201
|
-
print(" bounding_box_atol", bounding_box_atol)
|
|
202
|
-
print("\nbrep criteria are:")
|
|
203
|
-
for key, value in brep_part_properties.items():
|
|
204
|
-
print(f" {key}")
|
|
205
|
-
for key2, value2 in value.items():
|
|
206
|
-
print(f" {key2}, {value2}")
|
|
207
|
-
|
|
208
|
-
if lists_of_matching_parts_separate == []:
|
|
209
|
-
raise ValueError("No matching part found")
|
|
210
|
-
|
|
211
|
-
lists_of_matching_parts = list(
|
|
212
|
-
set.intersection(*map(set, lists_of_matching_parts_separate))
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
if verbose:
|
|
216
|
-
if len(lists_of_matching_parts) == 0:
|
|
217
|
-
warnings.warn("No single part found that matches all criteria")
|
|
218
|
-
print("search criteria are:")
|
|
219
|
-
print(" volume", volume)
|
|
220
|
-
print(" center_x", center_x)
|
|
221
|
-
print(" center_y", center_y)
|
|
222
|
-
print(" center_z", center_z)
|
|
223
|
-
print(" bounding_box_xmin", bounding_box_xmin)
|
|
224
|
-
print(" bounding_box_ymin", bounding_box_ymin)
|
|
225
|
-
print(" bounding_box_zmin", bounding_box_zmin)
|
|
226
|
-
print(" bounding_box_xmax", bounding_box_xmax)
|
|
227
|
-
print(" bounding_box_ymax", bounding_box_ymax)
|
|
228
|
-
print(" bounding_box_zmax", bounding_box_zmax)
|
|
229
|
-
print(" with tolerances")
|
|
230
|
-
print(" volume_atol", volume_atol)
|
|
231
|
-
print(" center_atol", center_atol)
|
|
232
|
-
print(" bounding_box_atol", bounding_box_atol)
|
|
233
|
-
print("\nbrep criteria are:")
|
|
234
|
-
for key, value in brep_part_properties.items():
|
|
235
|
-
print(f" {key}")
|
|
236
|
-
for key2, value2 in value.items():
|
|
237
|
-
print(f" {key2}, {value2}")
|
|
238
|
-
|
|
239
|
-
return lists_of_matching_parts
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
def get_matching_part_ids(
|
|
243
|
-
brep_part_properties: dict,
|
|
244
|
-
shape_properties: dict,
|
|
245
|
-
volume_atol: float = 1e-6,
|
|
246
|
-
center_atol: float = 1e-6,
|
|
247
|
-
bounding_box_atol: float = 1e-6,
|
|
248
|
-
verbose=True,
|
|
249
|
-
):
|
|
250
|
-
"""finds the brep id that matches the shape ids and returns a list of tuples
|
|
251
|
-
where the first tuple is the shape part id and the second tuple is the brep
|
|
252
|
-
id"""
|
|
253
|
-
|
|
254
|
-
brep_and_shape_part_id = []
|
|
255
|
-
remaining_shape_ids = []
|
|
256
|
-
for shape_id, value in shape_properties.items():
|
|
257
|
-
if isinstance(value, dict):
|
|
258
|
-
# check if value is a list of dictionaries or a dictionary
|
|
259
|
-
matching_part_id = get_matching_part_id(
|
|
260
|
-
brep_part_properties=brep_part_properties,
|
|
261
|
-
volume_atol=volume_atol,
|
|
262
|
-
center_atol=center_atol,
|
|
263
|
-
bounding_box_atol=bounding_box_atol,
|
|
264
|
-
**value,
|
|
265
|
-
)
|
|
266
|
-
# if len(matching_part_id) == 0:
|
|
267
|
-
# nothing found, recheck
|
|
268
|
-
if len(matching_part_id) > 1:
|
|
269
|
-
raise ValueError(f"multiple matching volumes were found for {shape_id}")
|
|
270
|
-
if len(matching_part_id) == 1:
|
|
271
|
-
if verbose:
|
|
272
|
-
print(
|
|
273
|
-
f" single matching pair, brep id = {matching_part_id[0]} shape id = {shape_id}"
|
|
274
|
-
)
|
|
275
|
-
brep_and_shape_part_id.append((matching_part_id[0], shape_id))
|
|
276
|
-
# print()
|
|
277
|
-
brep_part_properties.pop(matching_part_id[0])
|
|
278
|
-
# todo check that key is not already in use
|
|
279
|
-
|
|
280
|
-
else:
|
|
281
|
-
remaining_shape_ids.append(shape_id)
|
|
282
|
-
|
|
283
|
-
else:
|
|
284
|
-
msg = "shape_properties must be a dictionary of dictionaries"
|
|
285
|
-
raise ValueError(msg)
|
|
286
|
-
|
|
287
|
-
if verbose:
|
|
288
|
-
print(
|
|
289
|
-
f"remaining brep ids that were not matched = {brep_part_properties.keys()}"
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
if len(brep_part_properties.keys()) == 1:
|
|
293
|
-
if len(remaining_shape_ids) == 1:
|
|
294
|
-
value = shape_properties[remaining_shape_ids[0]]
|
|
295
|
-
|
|
296
|
-
# removing bounding box check as a last resort.
|
|
297
|
-
# The bounding box for cad is not as robust as the other checks
|
|
298
|
-
# Therefore in the case where just a single volume remains we
|
|
299
|
-
# check the volume and the center of mass but skip the bb check
|
|
300
|
-
value.pop("bounding_box_xmin")
|
|
301
|
-
value.pop("bounding_box_ymin")
|
|
302
|
-
value.pop("bounding_box_zmin")
|
|
303
|
-
value.pop("bounding_box_xmax")
|
|
304
|
-
value.pop("bounding_box_ymax")
|
|
305
|
-
value.pop("bounding_box_zmax")
|
|
306
|
-
|
|
307
|
-
matching_part_id = get_matching_part_id(
|
|
308
|
-
brep_part_properties=brep_part_properties,
|
|
309
|
-
volume_atol=volume_atol,
|
|
310
|
-
center_atol=center_atol,
|
|
311
|
-
bounding_box_atol=None,
|
|
312
|
-
**value,
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
if verbose:
|
|
316
|
-
print("matching_part_id", matching_part_id)
|
|
17
|
+
def get_ids_from_assembly(assembly):
|
|
18
|
+
ids = []
|
|
19
|
+
for obj, name, loc, _ in assembly:
|
|
20
|
+
ids.append(name)
|
|
21
|
+
return ids
|
|
317
22
|
|
|
318
|
-
remaining_brep_id = list(brep_part_properties.keys())[0]
|
|
319
|
-
remaining_shape_id = remaining_shape_ids[0]
|
|
320
23
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
24
|
+
def get_ids_from_imprinted_assembly(solid_id_dict):
|
|
25
|
+
ids = []
|
|
26
|
+
for id in list(solid_id_dict.values()):
|
|
27
|
+
print(id[0])
|
|
28
|
+
ids.append(id[0])
|
|
29
|
+
return ids
|
|
326
30
|
|
|
327
|
-
brep_and_shape_part_id = sorted(brep_and_shape_part_id, key=lambda x: x[0])
|
|
328
31
|
|
|
329
|
-
|
|
32
|
+
def order_material_ids_by_brep_order(original_ids, scrambled_id, material_tags):
|
|
33
|
+
material_tags_in_brep_order = []
|
|
34
|
+
for brep_id in scrambled_id:
|
|
35
|
+
id_of_solid_in_org = original_ids.index(brep_id)
|
|
36
|
+
material_tags_in_brep_order.append(material_tags[id_of_solid_in_org])
|
|
37
|
+
return material_tags_in_brep_order
|
cad_to_dagmc/brep_to_h5m.py
CHANGED
|
@@ -4,50 +4,8 @@ from .vertices_to_h5m import vertices_to_h5m
|
|
|
4
4
|
import typing
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def brep_to_h5m(
|
|
8
|
-
brep_filename: str,
|
|
9
|
-
material_tags: typing.Iterable[str],
|
|
10
|
-
h5m_filename: str = "dagmc.h5m",
|
|
11
|
-
min_mesh_size: float = 30,
|
|
12
|
-
max_mesh_size: float = 10,
|
|
13
|
-
mesh_algorithm: int = 1,
|
|
14
|
-
) -> str:
|
|
15
|
-
"""Converts a Brep file into a DAGMC h5m file. This makes use of Gmsh and
|
|
16
|
-
will therefore need to have Gmsh installed to work.
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
brep_filename: the filename of the Brep file to convert
|
|
20
|
-
material_tags: A list of material tags to tag the DAGMC volumes with.
|
|
21
|
-
Should be in the same order as the volumes
|
|
22
|
-
h5m_filename: the filename of the DAGMC h5m file to write
|
|
23
|
-
min_mesh_size: the minimum mesh element size to use in Gmsh. Passed
|
|
24
|
-
into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size)
|
|
25
|
-
max_mesh_size: the maximum mesh element size to use in Gmsh. Passed
|
|
26
|
-
into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
|
|
27
|
-
mesh_algorithm: The Gmsh mesh algorithm number to use. Passed into
|
|
28
|
-
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
29
|
-
Returns:
|
|
30
|
-
The filename of the h5m file produced
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
gmsh, volumes = mesh_brep(
|
|
34
|
-
brep_filename=brep_filename,
|
|
35
|
-
min_mesh_size=min_mesh_size,
|
|
36
|
-
max_mesh_size=max_mesh_size,
|
|
37
|
-
mesh_algorithm=mesh_algorithm,
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
h5m_filename = mesh_to_h5m_in_memory_method(
|
|
41
|
-
volumes=volumes,
|
|
42
|
-
material_tags=material_tags,
|
|
43
|
-
h5m_filename=h5m_filename,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
return h5m_filename
|
|
47
|
-
|
|
48
|
-
|
|
49
7
|
def mesh_brep(
|
|
50
|
-
|
|
8
|
+
brep_object: str,
|
|
51
9
|
min_mesh_size: float = 30,
|
|
52
10
|
max_mesh_size: float = 10,
|
|
53
11
|
mesh_algorithm: int = 1,
|
|
@@ -56,7 +14,7 @@ def mesh_brep(
|
|
|
56
14
|
Gmsh.
|
|
57
15
|
|
|
58
16
|
Args:
|
|
59
|
-
|
|
17
|
+
brep_object: the filename of the Brep file to convert
|
|
60
18
|
min_mesh_size: the minimum mesh element size to use in Gmsh. Passed
|
|
61
19
|
into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size)
|
|
62
20
|
max_mesh_size: the maximum mesh element size to use in Gmsh. Passed
|
|
@@ -68,14 +26,11 @@ def mesh_brep(
|
|
|
68
26
|
The gmsh object and volumes in Brep file
|
|
69
27
|
"""
|
|
70
28
|
|
|
71
|
-
if not Path(brep_filename).is_file():
|
|
72
|
-
msg = f"The specified brep ({brep_filename}) file was not found"
|
|
73
|
-
raise FileNotFoundError(msg)
|
|
74
|
-
|
|
75
29
|
gmsh.initialize()
|
|
76
30
|
gmsh.option.setNumber("General.Terminal", 1)
|
|
77
31
|
gmsh.model.add("made_with_brep_to_h5m_package")
|
|
78
|
-
volumes = gmsh.model.occ.
|
|
32
|
+
volumes = gmsh.model.occ.importShapesNativePointer(brep_object)
|
|
33
|
+
# gmsh.model.occ.importShapes(brep_object)
|
|
79
34
|
gmsh.model.occ.synchronize()
|
|
80
35
|
|
|
81
36
|
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
@@ -155,11 +110,9 @@ def mesh_to_h5m_in_memory_method(
|
|
|
155
110
|
gmsh.finalize()
|
|
156
111
|
|
|
157
112
|
# checks and fixes triangle fix_normals within vertices_to_h5m
|
|
158
|
-
vertices_to_h5m(
|
|
113
|
+
return vertices_to_h5m(
|
|
159
114
|
vertices=GroupedCoords,
|
|
160
115
|
triangles=nodes_in_each_pg,
|
|
161
116
|
material_tags=material_tags,
|
|
162
117
|
h5m_filename=h5m_filename,
|
|
163
118
|
)
|
|
164
|
-
|
|
165
|
-
return h5m_filename
|
cad_to_dagmc/core.py
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
from tempfile import mkstemp
|
|
2
|
-
|
|
3
1
|
import typing
|
|
4
2
|
from cadquery import importers
|
|
5
|
-
|
|
6
|
-
from
|
|
3
|
+
|
|
4
|
+
# from cadquery import Assembly
|
|
5
|
+
# from OCP.GCPnts import GCPnts_QuasiUniformDeflection
|
|
7
6
|
|
|
8
7
|
# from cadquery.occ_impl import shapes
|
|
9
8
|
import OCP
|
|
10
9
|
import cadquery as cq
|
|
11
|
-
from OCP.TopLoc import TopLoc_Location
|
|
12
|
-
from OCP.BRep import BRep_Tool
|
|
13
|
-
from OCP.TopAbs import TopAbs_Orientation
|
|
14
10
|
|
|
15
|
-
from .
|
|
11
|
+
# from OCP.TopLoc import TopLoc_Location
|
|
12
|
+
# from OCP.BRep import BRep_Tool
|
|
13
|
+
# from OCP.TopAbs import TopAbs_Orientation
|
|
14
|
+
|
|
15
|
+
from .brep_to_h5m import mesh_brep, mesh_to_h5m_in_memory_method
|
|
16
16
|
from .brep_part_finder import (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
get_ids_from_assembly,
|
|
18
|
+
get_ids_from_imprinted_assembly,
|
|
19
|
+
order_material_ids_by_brep_order,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
|
|
@@ -45,7 +45,7 @@ class CadToDagmc:
|
|
|
45
45
|
Useful when converting the geometry to cm for use in neutronics
|
|
46
46
|
simulations.
|
|
47
47
|
"""
|
|
48
|
-
|
|
48
|
+
print(f"loading stp file {filename}")
|
|
49
49
|
part = importers.importStep(str(filename)).val()
|
|
50
50
|
|
|
51
51
|
if scale_factor == 1:
|
|
@@ -94,71 +94,78 @@ class CadToDagmc:
|
|
|
94
94
|
filename: str = "dagmc.h5m",
|
|
95
95
|
min_mesh_size: float = 1,
|
|
96
96
|
max_mesh_size: float = 10,
|
|
97
|
-
|
|
98
|
-
volume_atol: float = 0.000001,
|
|
99
|
-
center_atol: float = 0.000001,
|
|
100
|
-
bounding_box_atol: float = 0.000001,
|
|
97
|
+
mesh_algorithm: int = 1,
|
|
101
98
|
):
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
99
|
+
assembly = cq.Assembly()
|
|
100
|
+
for part in self.parts:
|
|
101
|
+
assembly.add(part)
|
|
102
|
+
|
|
103
|
+
(
|
|
104
|
+
imprinted_assembly,
|
|
105
|
+
imprinted_solids_with_original_id,
|
|
106
|
+
) = cq.occ_impl.assembly.imprint(assembly)
|
|
107
|
+
|
|
108
|
+
original_ids = get_ids_from_assembly(assembly)
|
|
109
|
+
scrambled_ids = get_ids_from_imprinted_assembly(
|
|
110
|
+
imprinted_solids_with_original_id
|
|
111
|
+
)
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
# both id lists should be the same length as each other and the same
|
|
114
|
+
# length as the self.material_tags
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
shape_properties=shape_properties,
|
|
117
|
-
volume_atol=volume_atol,
|
|
118
|
-
center_atol=center_atol,
|
|
119
|
-
bounding_box_atol=bounding_box_atol,
|
|
116
|
+
material_tags_in_brep_order = order_material_ids_by_brep_order(
|
|
117
|
+
original_ids, scrambled_ids, self.material_tags
|
|
120
118
|
)
|
|
121
119
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
gmsh, volumes = mesh_brep(
|
|
121
|
+
brep_object=imprinted_assembly.wrapped._address(),
|
|
122
|
+
min_mesh_size=min_mesh_size,
|
|
123
|
+
max_mesh_size=max_mesh_size,
|
|
124
|
+
mesh_algorithm=mesh_algorithm,
|
|
125
|
+
)
|
|
125
126
|
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
h5m_filename = mesh_to_h5m_in_memory_method(
|
|
128
|
+
volumes=volumes,
|
|
128
129
|
material_tags=material_tags_in_brep_order,
|
|
129
130
|
h5m_filename=filename,
|
|
130
|
-
min_mesh_size=min_mesh_size,
|
|
131
|
-
max_mesh_size=max_mesh_size,
|
|
132
131
|
)
|
|
132
|
+
return h5m_filename
|
|
133
133
|
|
|
134
|
-
def _merge_surfaces(self):
|
|
135
|
-
"""Merges surfaces in the geometry that are the same. More details on
|
|
136
|
-
the merging process in the DAGMC docs
|
|
137
|
-
https://svalinn.github.io/DAGMC/usersguide/cubit_basics.html"""
|
|
138
134
|
|
|
139
|
-
|
|
135
|
+
def merge_surfaces(parts):
|
|
136
|
+
"""Merges surfaces in the geometry that are the same. More details on
|
|
137
|
+
the merging process in the DAGMC docs
|
|
138
|
+
https://svalinn.github.io/DAGMC/usersguide/cubit_basics.html"""
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
# solids = geometry.Solids()
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
# merged_solid = cq.Compound(solids)
|
|
145
|
-
return self.parts[0]
|
|
142
|
+
bldr = OCP.BOPAlgo.BOPAlgo_Splitter()
|
|
146
143
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
144
|
+
if len(parts) == 1:
|
|
145
|
+
# merged_solid = cq.Compound(solids)
|
|
146
|
+
|
|
147
|
+
if isinstance(
|
|
148
|
+
parts[0], (cq.occ_impl.shapes.Compound, cq.occ_impl.shapes.Solid)
|
|
149
|
+
):
|
|
150
|
+
# stp file
|
|
151
|
+
return parts[0], parts[0].wrapped
|
|
152
|
+
else:
|
|
153
|
+
return parts[0], parts[0].toOCC()
|
|
154
|
+
|
|
155
|
+
# else:
|
|
156
|
+
for solid in parts:
|
|
157
|
+
# checks if solid is a compound as .val() is not needed for compounds
|
|
158
|
+
if isinstance(solid, (cq.occ_impl.shapes.Compound, cq.occ_impl.shapes.Solid)):
|
|
159
|
+
bldr.AddArgument(solid.wrapped)
|
|
160
|
+
else:
|
|
161
|
+
bldr.AddArgument(solid.val().wrapped)
|
|
155
162
|
|
|
156
|
-
|
|
163
|
+
bldr.SetNonDestructive(True)
|
|
157
164
|
|
|
158
|
-
|
|
165
|
+
bldr.Perform()
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
bldr.Images()
|
|
161
168
|
|
|
162
|
-
|
|
169
|
+
merged_solid = cq.Compound(bldr.Shape())
|
|
163
170
|
|
|
164
|
-
|
|
171
|
+
return merged_solid, merged_solid.wrapped
|
cad_to_dagmc/vertices_to_h5m.py
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cad-to-dagmc
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Converts CAD files to a DAGMC h5m file
|
|
5
|
+
Author-email: Jonathan Shimwell <mail@jshimwell.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/fusion-energy/cad_to_dagmc
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/fusion-energy/cad_to_dagmc/issues
|
|
8
|
+
Keywords: dagmc,geometry,plot,slice
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: trimesh
|
|
16
|
+
Requires-Dist: networkx
|
|
17
|
+
Provides-Extra: tests
|
|
18
|
+
Requires-Dist: pytest ; extra == 'tests'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
[](https://www.python.org)
|
|
22
|
+
|
|
23
|
+
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/ci_with_install.yml)
|
|
24
|
+
|
|
25
|
+
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/python-publish.yml)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
[](https://pypi.org/project/cad_to_dagmc/)
|
|
29
|
+
|
|
30
|
+
___
|
|
31
|
+
|
|
32
|
+
A minimal package that uses CadQuery functionality to convert Cad geometry to [DAGMC](https://github.com/svalinn/DAGMC/) h5m files
|
|
33
|
+
|
|
34
|
+
This particular method of producing DAGMC compatible h5m files from CAD geometry
|
|
35
|
+
is intended to convert STP files or [CadQuery](https://cadquery.readthedocs.io) objects to h5m file.
|
|
36
|
+
|
|
37
|
+
One unique feature of this package is the ability to combine STP files with CadQuery objects.
|
|
38
|
+
This allows for the addition of parametric geometry to static geometry.
|
|
39
|
+
|
|
40
|
+
# Installation
|
|
41
|
+
|
|
42
|
+
In principle, any Conda distribution will work.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Install using Conda and pip
|
|
46
|
+
|
|
47
|
+
This example uses Conda to install some dependencies that are not available via PyPi.
|
|
48
|
+
|
|
49
|
+
Create a new conda environment
|
|
50
|
+
```bash
|
|
51
|
+
conda create --name new_env python=3.9 -y
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Activate the environment
|
|
55
|
+
```bash
|
|
56
|
+
conda activate new_env
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Install the dependencies
|
|
60
|
+
```bash
|
|
61
|
+
conda install -c conda-forge moab multimethod typish ezdxf nptyping nlopt casadi gmsh python-gmsh ocp>=7.7.1 -y
|
|
62
|
+
conda install -c cadquery -c conda-forge cadquery=master --no-deps -y
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then you can install the cad_to_dagmc package with ```pip```
|
|
66
|
+
```bash
|
|
67
|
+
pip install cad_to_dagmc
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
You may also want to install OpenMC with DAGMC to make use of the h5m geometry files produced in simulations. However you could also use other supported particle transport codes such as MCNP, FLUKA and others [link to DAGMC documentation](https://svalinn.github.io/DAGMC/).You can run ```conda install -c conda-forge openmc``` however this more specific command makes sure the latest version of OpenMC which contains DAGMC is chosen by conda / mamba
|
|
71
|
+
```bash
|
|
72
|
+
conda install -c conda-forge -y "openmc=0.13.3=dagmc*nompi*"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Install using Mamba and pip
|
|
77
|
+
|
|
78
|
+
This example uses Mamba to install some dependencies that are not available via PyPi.
|
|
79
|
+
|
|
80
|
+
Create a new conda environment, I've chosen Python 3.9 here but new versions are
|
|
81
|
+
also supported.
|
|
82
|
+
```bash
|
|
83
|
+
conda create --name new_env python=3.9 -y
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Activate the environment
|
|
87
|
+
```bash
|
|
88
|
+
mamba activate new_env
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Install the dependencies
|
|
92
|
+
```bash
|
|
93
|
+
conda install -c conda-forge mamba -y
|
|
94
|
+
mamba install -c conda-forge moab multimethod typish ezdxf nptyping nlopt casadi gmsh python-gmsh ocp>=7.7.1 -y
|
|
95
|
+
mamba install -c cadquery -c conda-forge cadquery=master --no-deps -y
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then you can install the cad_to_dagmc package with ```pip```
|
|
99
|
+
```bash
|
|
100
|
+
pip install cad_to_dagmc
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
You may also want to install OpenMC with DAGMC to make use of the h5m geometry files produced in simulations. However you could also use other supported particle transport codes such as MCNP, FLUKA and others [link to DAGMC documentation](https://svalinn.github.io/DAGMC/).You can run ```conda install -c conda-forge openmc``` however this more specific command makes sure the latest version of OpenMC which contains DAGMC is chosen by conda / mamba
|
|
104
|
+
```bash
|
|
105
|
+
mamba install -c conda-forge -y "openmc=0.13.3=dagmc*nompi*"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
# Usage - creation of DAGMC h5m files
|
|
109
|
+
|
|
110
|
+
For examples see the [examples folder](https://github.com/fusion-energy/cad_to_dagmc/tree/main/examples)
|
|
111
|
+
|
|
112
|
+
# Usage - simulation with transport code
|
|
113
|
+
|
|
114
|
+
For examples see the CAD tasks in the [neutronics-workshop](https://github.com/fusion-energy/neutronics-workshop)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
_version.py,sha256=QiCQVGOicQZY3DBr4tYPU9egzT1VgzOJGfLt9Q26uyU,160
|
|
2
|
+
cad_to_dagmc/__init__.py,sha256=PgkpCP8unzhcoyvw-lKpy5HLy2bnUNmFHS508_bsCCE,593
|
|
3
|
+
cad_to_dagmc/brep_part_finder.py,sha256=by2wnjo_KrTZaihFP5m5Z_sZJSdtEef7GS4nvpwqNrc,1020
|
|
4
|
+
cad_to_dagmc/brep_to_h5m.py,sha256=4w7xaO0uJU5c8PoQFtDoPUyzWart7pdSpynU1Rcv7xY,4107
|
|
5
|
+
cad_to_dagmc/core.py,sha256=XNXmEn06VellMwEqTXiCKRLVPN7NRDG3X0OQZXM2cOE,5594
|
|
6
|
+
cad_to_dagmc/vertices_to_h5m.py,sha256=h7KI2fofhBlyTMRdb0FXUO12SxW9MtnNEgwdCyNCPmk,5997
|
|
7
|
+
cad_to_dagmc-0.4.0.dist-info/LICENSE,sha256=B8kznH_777JVNZ3HOKDc4Tj24F7wJ68ledaNYeL9sCw,1070
|
|
8
|
+
cad_to_dagmc-0.4.0.dist-info/METADATA,sha256=9iMhi-El25ZzKZL1sKTQqwDQO5t2zd-8DEA5-acacgA,4545
|
|
9
|
+
cad_to_dagmc-0.4.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
10
|
+
cad_to_dagmc-0.4.0.dist-info/top_level.txt,sha256=zTi8C64SEBsE5WOtPovnxhOzt-E6Oc5nC3RW6M_5aEA,22
|
|
11
|
+
cad_to_dagmc-0.4.0.dist-info/RECORD,,
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: cad-to-dagmc
|
|
3
|
-
Version: 0.3.1
|
|
4
|
-
Summary: Converts CAD files to a DAGMC h5m file
|
|
5
|
-
Author-email: Jonathan Shimwell <mail@jshimwell.com>
|
|
6
|
-
Project-URL: Homepage, https://github.com/fusion-energy/cad_to_dagmc
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/fusion-energy/cad_to_dagmc/issues
|
|
8
|
-
Keywords: dagmc,geometry,plot,slice
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
12
|
-
Requires-Python: >=3.8
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
License-File: LICENSE
|
|
15
|
-
Requires-Dist: cadquery (>=2.2.0)
|
|
16
|
-
Requires-Dist: trimesh
|
|
17
|
-
Requires-Dist: networkx
|
|
18
|
-
Provides-Extra: tests
|
|
19
|
-
Requires-Dist: pytest ; extra == 'tests'
|
|
20
|
-
Requires-Dist: openmc-data-downloader ; extra == 'tests'
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
[](https://www.python.org)
|
|
24
|
-
|
|
25
|
-
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/ci_with_install.yml)
|
|
26
|
-
|
|
27
|
-
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/python-publish.yml)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
[](https://anaconda.org/fusion-energy/cad_to_dagmc)
|
|
31
|
-
[](https://pypi.org/project/cad_to_dagmc/)
|
|
32
|
-
|
|
33
|
-
___
|
|
34
|
-
|
|
35
|
-
A minimal package that uses CadQuery functionality to convert Cad geometry to DAGMC h5m files
|
|
36
|
-
|
|
37
|
-
This particular method of producing DAGMC compatible h5m files from CAD geometry
|
|
38
|
-
is intended to convert STP files or [CadQuery](https://cadquery.readthedocs.io) objects to h5m file.
|
|
39
|
-
|
|
40
|
-
One unique feature of this package is the ability to combine STP files with CadQuery objects.
|
|
41
|
-
This allows for the addition of parametric geometry to static geometry.
|
|
42
|
-
|
|
43
|
-
# Install (Conda)
|
|
44
|
-
|
|
45
|
-
Creates a new empty Conda environment and activate it
|
|
46
|
-
```bash
|
|
47
|
-
conda create --name new_env python=3.9
|
|
48
|
-
conda activate new_env
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Installs cad_to_dagmc and dependencies
|
|
52
|
-
```bash
|
|
53
|
-
conda install -c fusion-energy -c cadquery -c conda-forge cad_to_dagmc
|
|
54
|
-
```
|
|
55
|
-
# Install (Mamba)
|
|
56
|
-
|
|
57
|
-
Creates a new empty Conda environment and activate it
|
|
58
|
-
```bash
|
|
59
|
-
conda create --name new_env python=3.9
|
|
60
|
-
conda activate new_env
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Installs Mamba
|
|
64
|
-
```bash
|
|
65
|
-
conda install -c conda-forge mamba
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Installs cad_to_dagmc and dependencies
|
|
69
|
-
```bash
|
|
70
|
-
mamba install -c fusion-energy -c cadquery -c conda-forge cad_to_dagmc
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
# Install (Conda + pip)
|
|
74
|
-
|
|
75
|
-
You will need to install some dependencies that are not available via PyPi.
|
|
76
|
-
This example uses Conda but Mamba could also be used.
|
|
77
|
-
```bash
|
|
78
|
-
conda install -c conda-forge moab
|
|
79
|
-
conda install -c conda-forge gmsh
|
|
80
|
-
conda install -c conda-forge python-gmsh
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Then you can install the cad_to_dagmc package with ```pip```
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
pip install cad_to_dagmc
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
# Usage
|
|
90
|
-
|
|
91
|
-
To use the h5m geometry you will need a transport code with DAGMC enabled such as OpenMC.
|
|
92
|
-
Just to note that currently the conda install for CadQuery and OpenMC can't be installed in the same conda environment.
|
|
93
|
-
A work around for this is to create the h5m geometry in one conda environment and simulate with OpenMC in another conda environment.
|
|
94
|
-
|
|
95
|
-
For examples see the [examples folder](https://github.com/fusion-energy/cad_to_dagmc/tree/main/examples)
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
_version.py,sha256=NpX2iZJQYVxuIsKBfyjQghJWMvGYxwOlfWJ3M_xOU7s,160
|
|
2
|
-
cad_to_dagmc/__init__.py,sha256=PgkpCP8unzhcoyvw-lKpy5HLy2bnUNmFHS508_bsCCE,593
|
|
3
|
-
cad_to_dagmc/brep_part_finder.py,sha256=XNxCbVqlnDokFmUpFaCd_Zi_DoG9XxF0jVezv4MrGUE,11973
|
|
4
|
-
cad_to_dagmc/brep_to_h5m.py,sha256=0m-TLfRldc3p60f96-0J9WeOaa-z3ba4acZJ4KgKvmw,5730
|
|
5
|
-
cad_to_dagmc/core.py,sha256=oj9Ol3-Y7tzC4No2FqelPCH8PzKYKVAbkMoO7f1Ot-w,5547
|
|
6
|
-
cad_to_dagmc/vertices_to_h5m.py,sha256=gJImjUvHzCWe0tHckHs4BRa4kbaVM2aYWDZGRgzPQng,5972
|
|
7
|
-
cad_to_dagmc-0.3.1.dist-info/LICENSE,sha256=B8kznH_777JVNZ3HOKDc4Tj24F7wJ68ledaNYeL9sCw,1070
|
|
8
|
-
cad_to_dagmc-0.3.1.dist-info/METADATA,sha256=XIopZBD9DVbP44VAdxeeOgGZNKQQ3Xa--w2Tml9rUb8,3485
|
|
9
|
-
cad_to_dagmc-0.3.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
10
|
-
cad_to_dagmc-0.3.1.dist-info/top_level.txt,sha256=zTi8C64SEBsE5WOtPovnxhOzt-E6Oc5nC3RW6M_5aEA,22
|
|
11
|
-
cad_to_dagmc-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|