cad-to-dagmc 0.5.0__py3-none-any.whl → 0.6.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.
- _version.py +11 -3
- cad_to_dagmc/__init__.py +1 -6
- cad_to_dagmc/core.py +416 -84
- cad_to_dagmc-0.6.0.dist-info/METADATA +144 -0
- cad_to_dagmc-0.6.0.dist-info/RECORD +8 -0
- {cad_to_dagmc-0.5.0.dist-info → cad_to_dagmc-0.6.0.dist-info}/WHEEL +1 -1
- cad_to_dagmc/brep_part_finder.py +0 -36
- cad_to_dagmc/brep_to_h5m.py +0 -121
- cad_to_dagmc/vertices_to_h5m.py +0 -262
- cad_to_dagmc-0.5.0.dist-info/METADATA +0 -119
- cad_to_dagmc-0.5.0.dist-info/RECORD +0 -11
- {cad_to_dagmc-0.5.0.dist-info → cad_to_dagmc-0.6.0.dist-info}/LICENSE +0 -0
- {cad_to_dagmc-0.5.0.dist-info → cad_to_dagmc-0.6.0.dist-info}/top_level.txt +0 -0
_version.py
CHANGED
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
TYPE_CHECKING = False
|
|
4
4
|
if TYPE_CHECKING:
|
|
5
|
-
from typing import Tuple
|
|
5
|
+
from typing import Tuple, Union
|
|
6
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
|
+
else:
|
|
8
|
+
VERSION_TUPLE = object
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
version: str
|
|
11
|
+
__version__: str
|
|
12
|
+
__version_tuple__: VERSION_TUPLE
|
|
13
|
+
version_tuple: VERSION_TUPLE
|
|
14
|
+
|
|
15
|
+
__version__ = version = '0.6.0'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 6, 0)
|
cad_to_dagmc/__init__.py
CHANGED
|
@@ -13,9 +13,4 @@ except PackageNotFoundError:
|
|
|
13
13
|
|
|
14
14
|
__all__ = ["__version__"]
|
|
15
15
|
|
|
16
|
-
from .core import
|
|
17
|
-
from .vertices_to_h5m import vertices_to_h5m
|
|
18
|
-
from .brep_part_finder import *
|
|
19
|
-
from .brep_to_h5m import *
|
|
20
|
-
|
|
21
|
-
[CadToDagmc, vertices_to_h5m]
|
|
16
|
+
from .core import *
|
cad_to_dagmc/core.py
CHANGED
|
@@ -1,38 +1,325 @@
|
|
|
1
1
|
import typing
|
|
2
|
+
|
|
3
|
+
import cadquery as cq
|
|
4
|
+
import gmsh
|
|
5
|
+
import numpy as np
|
|
2
6
|
from cadquery import importers
|
|
7
|
+
from pymoab import core, types
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _define_moab_core_and_tags() -> typing.Tuple[core.Core, dict]:
|
|
11
|
+
"""Creates a MOAB Core instance which can be built up by adding sets of
|
|
12
|
+
triangles to the instance
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
(pymoab Core): A pymoab.core.Core() instance
|
|
16
|
+
(pymoab tag_handle): A pymoab.core.tag_get_handle() instance
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
# create pymoab instance
|
|
20
|
+
moab_core = core.Core()
|
|
21
|
+
|
|
22
|
+
tags = dict()
|
|
23
|
+
|
|
24
|
+
sense_tag_name = "GEOM_SENSE_2"
|
|
25
|
+
sense_tag_size = 2
|
|
26
|
+
tags["surf_sense"] = moab_core.tag_get_handle(
|
|
27
|
+
sense_tag_name,
|
|
28
|
+
sense_tag_size,
|
|
29
|
+
types.MB_TYPE_HANDLE,
|
|
30
|
+
types.MB_TAG_SPARSE,
|
|
31
|
+
create_if_missing=True,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
tags["category"] = moab_core.tag_get_handle(
|
|
35
|
+
types.CATEGORY_TAG_NAME,
|
|
36
|
+
types.CATEGORY_TAG_SIZE,
|
|
37
|
+
types.MB_TYPE_OPAQUE,
|
|
38
|
+
types.MB_TAG_SPARSE,
|
|
39
|
+
create_if_missing=True,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
tags["name"] = moab_core.tag_get_handle(
|
|
43
|
+
types.NAME_TAG_NAME,
|
|
44
|
+
types.NAME_TAG_SIZE,
|
|
45
|
+
types.MB_TYPE_OPAQUE,
|
|
46
|
+
types.MB_TAG_SPARSE,
|
|
47
|
+
create_if_missing=True,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
tags["geom_dimension"] = moab_core.tag_get_handle(
|
|
51
|
+
types.GEOM_DIMENSION_TAG_NAME,
|
|
52
|
+
1,
|
|
53
|
+
types.MB_TYPE_INTEGER,
|
|
54
|
+
types.MB_TAG_DENSE,
|
|
55
|
+
create_if_missing=True,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Global ID is a default tag, just need the name to retrieve
|
|
59
|
+
tags["global_id"] = moab_core.tag_get_handle(types.GLOBAL_ID_TAG_NAME)
|
|
60
|
+
|
|
61
|
+
return moab_core, tags
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _vertices_to_h5m(
|
|
65
|
+
vertices: typing.Union[
|
|
66
|
+
typing.Iterable[typing.Tuple[float, float, float]],
|
|
67
|
+
typing.Iterable["cadquery.occ_impl.geom.Vector"],
|
|
68
|
+
],
|
|
69
|
+
triangles_by_solid_by_face: typing.Iterable[typing.Iterable[typing.Tuple[int, int, int]]],
|
|
70
|
+
material_tags: typing.Iterable[str],
|
|
71
|
+
h5m_filename="dagmc.h5m",
|
|
72
|
+
implicit_complement_material_tag=None,
|
|
73
|
+
):
|
|
74
|
+
"""Converts vertices and triangle sets into a tagged h5m file compatible
|
|
75
|
+
with DAGMC enabled neutronics simulations
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
vertices:
|
|
79
|
+
triangles:
|
|
80
|
+
material_tags:
|
|
81
|
+
h5m_filename:
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
if len(material_tags) != len(triangles_by_solid_by_face):
|
|
85
|
+
msg = f"The number of material_tags provided is {len(material_tags)} and the number of sets of triangles is {len(triangles_by_solid_by_face)}. You must provide one material_tag for every triangle set"
|
|
86
|
+
raise ValueError(msg)
|
|
87
|
+
|
|
88
|
+
# limited attribute checking to see if user passed in a list of CadQuery vectors
|
|
89
|
+
if hasattr(vertices[0], "x") and hasattr(vertices[0], "y") and hasattr(vertices[0], "z"):
|
|
90
|
+
vertices_floats = []
|
|
91
|
+
for vert in vertices:
|
|
92
|
+
vertices_floats.append((vert.x, vert.y, vert.z))
|
|
93
|
+
else:
|
|
94
|
+
vertices_floats = vertices
|
|
95
|
+
|
|
96
|
+
face_ids_with_solid_ids = {}
|
|
97
|
+
for solid_id, triangles_on_each_face in triangles_by_solid_by_face.items():
|
|
98
|
+
for face_id, triangles_on_face in triangles_on_each_face.items():
|
|
99
|
+
if face_id in face_ids_with_solid_ids.keys():
|
|
100
|
+
face_ids_with_solid_ids[face_id].append(solid_id)
|
|
101
|
+
else:
|
|
102
|
+
face_ids_with_solid_ids[face_id] = [solid_id]
|
|
103
|
+
|
|
104
|
+
moab_core, tags = _define_moab_core_and_tags()
|
|
105
|
+
|
|
106
|
+
volume_sets_by_solid_id = {}
|
|
107
|
+
for material_tag, (solid_id, triangles_on_each_face) in zip(
|
|
108
|
+
material_tags, triangles_by_solid_by_face.items()
|
|
109
|
+
):
|
|
110
|
+
volume_set = moab_core.create_meshset()
|
|
111
|
+
volume_sets_by_solid_id[solid_id] = volume_set
|
|
3
112
|
|
|
4
|
-
|
|
5
|
-
|
|
113
|
+
added_surfaces_ids = {}
|
|
114
|
+
for material_tag, (solid_id, triangles_on_each_face) in zip(
|
|
115
|
+
material_tags, triangles_by_solid_by_face.items()
|
|
116
|
+
):
|
|
117
|
+
volume_set = volume_sets_by_solid_id[solid_id]
|
|
6
118
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
119
|
+
moab_core.tag_set_data(tags["global_id"], volume_set, solid_id)
|
|
120
|
+
moab_core.tag_set_data(tags["geom_dimension"], volume_set, 3)
|
|
121
|
+
moab_core.tag_set_data(tags["category"], volume_set, "Volume")
|
|
122
|
+
|
|
123
|
+
group_set = moab_core.create_meshset()
|
|
124
|
+
moab_core.tag_set_data(tags["category"], group_set, "Group")
|
|
125
|
+
moab_core.tag_set_data(tags["name"], group_set, f"mat:{material_tag}")
|
|
126
|
+
moab_core.tag_set_data(tags["global_id"], group_set, solid_id)
|
|
127
|
+
# moab_core.tag_set_data(tags["geom_dimension"], group_set, 4)
|
|
128
|
+
|
|
129
|
+
for face_id, triangles_on_face in triangles_on_each_face.items():
|
|
130
|
+
if face_id not in added_surfaces_ids.keys():
|
|
131
|
+
face_set = moab_core.create_meshset()
|
|
132
|
+
moab_core.tag_set_data(tags["global_id"], face_set, face_id)
|
|
133
|
+
moab_core.tag_set_data(tags["geom_dimension"], face_set, 2)
|
|
134
|
+
moab_core.tag_set_data(tags["category"], face_set, "Surface")
|
|
135
|
+
|
|
136
|
+
if len(face_ids_with_solid_ids[face_id]) == 2:
|
|
137
|
+
other_solid_id = face_ids_with_solid_ids[face_id][1]
|
|
138
|
+
other_volume_set = volume_sets_by_solid_id[other_solid_id]
|
|
139
|
+
sense_data = np.array([other_volume_set, volume_set], dtype="uint64")
|
|
140
|
+
else:
|
|
141
|
+
sense_data = np.array([volume_set, 0], dtype="uint64")
|
|
142
|
+
|
|
143
|
+
moab_core.tag_set_data(tags["surf_sense"], face_set, sense_data)
|
|
144
|
+
|
|
145
|
+
moab_verts = moab_core.create_vertices(vertices)
|
|
146
|
+
moab_core.add_entity(face_set, moab_verts)
|
|
147
|
+
|
|
148
|
+
for triangle in triangles_on_face:
|
|
149
|
+
tri = (
|
|
150
|
+
moab_verts[int(triangle[0])],
|
|
151
|
+
moab_verts[int(triangle[1])],
|
|
152
|
+
moab_verts[int(triangle[2])],
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
moab_triangle = moab_core.create_element(types.MBTRI, tri)
|
|
156
|
+
moab_core.add_entity(face_set, moab_triangle)
|
|
10
157
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
158
|
+
added_surfaces_ids[face_id] = face_set
|
|
159
|
+
else:
|
|
160
|
+
face_set = added_surfaces_ids[face_id]
|
|
14
161
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
162
|
+
other_solid_id = face_ids_with_solid_ids[face_id][0]
|
|
163
|
+
|
|
164
|
+
other_volume_set = volume_sets_by_solid_id[other_solid_id]
|
|
165
|
+
|
|
166
|
+
sense_data = np.array([other_volume_set, volume_set], dtype="uint64")
|
|
167
|
+
moab_core.tag_set_data(tags["surf_sense"], face_set, sense_data)
|
|
168
|
+
|
|
169
|
+
moab_core.add_parent_child(volume_set, face_set)
|
|
170
|
+
|
|
171
|
+
moab_core.add_entity(group_set, volume_set)
|
|
172
|
+
|
|
173
|
+
if implicit_complement_material_tag:
|
|
174
|
+
group_set = moab_core.create_meshset()
|
|
175
|
+
moab_core.tag_set_data(tags["category"], group_set, "Group")
|
|
176
|
+
moab_core.tag_set_data(
|
|
177
|
+
tags["name"], group_set, f"mat:{implicit_complement_material_tag}_comp"
|
|
178
|
+
)
|
|
179
|
+
moab_core.tag_set_data(tags["geom_dimension"], group_set, 4)
|
|
180
|
+
moab_core.add_entity(
|
|
181
|
+
group_set, volume_set
|
|
182
|
+
) # volume is arbitrary but should exist in moab core
|
|
183
|
+
|
|
184
|
+
all_sets = moab_core.get_entities_by_handle(0)
|
|
185
|
+
|
|
186
|
+
file_set = moab_core.create_meshset()
|
|
187
|
+
|
|
188
|
+
moab_core.add_entities(file_set, all_sets)
|
|
189
|
+
|
|
190
|
+
moab_core.write_file(h5m_filename)
|
|
191
|
+
|
|
192
|
+
return h5m_filename
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _mesh_brep(
|
|
196
|
+
brep_object: str,
|
|
197
|
+
min_mesh_size: float = 1,
|
|
198
|
+
max_mesh_size: float = 10,
|
|
199
|
+
mesh_algorithm: int = 1,
|
|
200
|
+
dimensions: int = 2,
|
|
201
|
+
):
|
|
202
|
+
"""Creates a conformal surface meshes of the volumes in a Brep file using
|
|
203
|
+
Gmsh.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
brep_object: the filename of the Brep file to convert
|
|
207
|
+
min_mesh_size: the minimum mesh element size to use in Gmsh. Passed
|
|
208
|
+
into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size)
|
|
209
|
+
max_mesh_size: the maximum mesh element size to use in Gmsh. Passed
|
|
210
|
+
into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
|
|
211
|
+
mesh_algorithm: The Gmsh mesh algorithm number to use. Passed into
|
|
212
|
+
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
213
|
+
dimensions: The number of dimensions, 2 for a surface mesh 3 for a
|
|
214
|
+
volume mesh. Passed to gmsh.model.mesh.generate()
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
The resulting gmsh object and volumes
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
gmsh.initialize()
|
|
221
|
+
gmsh.option.setNumber("General.Terminal", 1)
|
|
222
|
+
gmsh.model.add("made_with_cad_to_dagmc_package")
|
|
223
|
+
volumes = gmsh.model.occ.importShapesNativePointer(brep_object)
|
|
224
|
+
gmsh.model.occ.synchronize()
|
|
225
|
+
|
|
226
|
+
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
227
|
+
gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size)
|
|
228
|
+
gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
|
|
229
|
+
gmsh.model.mesh.generate(dimensions)
|
|
230
|
+
|
|
231
|
+
return gmsh, volumes
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _mesh_to_h5m_in_memory_method(
|
|
235
|
+
volumes,
|
|
236
|
+
) -> str:
|
|
237
|
+
"""Converts gmsh volumes into a DAGMC h5m file.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
volumes: the volumes in the gmsh file, found with gmsh.model.occ.importShapes
|
|
241
|
+
material_tags: A list of material tags to tag the DAGMC volumes with.
|
|
242
|
+
Should be in the same order as the volumes
|
|
243
|
+
h5m_filename: the filename of the DAGMC h5m file to write
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
vertices and triangles (grouped by solid then by face)
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
n = 3 # number of verts in a triangles
|
|
250
|
+
triangles_by_solid_by_face = {}
|
|
251
|
+
for dim_and_vol in volumes:
|
|
252
|
+
# removes all groups so that the following getEntitiesForPhysicalGroup
|
|
253
|
+
# command only finds surfaces for the volume
|
|
254
|
+
gmsh.model.removePhysicalGroups()
|
|
255
|
+
|
|
256
|
+
vol_id = dim_and_vol[1]
|
|
257
|
+
entities_in_volume = gmsh.model.getAdjacencies(3, vol_id)
|
|
258
|
+
surfaces_in_volume = entities_in_volume[1]
|
|
259
|
+
ps = gmsh.model.addPhysicalGroup(2, surfaces_in_volume)
|
|
260
|
+
gmsh.model.setPhysicalName(2, ps, f"surfaces_on_volume_{vol_id}")
|
|
261
|
+
|
|
262
|
+
groups = gmsh.model.getPhysicalGroups()
|
|
263
|
+
group = groups[0]
|
|
264
|
+
# for group in groups:
|
|
265
|
+
dim = group[0]
|
|
266
|
+
tag = group[1]
|
|
267
|
+
|
|
268
|
+
surfaces = gmsh.model.getEntitiesForPhysicalGroup(dim, tag)
|
|
269
|
+
|
|
270
|
+
# nodes_in_all_surfaces = []
|
|
271
|
+
nodes_in_each_surface = {}
|
|
272
|
+
for surface in surfaces:
|
|
273
|
+
_, _, nodeTags = gmsh.model.mesh.getElements(2, surface)
|
|
274
|
+
nodeTags = nodeTags[0].tolist()
|
|
275
|
+
shifted_node_tags = []
|
|
276
|
+
for nodeTag in nodeTags:
|
|
277
|
+
shifted_node_tags.append(nodeTag - 1)
|
|
278
|
+
grouped_node_tags = [
|
|
279
|
+
shifted_node_tags[i : i + n] for i in range(0, len(shifted_node_tags), n)
|
|
280
|
+
]
|
|
281
|
+
nodes_in_each_surface[surface] = grouped_node_tags
|
|
282
|
+
triangles_by_solid_by_face[vol_id] = nodes_in_each_surface
|
|
283
|
+
|
|
284
|
+
_, all_coords, _ = gmsh.model.mesh.getNodes()
|
|
285
|
+
|
|
286
|
+
vertices = [all_coords[i : i + n].tolist() for i in range(0, len(all_coords), n)]
|
|
287
|
+
|
|
288
|
+
return vertices, triangles_by_solid_by_face
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def _get_ids_from_assembly(assembly: cq.assembly.Assembly):
|
|
292
|
+
ids = []
|
|
293
|
+
for obj, name, loc, _ in assembly:
|
|
294
|
+
ids.append(name)
|
|
295
|
+
return ids
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _get_ids_from_imprinted_assembly(solid_id_dict):
|
|
299
|
+
ids = []
|
|
300
|
+
for id in list(solid_id_dict.values()):
|
|
301
|
+
ids.append(id[0])
|
|
302
|
+
return ids
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def order_material_ids_by_brep_order(original_ids, scrambled_id, material_tags):
|
|
306
|
+
material_tags_in_brep_order = []
|
|
307
|
+
for brep_id in scrambled_id:
|
|
308
|
+
id_of_solid_in_org = original_ids.index(brep_id)
|
|
309
|
+
material_tags_in_brep_order.append(material_tags[id_of_solid_in_org])
|
|
310
|
+
return material_tags_in_brep_order
|
|
21
311
|
|
|
22
312
|
|
|
23
313
|
class CadToDagmc:
|
|
24
314
|
def __init__(self):
|
|
25
315
|
self.parts = []
|
|
26
|
-
self.material_tags = []
|
|
27
316
|
|
|
28
317
|
def add_stp_file(
|
|
29
318
|
self,
|
|
30
319
|
filename: str,
|
|
31
|
-
material_tags: typing.Iterable[str],
|
|
32
320
|
scale_factor: float = 1.0,
|
|
33
321
|
):
|
|
34
|
-
"""Loads the parts from stp file into the model
|
|
35
|
-
parts and their material tags.
|
|
322
|
+
"""Loads the parts from stp file into the model.
|
|
36
323
|
|
|
37
324
|
Args:
|
|
38
325
|
filename: the filename used to save the html graph.
|
|
@@ -47,28 +334,22 @@ class CadToDagmc:
|
|
|
47
334
|
"""
|
|
48
335
|
part = importers.importStep(str(filename)).val()
|
|
49
336
|
|
|
50
|
-
if scale_factor == 1:
|
|
337
|
+
if scale_factor == 1.0:
|
|
51
338
|
scaled_part = part
|
|
52
339
|
else:
|
|
53
340
|
scaled_part = part.scale(scale_factor)
|
|
54
|
-
self.add_cadquery_object(object=scaled_part
|
|
341
|
+
self.add_cadquery_object(object=scaled_part)
|
|
55
342
|
|
|
56
343
|
def add_cadquery_object(
|
|
57
344
|
self,
|
|
58
345
|
object: typing.Union[
|
|
59
346
|
cq.assembly.Assembly, cq.occ_impl.shapes.Compound, cq.occ_impl.shapes.Solid
|
|
60
347
|
],
|
|
61
|
-
material_tags: typing.Iterable[str],
|
|
62
348
|
):
|
|
63
|
-
"""Loads the parts from CadQuery object into the model
|
|
64
|
-
the parts and their material tags.
|
|
349
|
+
"""Loads the parts from CadQuery object into the model.
|
|
65
350
|
|
|
66
351
|
Args:
|
|
67
352
|
object: the cadquery object to convert
|
|
68
|
-
material_tags: the names of the DAGMC material tags to assign.
|
|
69
|
-
These will need to be in the same order as the volumes in the
|
|
70
|
-
STP file and match the material tags used in the neutronics
|
|
71
|
-
code (e.g. OpenMC).
|
|
72
353
|
"""
|
|
73
354
|
|
|
74
355
|
if isinstance(object, cq.assembly.Assembly):
|
|
@@ -80,92 +361,143 @@ class CadToDagmc:
|
|
|
80
361
|
iterable_solids = object.val().Solids()
|
|
81
362
|
self.parts = self.parts + iterable_solids
|
|
82
363
|
|
|
83
|
-
|
|
84
|
-
msg = f"Number of volumes {len(iterable_solids)} is not equal to number of material tags {len(material_tags)}"
|
|
85
|
-
raise ValueError(msg)
|
|
86
|
-
|
|
87
|
-
for material_tag in material_tags:
|
|
88
|
-
self.material_tags.append(material_tag)
|
|
89
|
-
|
|
90
|
-
def export_dagmc_h5m_file(
|
|
364
|
+
def export_unstructured_mesh_file(
|
|
91
365
|
self,
|
|
92
|
-
filename: str = "
|
|
366
|
+
filename: str = "umesh.h5m",
|
|
93
367
|
min_mesh_size: float = 1,
|
|
94
368
|
max_mesh_size: float = 5,
|
|
95
369
|
mesh_algorithm: int = 1,
|
|
96
|
-
msh_filename: str = None,
|
|
97
370
|
):
|
|
371
|
+
|
|
98
372
|
assembly = cq.Assembly()
|
|
99
373
|
for part in self.parts:
|
|
100
374
|
assembly.add(part)
|
|
101
375
|
|
|
102
|
-
(
|
|
103
|
-
imprinted_assembly,
|
|
104
|
-
imprinted_solids_with_original_id,
|
|
105
|
-
) = cq.occ_impl.assembly.imprint(assembly)
|
|
376
|
+
imprinted_assembly, _ = cq.occ_impl.assembly.imprint(assembly)
|
|
106
377
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
378
|
+
gmsh, volumes = _mesh_brep(
|
|
379
|
+
brep_object=imprinted_assembly.wrapped._address(),
|
|
380
|
+
min_mesh_size=min_mesh_size,
|
|
381
|
+
max_mesh_size=max_mesh_size,
|
|
382
|
+
mesh_algorithm=mesh_algorithm,
|
|
383
|
+
dimensions=3,
|
|
110
384
|
)
|
|
111
385
|
|
|
112
|
-
#
|
|
113
|
-
|
|
386
|
+
# gmesh writes out a vtk file that is converted by pymoab into a h5 file
|
|
387
|
+
gmsh.write(filename + ".vtk")
|
|
114
388
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
389
|
+
moab_core = core.Core()
|
|
390
|
+
moab_core.load_file(filename + ".vtk")
|
|
391
|
+
moab_core.write_file(filename)
|
|
392
|
+
|
|
393
|
+
gmsh.finalize()
|
|
394
|
+
|
|
395
|
+
def export_gmsh_mesh_file(
|
|
396
|
+
self,
|
|
397
|
+
filename: str = "mesh.msh",
|
|
398
|
+
min_mesh_size: float = 1,
|
|
399
|
+
max_mesh_size: float = 5,
|
|
400
|
+
mesh_algorithm: int = 1,
|
|
401
|
+
dimensions: int = 2,
|
|
402
|
+
):
|
|
403
|
+
"""Saves a GMesh msh file of the geometry in either 2D surface mesh or
|
|
404
|
+
3D volume mesh.
|
|
405
|
+
|
|
406
|
+
Args:
|
|
407
|
+
filename
|
|
408
|
+
min_mesh_size: the minimum size of mesh elements to use.
|
|
409
|
+
max_mesh_size: the maximum size of mesh elements to use.
|
|
410
|
+
mesh_algorithm: the gmsh mesh algorithm to use.
|
|
411
|
+
dimensions: The number of dimensions, 2 for a surface mesh 3 for a
|
|
412
|
+
volume mesh. Passed to gmsh.model.mesh.generate()
|
|
413
|
+
"""
|
|
414
|
+
|
|
415
|
+
assembly = cq.Assembly()
|
|
416
|
+
for part in self.parts:
|
|
417
|
+
assembly.add(part)
|
|
418
|
+
|
|
419
|
+
imprinted_assembly, _ = cq.occ_impl.assembly.imprint(assembly)
|
|
118
420
|
|
|
119
|
-
gmsh, volumes =
|
|
421
|
+
gmsh, volumes = _mesh_brep(
|
|
120
422
|
brep_object=imprinted_assembly.wrapped._address(),
|
|
121
423
|
min_mesh_size=min_mesh_size,
|
|
122
424
|
max_mesh_size=max_mesh_size,
|
|
123
425
|
mesh_algorithm=mesh_algorithm,
|
|
426
|
+
dimensions=dimensions,
|
|
124
427
|
)
|
|
125
428
|
|
|
126
|
-
|
|
127
|
-
volumes=volumes,
|
|
128
|
-
material_tags=material_tags_in_brep_order,
|
|
129
|
-
h5m_filename=filename,
|
|
130
|
-
msh_filename=msh_filename,
|
|
131
|
-
)
|
|
132
|
-
return h5m_filename
|
|
429
|
+
gmsh.write(filename)
|
|
133
430
|
|
|
431
|
+
gmsh.finalize()
|
|
134
432
|
|
|
135
|
-
def
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
433
|
+
def export_dagmc_h5m_file(
|
|
434
|
+
self,
|
|
435
|
+
material_tags: typing.Iterable[str],
|
|
436
|
+
filename: str = "dagmc.h5m",
|
|
437
|
+
min_mesh_size: float = 1,
|
|
438
|
+
max_mesh_size: float = 5,
|
|
439
|
+
mesh_algorithm: int = 1,
|
|
440
|
+
implicit_complement_material_tag: typing.Optional[str] = None,
|
|
441
|
+
):
|
|
442
|
+
"""Saves a DAGMC h5m file of the geometry
|
|
139
443
|
|
|
140
|
-
|
|
444
|
+
Args:
|
|
445
|
+
filename
|
|
446
|
+
min_mesh_size: the minimum size of mesh elements to use.
|
|
447
|
+
max_mesh_size: the maximum size of mesh elements to use.
|
|
448
|
+
mesh_algorithm: the gmsh mesh algorithm to use.
|
|
449
|
+
material_tags: the names of the DAGMC material tags to assign.
|
|
450
|
+
These will need to be in the same order as the volumes in the
|
|
451
|
+
geometry geometry added (STP file and CadQuery objects) and
|
|
452
|
+
match the material tags used in the neutronics code (e.g. OpenMC).
|
|
453
|
+
implicit_complement_material_tag: the name of the material tag to
|
|
454
|
+
use for the implicit complement (void space). Defaults to None
|
|
455
|
+
which is a vacuum.
|
|
456
|
+
"""
|
|
457
|
+
assembly = cq.Assembly()
|
|
458
|
+
for part in self.parts:
|
|
459
|
+
assembly.add(part)
|
|
141
460
|
|
|
142
|
-
|
|
461
|
+
imprinted_assembly, imprinted_solids_with_org_id = cq.occ_impl.assembly.imprint(assembly)
|
|
143
462
|
|
|
144
|
-
|
|
145
|
-
|
|
463
|
+
original_ids = _get_ids_from_assembly(assembly)
|
|
464
|
+
scrambled_ids = _get_ids_from_imprinted_assembly(imprinted_solids_with_org_id)
|
|
146
465
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
):
|
|
150
|
-
# stp file
|
|
151
|
-
return parts[0], parts[0].wrapped
|
|
152
|
-
else:
|
|
153
|
-
return parts[0], parts[0].toOCC()
|
|
466
|
+
# both id lists should be the same length as each other and the same
|
|
467
|
+
# length as the self.material_tags
|
|
154
468
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
469
|
+
if len(original_ids) != len(material_tags):
|
|
470
|
+
msg = f"Number of volumes {len(original_ids)} is not equal to number of material tags {len(material_tags)}"
|
|
471
|
+
raise ValueError(msg)
|
|
472
|
+
|
|
473
|
+
material_tags_in_brep_order = order_material_ids_by_brep_order(
|
|
474
|
+
original_ids, scrambled_ids, material_tags
|
|
475
|
+
)
|
|
162
476
|
|
|
163
|
-
|
|
477
|
+
gmsh, volumes = _mesh_brep(
|
|
478
|
+
brep_object=imprinted_assembly.wrapped._address(), # in memory address
|
|
479
|
+
min_mesh_size=min_mesh_size,
|
|
480
|
+
max_mesh_size=max_mesh_size,
|
|
481
|
+
mesh_algorithm=mesh_algorithm,
|
|
482
|
+
)
|
|
164
483
|
|
|
165
|
-
|
|
484
|
+
if isinstance(material_tags_in_brep_order, str):
|
|
485
|
+
msg = f"material_tags should be a list of strings, not a single string."
|
|
486
|
+
raise ValueError(msg)
|
|
166
487
|
|
|
167
|
-
|
|
488
|
+
if len(volumes) != len(material_tags_in_brep_order):
|
|
489
|
+
msg = f"{len(volumes)} volumes found in Brep file is not equal to the number of material_tags {len(material_tags_in_brep_order)} provided."
|
|
490
|
+
raise ValueError(msg)
|
|
491
|
+
|
|
492
|
+
vertices, triangles_by_solid_by_face = _mesh_to_h5m_in_memory_method(volumes=volumes)
|
|
168
493
|
|
|
169
|
-
|
|
494
|
+
gmsh.finalize()
|
|
170
495
|
|
|
171
|
-
|
|
496
|
+
# checks and fixes triangle fix_normals within vertices_to_h5m
|
|
497
|
+
return _vertices_to_h5m(
|
|
498
|
+
vertices=vertices,
|
|
499
|
+
triangles_by_solid_by_face=triangles_by_solid_by_face,
|
|
500
|
+
material_tags=material_tags_in_brep_order,
|
|
501
|
+
h5m_filename=filename,
|
|
502
|
+
implicit_complement_material_tag=implicit_complement_material_tag,
|
|
503
|
+
)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cad_to_dagmc
|
|
3
|
+
Version: 0.6.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
|
+
Requires-Dist: vtk ; extra == 'tests'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
[](https://www.python.org)
|
|
23
|
+
|
|
24
|
+
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/ci_with_install.yml) Testing package and running examples
|
|
25
|
+
|
|
26
|
+
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/ci_with_benchmarks.yml) Testing with [Model Benchmark Zoo](https://github.com/fusion-energy/model_benchmark_zoo)
|
|
27
|
+
|
|
28
|
+
[](https://github.com/fusion-energy/cad_to_dagmc/actions/workflows/python-publish.yml)
|
|
29
|
+
|
|
30
|
+
[](https://pypi.org/project/cad_to_dagmc/)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
A minimal package that converts CAD geometry to [DAGMC](https://github.com/svalinn/DAGMC/) h5m files
|
|
34
|
+
|
|
35
|
+
cad-to-dagmc can create:
|
|
36
|
+
- surface meshes / faceted geometry / triangular meshes
|
|
37
|
+
- unstructured mesh / tetrahedral meshes / volume meshes
|
|
38
|
+
|
|
39
|
+
cad-to-dagmc can convert:
|
|
40
|
+
- STEP files
|
|
41
|
+
- CadQuery objects (in memory)
|
|
42
|
+
|
|
43
|
+
cadto-dagmc aims to produce DAGMC compatible h5m files from CAD geometry is intended to convert [STEP](http://www.steptools.com/stds/step/) files or [CadQuery](https://cadquery.readthedocs.io) objects to a [DAGMC](https://github.com/svalinn/DAGMC/) compatible h5m file.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
The resulting DAGMC geometry can then be used for simulations in [OpenMC](https://github.com/openmc-dev/openmc/) or [other supported codes](https://svalinn.github.io/DAGMC/).
|
|
47
|
+
|
|
48
|
+
This package is tested with [pytest tests](https://github.com/fusion-energy/cad_to_dagmc/tree/main/tests) and also the DAGMC geometry made with this package is compared to simulation carried out with native constructive solid geometry, see [Model Benchmark Zoo](https://github.com/fusion-energy/model_benchmark_zoo) for more details.
|
|
49
|
+
|
|
50
|
+
Also checkout these other software projects that also create DAGMC geometry [CAD-to-OpenMC](https://github.com/openmsr/CAD_to_OpenMC), [Stellarmesh](https://github.com/Thea-Energy/stellarmesh) and [Coreform Cubit](https://coreform.com/products/coreform-cubit/)
|
|
51
|
+
|
|
52
|
+
# Installation prerequisite
|
|
53
|
+
|
|
54
|
+
In principle, any Conda/Mamba distribution will work. A few Conda/Mamba options are:
|
|
55
|
+
- [Miniforge](https://github.com/conda-forge/miniforge) (recommended as it includes mamba)
|
|
56
|
+
- [Anaconda](https://www.anaconda.com/download)
|
|
57
|
+
- [Miniconda](https://docs.conda.io/en/latest/miniconda.html)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Install using Mamba and pip
|
|
61
|
+
|
|
62
|
+
This example assumes you have installed the Miniforge option or separately have installed Mamba with ```conda install -c conda-forge mamba -y```
|
|
63
|
+
|
|
64
|
+
Create a new conda environment, I've chosen Python 3.10 here but newer versions are
|
|
65
|
+
also supported.
|
|
66
|
+
```bash
|
|
67
|
+
mamba create --name new_env python=3.10 -y
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Activate the environment
|
|
71
|
+
```bash
|
|
72
|
+
mamba activate new_env
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Install the dependencies
|
|
76
|
+
```bash
|
|
77
|
+
mamba install -y -c conda-forge gmsh python-gmsh moab>=5.3.0 ocp>=7.7.2.0 cadquery>=2.4.0
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Then you can install the cad_to_dagmc package with ```pip```
|
|
81
|
+
```bash
|
|
82
|
+
pip install cad_to_dagmc
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
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/).
|
|
86
|
+
|
|
87
|
+
To install OpenMC You can run ```mamba 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
|
|
88
|
+
```bash
|
|
89
|
+
mamba install -c conda-forge -y "openmc=0.14.0=dagmc*nompi*"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
It might not be possible to install OpenMC and cad-to-dagmc in the same conda/mamba python environment so you may have to create a new conda/mamba environment and install OpenMC there.
|
|
93
|
+
|
|
94
|
+
Another option would be to [install OpenMC from source](https://docs.openmc.org/en/stable/quickinstall.html) which would also need compiling with MOAB and DAGMC options.
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# Install using Conda and pip
|
|
98
|
+
|
|
99
|
+
This example uses Conda to install some dependencies that are not available via PyPi.
|
|
100
|
+
|
|
101
|
+
Create a new conda environment
|
|
102
|
+
```bash
|
|
103
|
+
conda create --name new_env python=3.10 -y
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Activate the environment
|
|
107
|
+
```bash
|
|
108
|
+
conda activate new_env
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Install the dependencies
|
|
112
|
+
```bash
|
|
113
|
+
conda install -y -c conda-forge gmsh python-gmsh moab>=5.3.0 ocp>=7.7.2.0 cadquery>=2.4.0
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Then you can install the cad_to_dagmc package with ```pip```
|
|
117
|
+
```bash
|
|
118
|
+
pip install cad_to_dagmc
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
# Usage - with OpenMC
|
|
122
|
+
|
|
123
|
+
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 supported by [DAGMC](https://svalinn.github.io/DAGMC/).
|
|
124
|
+
|
|
125
|
+
You can run ```mamba install -c conda-forge openmc``` however this may choose to install OpenMC without DAGMC included.
|
|
126
|
+
|
|
127
|
+
You can be more specific with conda/mamba commands to make sure the latest version of OpenMC which contains DAGMC is chosen by conda / mamba
|
|
128
|
+
```bash
|
|
129
|
+
mamba install -c conda-forge -y "openmc=0.14.0=dagmc*nompi*"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
You could also [install OpenMC from source](https://docs.openmc.org/en/stable/quickinstall.html) which might be prefered as it can be tricky for the conda enviroment to get resolved.
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# Usage - creation of DAGMC h5m files
|
|
137
|
+
|
|
138
|
+
For examples see the [examples folder](https://github.com/fusion-energy/cad_to_dagmc/tree/main/examples)
|
|
139
|
+
|
|
140
|
+
# Usage - simulation with transport code
|
|
141
|
+
|
|
142
|
+
For examples see the [examples folder](https://github.com/fusion-energy/cad_to_dagmc/tree/main/examples)
|
|
143
|
+
|
|
144
|
+
For more examples see the CAD tasks in the [neutronics-workshop](https://github.com/fusion-energy/neutronics-workshop) and [model benchmark zoo](https://github.com/fusion-energy/model_benchmark_zoo)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
_version.py,sha256=2JKwcA-YQ0okV2N-gwTWy_n51igWrPcsKQFm0cnqsvw,411
|
|
2
|
+
cad_to_dagmc/__init__.py,sha256=fskHUTyCunSpnpJUvBfAYjx4uwDKXHTTiMP6GqnFRf0,494
|
|
3
|
+
cad_to_dagmc/core.py,sha256=eMwKgKOjje3gBZEqjNzy9O6NF8a02WxD-VhXB5AJg58,18108
|
|
4
|
+
cad_to_dagmc-0.6.0.dist-info/LICENSE,sha256=B8kznH_777JVNZ3HOKDc4Tj24F7wJ68ledaNYeL9sCw,1070
|
|
5
|
+
cad_to_dagmc-0.6.0.dist-info/METADATA,sha256=Zrz_-X2KkLAoKrucNIcvOr1070dmSxq10ytsfqU5oWA,6771
|
|
6
|
+
cad_to_dagmc-0.6.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
7
|
+
cad_to_dagmc-0.6.0.dist-info/top_level.txt,sha256=zTi8C64SEBsE5WOtPovnxhOzt-E6Oc5nC3RW6M_5aEA,22
|
|
8
|
+
cad_to_dagmc-0.6.0.dist-info/RECORD,,
|
cad_to_dagmc/brep_part_finder.py
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import cadquery as cq
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def convert_shape_to_iterable_of_shapes(shapes):
|
|
5
|
-
if isinstance(shapes, cq.occ_impl.shapes.Compound):
|
|
6
|
-
# brep route
|
|
7
|
-
iterable_solids = shapes.Solids()
|
|
8
|
-
elif isinstance(shapes, cq.Workplane):
|
|
9
|
-
# workplane route
|
|
10
|
-
iterable_solids = shapes.val().Solids()
|
|
11
|
-
else:
|
|
12
|
-
iterable_solids = shapes.Solids()
|
|
13
|
-
|
|
14
|
-
return iterable_solids
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def get_ids_from_assembly(assembly):
|
|
18
|
-
ids = []
|
|
19
|
-
for obj, name, loc, _ in assembly:
|
|
20
|
-
ids.append(name)
|
|
21
|
-
return ids
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def get_ids_from_imprinted_assembly(solid_id_dict):
|
|
25
|
-
ids = []
|
|
26
|
-
for id in list(solid_id_dict.values()):
|
|
27
|
-
ids.append(id[0])
|
|
28
|
-
return ids
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def order_material_ids_by_brep_order(original_ids, scrambled_id, material_tags):
|
|
32
|
-
material_tags_in_brep_order = []
|
|
33
|
-
for brep_id in scrambled_id:
|
|
34
|
-
id_of_solid_in_org = original_ids.index(brep_id)
|
|
35
|
-
material_tags_in_brep_order.append(material_tags[id_of_solid_in_org])
|
|
36
|
-
return material_tags_in_brep_order
|
cad_to_dagmc/brep_to_h5m.py
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import gmsh
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
from .vertices_to_h5m import vertices_to_h5m
|
|
4
|
-
import typing
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def mesh_brep(
|
|
8
|
-
brep_object: str,
|
|
9
|
-
min_mesh_size: float = 1,
|
|
10
|
-
max_mesh_size: float = 10,
|
|
11
|
-
mesh_algorithm: int = 1,
|
|
12
|
-
):
|
|
13
|
-
"""Creates a conformal surface meshes of the volumes in a Brep file using
|
|
14
|
-
Gmsh.
|
|
15
|
-
|
|
16
|
-
Args:
|
|
17
|
-
brep_object: the filename of the Brep file to convert
|
|
18
|
-
min_mesh_size: the minimum mesh element size to use in Gmsh. Passed
|
|
19
|
-
into gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size)
|
|
20
|
-
max_mesh_size: the maximum mesh element size to use in Gmsh. Passed
|
|
21
|
-
into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
|
|
22
|
-
mesh_algorithm: The Gmsh mesh algorithm number to use. Passed into
|
|
23
|
-
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
The gmsh object and volumes in Brep file
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
gmsh.initialize()
|
|
30
|
-
gmsh.option.setNumber("General.Terminal", 1)
|
|
31
|
-
gmsh.model.add("made_with_brep_to_h5m_package")
|
|
32
|
-
volumes = gmsh.model.occ.importShapesNativePointer(brep_object)
|
|
33
|
-
# gmsh.model.occ.importShapes(brep_object)
|
|
34
|
-
gmsh.model.occ.synchronize()
|
|
35
|
-
|
|
36
|
-
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
37
|
-
gmsh.option.setNumber("Mesh.MeshSizeMin", min_mesh_size)
|
|
38
|
-
gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
|
|
39
|
-
gmsh.model.mesh.generate(2)
|
|
40
|
-
|
|
41
|
-
return gmsh, volumes
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def mesh_to_h5m_in_memory_method(
|
|
45
|
-
volumes,
|
|
46
|
-
material_tags: typing.Iterable[str],
|
|
47
|
-
h5m_filename: str = "dagmc.h5m",
|
|
48
|
-
msh_filename=None,
|
|
49
|
-
) -> str:
|
|
50
|
-
"""Converts gmsh volumes into a DAGMC h5m file.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
volumes: the volumes in the gmsh file, found with gmsh.model.occ.importShapes
|
|
54
|
-
material_tags: A list of material tags to tag the DAGMC volumes with.
|
|
55
|
-
Should be in the same order as the volumes
|
|
56
|
-
h5m_filename: the filename of the DAGMC h5m file to write
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
The filename of the h5m file produced
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
if isinstance(material_tags, str):
|
|
63
|
-
msg = f"material_tags should be a list of strings, not a single string."
|
|
64
|
-
raise ValueError(msg)
|
|
65
|
-
|
|
66
|
-
if len(volumes) != len(material_tags):
|
|
67
|
-
msg = f"{len(volumes)} volumes found in Brep file is not equal to the number of material_tags {len(material_tags)} provided."
|
|
68
|
-
raise ValueError(msg)
|
|
69
|
-
|
|
70
|
-
n = 3 # number of verts in a triangles
|
|
71
|
-
triangles_by_solid_by_face = {}
|
|
72
|
-
for dim_and_vol in volumes:
|
|
73
|
-
# removes all groups so that the following getEntitiesForPhysicalGroup
|
|
74
|
-
# command only finds surfaces for the volume
|
|
75
|
-
gmsh.model.removePhysicalGroups()
|
|
76
|
-
|
|
77
|
-
vol_id = dim_and_vol[1]
|
|
78
|
-
entities_in_volume = gmsh.model.getAdjacencies(3, vol_id)
|
|
79
|
-
surfaces_in_volume = entities_in_volume[1]
|
|
80
|
-
ps = gmsh.model.addPhysicalGroup(2, surfaces_in_volume)
|
|
81
|
-
gmsh.model.setPhysicalName(2, ps, f"surfaces_on_volume_{vol_id}")
|
|
82
|
-
|
|
83
|
-
groups = gmsh.model.getPhysicalGroups()
|
|
84
|
-
group = groups[0]
|
|
85
|
-
# for group in groups:
|
|
86
|
-
dim = group[0]
|
|
87
|
-
tag = group[1]
|
|
88
|
-
|
|
89
|
-
surfaces = gmsh.model.getEntitiesForPhysicalGroup(dim, tag)
|
|
90
|
-
|
|
91
|
-
# nodes_in_all_surfaces = []
|
|
92
|
-
nodes_in_each_surface = {}
|
|
93
|
-
for surface in surfaces:
|
|
94
|
-
_, _, nodeTags = gmsh.model.mesh.getElements(2, surface)
|
|
95
|
-
nodeTags = nodeTags[0].tolist()
|
|
96
|
-
shifted_node_tags = []
|
|
97
|
-
for nodeTag in nodeTags:
|
|
98
|
-
shifted_node_tags.append(nodeTag - 1)
|
|
99
|
-
grouped_node_tags = [
|
|
100
|
-
shifted_node_tags[i : i + n]
|
|
101
|
-
for i in range(0, len(shifted_node_tags), n)
|
|
102
|
-
]
|
|
103
|
-
nodes_in_each_surface[surface] = grouped_node_tags
|
|
104
|
-
triangles_by_solid_by_face[vol_id] = nodes_in_each_surface
|
|
105
|
-
|
|
106
|
-
_, all_coords, _ = gmsh.model.mesh.getNodes()
|
|
107
|
-
|
|
108
|
-
vertices = [all_coords[i : i + n].tolist() for i in range(0, len(all_coords), n)]
|
|
109
|
-
|
|
110
|
-
if msh_filename is not None:
|
|
111
|
-
gmsh.write(msh_filename)
|
|
112
|
-
|
|
113
|
-
gmsh.finalize()
|
|
114
|
-
|
|
115
|
-
# checks and fixes triangle fix_normals within vertices_to_h5m
|
|
116
|
-
return vertices_to_h5m(
|
|
117
|
-
vertices=vertices,
|
|
118
|
-
triangles_by_solid_by_face=triangles_by_solid_by_face,
|
|
119
|
-
material_tags=material_tags,
|
|
120
|
-
h5m_filename=h5m_filename,
|
|
121
|
-
)
|
cad_to_dagmc/vertices_to_h5m.py
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
from typing import Iterable, Tuple, Union
|
|
2
|
-
import typing
|
|
3
|
-
import numpy as np
|
|
4
|
-
import trimesh
|
|
5
|
-
from pymoab import core, types
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def fix_normals(vertices: list, triangles_in_each_volume: list):
|
|
9
|
-
fixed_triangles = []
|
|
10
|
-
for triangles in triangles_in_each_volume:
|
|
11
|
-
fixed_triangles.append(fix_normal(vertices, triangles))
|
|
12
|
-
return fixed_triangles
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def fix_normal(vertices: list, triangles: list):
|
|
16
|
-
mesh = trimesh.Trimesh(vertices=vertices, faces=triangles, process=False)
|
|
17
|
-
|
|
18
|
-
mesh.fix_normals()
|
|
19
|
-
|
|
20
|
-
return mesh.faces
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _define_moab_core_and_tags() -> Tuple[core.Core, dict]:
|
|
24
|
-
"""Creates a MOAB Core instance which can be built up by adding sets of
|
|
25
|
-
triangles to the instance
|
|
26
|
-
|
|
27
|
-
Returns:
|
|
28
|
-
(pymoab Core): A pymoab.core.Core() instance
|
|
29
|
-
(pymoab tag_handle): A pymoab.core.tag_get_handle() instance
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
# create pymoab instance
|
|
33
|
-
moab_core = core.Core()
|
|
34
|
-
|
|
35
|
-
tags = dict()
|
|
36
|
-
|
|
37
|
-
sense_tag_name = "GEOM_SENSE_2"
|
|
38
|
-
sense_tag_size = 2
|
|
39
|
-
tags["surf_sense"] = moab_core.tag_get_handle(
|
|
40
|
-
sense_tag_name,
|
|
41
|
-
sense_tag_size,
|
|
42
|
-
types.MB_TYPE_HANDLE,
|
|
43
|
-
types.MB_TAG_SPARSE,
|
|
44
|
-
create_if_missing=True,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
tags["category"] = moab_core.tag_get_handle(
|
|
48
|
-
types.CATEGORY_TAG_NAME,
|
|
49
|
-
types.CATEGORY_TAG_SIZE,
|
|
50
|
-
types.MB_TYPE_OPAQUE,
|
|
51
|
-
types.MB_TAG_SPARSE,
|
|
52
|
-
create_if_missing=True,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
tags["name"] = moab_core.tag_get_handle(
|
|
56
|
-
types.NAME_TAG_NAME,
|
|
57
|
-
types.NAME_TAG_SIZE,
|
|
58
|
-
types.MB_TYPE_OPAQUE,
|
|
59
|
-
types.MB_TAG_SPARSE,
|
|
60
|
-
create_if_missing=True,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
tags["geom_dimension"] = moab_core.tag_get_handle(
|
|
64
|
-
types.GEOM_DIMENSION_TAG_NAME,
|
|
65
|
-
1,
|
|
66
|
-
types.MB_TYPE_INTEGER,
|
|
67
|
-
types.MB_TAG_DENSE,
|
|
68
|
-
create_if_missing=True,
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
# Global ID is a default tag, just need the name to retrieve
|
|
72
|
-
tags["global_id"] = moab_core.tag_get_handle(types.GLOBAL_ID_TAG_NAME)
|
|
73
|
-
|
|
74
|
-
return moab_core, tags
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def prepare_moab_core_volume_set(
|
|
78
|
-
moab_core,
|
|
79
|
-
volume_id,
|
|
80
|
-
tags,
|
|
81
|
-
):
|
|
82
|
-
volume_set = moab_core.create_meshset()
|
|
83
|
-
|
|
84
|
-
# recent versions of MOAB handle this automatically
|
|
85
|
-
# but best to go ahead and do it manually
|
|
86
|
-
moab_core.tag_set_data(tags["global_id"], volume_set, volume_id)
|
|
87
|
-
|
|
88
|
-
# set geom IDs
|
|
89
|
-
moab_core.tag_set_data(tags["geom_dimension"], volume_set, 3)
|
|
90
|
-
|
|
91
|
-
# set category tag values
|
|
92
|
-
moab_core.tag_set_data(tags["category"], volume_set, "Volume")
|
|
93
|
-
|
|
94
|
-
return moab_core, volume_set
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def prepare_moab_core_surface_set(
|
|
98
|
-
moab_core,
|
|
99
|
-
surface_id,
|
|
100
|
-
tags,
|
|
101
|
-
):
|
|
102
|
-
surface_set = moab_core.create_meshset()
|
|
103
|
-
|
|
104
|
-
moab_core.tag_set_data(tags["global_id"], surface_set, surface_id)
|
|
105
|
-
|
|
106
|
-
# set geom IDs
|
|
107
|
-
moab_core.tag_set_data(tags["geom_dimension"], surface_set, 2)
|
|
108
|
-
|
|
109
|
-
# set category tag values
|
|
110
|
-
moab_core.tag_set_data(tags["category"], surface_set, "Surface")
|
|
111
|
-
|
|
112
|
-
return moab_core, surface_set
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def add_triangles_to_moab_core(
|
|
116
|
-
material_tag, surface_set, moab_core, tags, triangles, moab_verts, volume_set
|
|
117
|
-
):
|
|
118
|
-
for triangle in triangles:
|
|
119
|
-
tri = (
|
|
120
|
-
moab_verts[int(triangle[0])],
|
|
121
|
-
moab_verts[int(triangle[1])],
|
|
122
|
-
moab_verts[int(triangle[2])],
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
moab_triangle = moab_core.create_element(types.MBTRI, tri)
|
|
126
|
-
moab_core.add_entity(surface_set, moab_triangle)
|
|
127
|
-
|
|
128
|
-
group_set = moab_core.create_meshset()
|
|
129
|
-
|
|
130
|
-
moab_core.tag_set_data(tags["category"], group_set, "Group")
|
|
131
|
-
|
|
132
|
-
moab_core.tag_set_data(tags["name"], group_set, f"mat:{material_tag}")
|
|
133
|
-
|
|
134
|
-
moab_core.tag_set_data(tags["geom_dimension"], group_set, 4)
|
|
135
|
-
|
|
136
|
-
moab_core.add_entity(group_set, volume_set)
|
|
137
|
-
|
|
138
|
-
return moab_core
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def vertices_to_h5m(
|
|
142
|
-
vertices: Union[
|
|
143
|
-
Iterable[Tuple[float, float, float]], Iterable["cadquery.occ_impl.geom.Vector"]
|
|
144
|
-
],
|
|
145
|
-
triangles_by_solid_by_face: Iterable[Iterable[Tuple[int, int, int]]],
|
|
146
|
-
material_tags: Iterable[str],
|
|
147
|
-
h5m_filename="dagmc.h5m",
|
|
148
|
-
):
|
|
149
|
-
"""Converts vertices and triangle sets into a tagged h5m file compatible
|
|
150
|
-
with DAGMC enabled neutronics simulations
|
|
151
|
-
|
|
152
|
-
Args:
|
|
153
|
-
vertices:
|
|
154
|
-
triangles:
|
|
155
|
-
material_tags:
|
|
156
|
-
h5m_filename:
|
|
157
|
-
"""
|
|
158
|
-
|
|
159
|
-
if len(material_tags) != len(triangles_by_solid_by_face):
|
|
160
|
-
msg = f"The number of material_tags provided is {len(material_tags)} and the number of sets of triangles is {len(triangles_by_solid_by_face)}. You must provide one material_tag for every triangle set"
|
|
161
|
-
raise ValueError(msg)
|
|
162
|
-
|
|
163
|
-
# limited attribute checking to see if user passed in a list of CadQuery vectors
|
|
164
|
-
if (
|
|
165
|
-
hasattr(vertices[0], "x")
|
|
166
|
-
and hasattr(vertices[0], "y")
|
|
167
|
-
and hasattr(vertices[0], "z")
|
|
168
|
-
):
|
|
169
|
-
vertices_floats = []
|
|
170
|
-
for vert in vertices:
|
|
171
|
-
vertices_floats.append((vert.x, vert.y, vert.z))
|
|
172
|
-
else:
|
|
173
|
-
vertices_floats = vertices
|
|
174
|
-
|
|
175
|
-
face_ids_with_solid_ids = {}
|
|
176
|
-
for solid_id, triangles_on_each_face in triangles_by_solid_by_face.items():
|
|
177
|
-
for face_id, triangles_on_face in triangles_on_each_face.items():
|
|
178
|
-
if face_id in face_ids_with_solid_ids.keys():
|
|
179
|
-
face_ids_with_solid_ids[face_id].append(solid_id)
|
|
180
|
-
else:
|
|
181
|
-
face_ids_with_solid_ids[face_id] = [solid_id]
|
|
182
|
-
|
|
183
|
-
moab_core, tags = _define_moab_core_and_tags()
|
|
184
|
-
|
|
185
|
-
volume_sets_by_solid_id = {}
|
|
186
|
-
for material_tag, (solid_id, triangles_on_each_face) in zip(
|
|
187
|
-
material_tags, triangles_by_solid_by_face.items()
|
|
188
|
-
):
|
|
189
|
-
volume_set = moab_core.create_meshset()
|
|
190
|
-
volume_sets_by_solid_id[solid_id] = volume_set
|
|
191
|
-
|
|
192
|
-
added_surfaces_ids = {}
|
|
193
|
-
for material_tag, (solid_id, triangles_on_each_face) in zip(
|
|
194
|
-
material_tags, triangles_by_solid_by_face.items()
|
|
195
|
-
):
|
|
196
|
-
volume_set = volume_sets_by_solid_id[solid_id]
|
|
197
|
-
|
|
198
|
-
moab_core.tag_set_data(tags["global_id"], volume_set, solid_id)
|
|
199
|
-
moab_core.tag_set_data(tags["geom_dimension"], volume_set, 3)
|
|
200
|
-
moab_core.tag_set_data(tags["category"], volume_set, "Volume")
|
|
201
|
-
|
|
202
|
-
group_set = moab_core.create_meshset()
|
|
203
|
-
moab_core.tag_set_data(tags["category"], group_set, "Group")
|
|
204
|
-
moab_core.tag_set_data(tags["name"], group_set, f"mat:{material_tag}")
|
|
205
|
-
moab_core.tag_set_data(tags["global_id"], group_set, solid_id)
|
|
206
|
-
# moab_core.tag_set_data(tags["geom_dimension"], group_set, 4)
|
|
207
|
-
|
|
208
|
-
for face_id, triangles_on_face in triangles_on_each_face.items():
|
|
209
|
-
if face_id not in added_surfaces_ids.keys():
|
|
210
|
-
face_set = moab_core.create_meshset()
|
|
211
|
-
moab_core.tag_set_data(tags["global_id"], face_set, face_id)
|
|
212
|
-
moab_core.tag_set_data(tags["geom_dimension"], face_set, 2)
|
|
213
|
-
moab_core.tag_set_data(tags["category"], face_set, "Surface")
|
|
214
|
-
|
|
215
|
-
if len(face_ids_with_solid_ids[face_id]) == 2:
|
|
216
|
-
other_solid_id = face_ids_with_solid_ids[face_id][1]
|
|
217
|
-
other_volume_set = volume_sets_by_solid_id[other_solid_id]
|
|
218
|
-
sense_data = np.array(
|
|
219
|
-
[other_volume_set, volume_set], dtype="uint64"
|
|
220
|
-
)
|
|
221
|
-
else:
|
|
222
|
-
sense_data = np.array([volume_set, 0], dtype="uint64")
|
|
223
|
-
|
|
224
|
-
moab_core.tag_set_data(tags["surf_sense"], face_set, sense_data)
|
|
225
|
-
|
|
226
|
-
moab_verts = moab_core.create_vertices(vertices)
|
|
227
|
-
moab_core.add_entity(face_set, moab_verts)
|
|
228
|
-
|
|
229
|
-
for triangle in triangles_on_face:
|
|
230
|
-
tri = (
|
|
231
|
-
moab_verts[int(triangle[0])],
|
|
232
|
-
moab_verts[int(triangle[1])],
|
|
233
|
-
moab_verts[int(triangle[2])],
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
moab_triangle = moab_core.create_element(types.MBTRI, tri)
|
|
237
|
-
moab_core.add_entity(face_set, moab_triangle)
|
|
238
|
-
|
|
239
|
-
added_surfaces_ids[face_id] = face_set
|
|
240
|
-
else:
|
|
241
|
-
face_set = added_surfaces_ids[face_id]
|
|
242
|
-
|
|
243
|
-
other_solid_id = face_ids_with_solid_ids[face_id][0]
|
|
244
|
-
|
|
245
|
-
other_volume_set = volume_sets_by_solid_id[other_solid_id]
|
|
246
|
-
|
|
247
|
-
sense_data = np.array([other_volume_set, volume_set], dtype="uint64")
|
|
248
|
-
moab_core.tag_set_data(tags["surf_sense"], face_set, sense_data)
|
|
249
|
-
|
|
250
|
-
moab_core.add_parent_child(volume_set, face_set)
|
|
251
|
-
|
|
252
|
-
moab_core.add_entity(group_set, volume_set)
|
|
253
|
-
|
|
254
|
-
all_sets = moab_core.get_entities_by_handle(0)
|
|
255
|
-
|
|
256
|
-
file_set = moab_core.create_meshset()
|
|
257
|
-
|
|
258
|
-
moab_core.add_entities(file_set, all_sets)
|
|
259
|
-
|
|
260
|
-
moab_core.write_file(h5m_filename)
|
|
261
|
-
|
|
262
|
-
return h5m_filename
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: cad-to-dagmc
|
|
3
|
-
Version: 0.5.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
|
-
[](https://pypi.org/project/cad_to_dagmc/)
|
|
28
|
-
|
|
29
|
-
___
|
|
30
|
-
|
|
31
|
-
A minimal package that uses CadQuery functionality to convert CAD geometry to [DAGMC](https://github.com/svalinn/DAGMC/) h5m files
|
|
32
|
-
|
|
33
|
-
This particular method of producing DAGMC compatible h5m files from CAD geometry
|
|
34
|
-
is intended to convert STP files or [CadQuery](https://cadquery.readthedocs.io) objects to h5m file.
|
|
35
|
-
|
|
36
|
-
One unique feature of this package is the ability to combine STP files with CadQuery objects.
|
|
37
|
-
This allows for the addition of parametric geometry to static geometry.
|
|
38
|
-
|
|
39
|
-
The resulting DAGMC geometry can then be used for simulations in [OpenMC](https://github.com/openmc-dev/openmc/) or [other supported codes](https://svalinn.github.io/DAGMC/).
|
|
40
|
-
|
|
41
|
-
# Installation prerequisite
|
|
42
|
-
|
|
43
|
-
In principle, any Conda/Mamba distribution will work. A few Conda/Mamba options are:
|
|
44
|
-
- [Mambaforge](https://github.com/conda-forge/miniforge#mambaforge)
|
|
45
|
-
- [Miniforge](https://github.com/conda-forge/miniforge#miniforge-pypy3)
|
|
46
|
-
- [Anaconda](https://www.anaconda.com/download)
|
|
47
|
-
- [Miniconda](https://docs.conda.io/en/latest/miniconda.html)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
# Install using Mamba and pip
|
|
51
|
-
|
|
52
|
-
This example assumes you have installed the MambaForge option or separately
|
|
53
|
-
installed Mamba with ```conda install -c conda-forge mamba -y```
|
|
54
|
-
|
|
55
|
-
Create a new conda environment, I've chosen Python 3.9 here but new versions are
|
|
56
|
-
also supported.
|
|
57
|
-
```bash
|
|
58
|
-
mamba create --name new_env python=3.9 -y
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Activate the environment
|
|
62
|
-
```bash
|
|
63
|
-
mamba activate new_env
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Install the dependencies
|
|
67
|
-
```bash
|
|
68
|
-
mamba install -c cadquery -c conda-forge moab gmsh python-gmsh cadquery=master -y
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Then you can install the cad_to_dagmc package with ```pip```
|
|
72
|
-
```bash
|
|
73
|
-
pip install cad_to_dagmc
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
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
|
|
77
|
-
```bash
|
|
78
|
-
mamba install -c conda-forge -y "openmc=0.13.3=dagmc*nompi*"
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# Install using Conda and pip
|
|
83
|
-
|
|
84
|
-
This example uses Conda to install some dependencies that are not available via PyPi.
|
|
85
|
-
|
|
86
|
-
Create a new conda environment
|
|
87
|
-
```bash
|
|
88
|
-
conda create --name new_env python=3.9 -y
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Activate the environment
|
|
92
|
-
```bash
|
|
93
|
-
conda activate new_env
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Install the dependencies
|
|
97
|
-
```bash
|
|
98
|
-
conda install -c cadquery -c conda-forge moab gmsh python-gmsh cadquery=master -y
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Then you can install the cad_to_dagmc package with ```pip```
|
|
102
|
-
```bash
|
|
103
|
-
pip install cad_to_dagmc
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
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
|
|
107
|
-
```bash
|
|
108
|
-
conda install -c conda-forge -y "openmc=0.13.3=dagmc*nompi*"
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
# Usage - creation of DAGMC h5m files
|
|
114
|
-
|
|
115
|
-
For examples see the [examples folder](https://github.com/fusion-energy/cad_to_dagmc/tree/main/examples)
|
|
116
|
-
|
|
117
|
-
# Usage - simulation with transport code
|
|
118
|
-
|
|
119
|
-
For examples see the CAD tasks in the [neutronics-workshop](https://github.com/fusion-energy/neutronics-workshop)
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
_version.py,sha256=3YxISZVp_DgBHizWP4UzbUATbJ2-kn6oz3xEF0uxyCg,274
|
|
2
|
-
cad_to_dagmc/__init__.py,sha256=pI6sOn4nbEiZClP53g2UJSNgE8tkm9wz-hA_JLwUkLk,638
|
|
3
|
-
cad_to_dagmc/brep_part_finder.py,sha256=Se5IYTbPvmYOU28C-Sx2xYrn6ZRVXWicNjra1lVyWxw,999
|
|
4
|
-
cad_to_dagmc/brep_to_h5m.py,sha256=AXm8AF68rD6iSNpLcSyGwCPTUyXC1yoLH47Q4hmUZFc,4266
|
|
5
|
-
cad_to_dagmc/core.py,sha256=Sd2ITQfg2pEcRjpUGZgysGJNdiXrk9En953ItqgAH7o,5584
|
|
6
|
-
cad_to_dagmc/vertices_to_h5m.py,sha256=AUi8ddOl5pv1riH7rZY4r4L1GsgoPUO_NZ4S2sxwPJQ,8550
|
|
7
|
-
cad_to_dagmc-0.5.0.dist-info/LICENSE,sha256=B8kznH_777JVNZ3HOKDc4Tj24F7wJ68ledaNYeL9sCw,1070
|
|
8
|
-
cad_to_dagmc-0.5.0.dist-info/METADATA,sha256=oj692qzyRJyYR13BfyZyaoJ4Ue1QMKvbRs6U2osQ19U,4838
|
|
9
|
-
cad_to_dagmc-0.5.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
10
|
-
cad_to_dagmc-0.5.0.dist-info/top_level.txt,sha256=zTi8C64SEBsE5WOtPovnxhOzt-E6Oc5nC3RW6M_5aEA,22
|
|
11
|
-
cad_to_dagmc-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|