cad-to-dagmc 0.9.0__py3-none-any.whl → 0.9.2__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/core.py +97 -37
- {cad_to_dagmc-0.9.0.dist-info → cad_to_dagmc-0.9.2.dist-info}/METADATA +5 -14
- cad_to_dagmc-0.9.2.dist-info/RECORD +8 -0
- {cad_to_dagmc-0.9.0.dist-info → cad_to_dagmc-0.9.2.dist-info}/WHEEL +1 -1
- cad_to_dagmc-0.9.0.dist-info/RECORD +0 -8
- {cad_to_dagmc-0.9.0.dist-info → cad_to_dagmc-0.9.2.dist-info}/licenses/LICENSE +0 -0
- {cad_to_dagmc-0.9.0.dist-info → cad_to_dagmc-0.9.2.dist-info}/top_level.txt +0 -0
_version.py
CHANGED
cad_to_dagmc/core.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
+
from typing import Iterable
|
|
2
3
|
import cadquery as cq
|
|
3
4
|
import gmsh
|
|
4
5
|
import numpy as np
|
|
@@ -6,6 +7,7 @@ from cadquery import importers
|
|
|
6
7
|
from pymoab import core, types
|
|
7
8
|
import tempfile
|
|
8
9
|
import warnings
|
|
10
|
+
from typing import Iterable
|
|
9
11
|
from cad_to_dagmc import __version__
|
|
10
12
|
|
|
11
13
|
|
|
@@ -234,15 +236,14 @@ def init_gmsh():
|
|
|
234
236
|
return gmsh
|
|
235
237
|
|
|
236
238
|
|
|
237
|
-
def
|
|
239
|
+
def set_sizes_for_mesh(
|
|
238
240
|
gmsh,
|
|
239
241
|
min_mesh_size: float | None = None,
|
|
240
242
|
max_mesh_size: float | None = None,
|
|
241
243
|
mesh_algorithm: int = 1,
|
|
242
|
-
dimensions: int = 2,
|
|
243
244
|
set_size: dict[int, float] | None = None,
|
|
244
245
|
):
|
|
245
|
-
"""
|
|
246
|
+
"""Sets up the mesh sizes for each volume in the mesh.
|
|
246
247
|
|
|
247
248
|
Args:
|
|
248
249
|
occ_shape: the occ_shape of the Brep file to convert
|
|
@@ -252,8 +253,6 @@ def mesh_brep(
|
|
|
252
253
|
into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
|
|
253
254
|
mesh_algorithm: The Gmsh mesh algorithm number to use. Passed into
|
|
254
255
|
gmsh.option.setNumber("Mesh.Algorithm", mesh_algorithm)
|
|
255
|
-
dimensions: The number of dimensions, 2 for a surface mesh 3 for a
|
|
256
|
-
volume mesh. Passed to gmsh.model.mesh.generate()
|
|
257
256
|
set_size: a dictionary of volume ids (int) and target mesh sizes
|
|
258
257
|
(floats) to set for each volume, passed to gmsh.model.mesh.setSize.
|
|
259
258
|
|
|
@@ -279,25 +278,42 @@ def mesh_brep(
|
|
|
279
278
|
volumes = gmsh.model.getEntities(3)
|
|
280
279
|
available_volumes = [volume[1] for volume in volumes]
|
|
281
280
|
print("volumes", volumes)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
# TODO face specific mesh sizes
|
|
287
|
-
pass
|
|
288
|
-
else:
|
|
289
|
-
boundaries = gmsh.model.getBoundary(
|
|
290
|
-
[(3, volume_id)], recursive=True
|
|
291
|
-
) # dim must be set to 3
|
|
292
|
-
print("boundaries", boundaries)
|
|
293
|
-
gmsh.model.mesh.setSize(boundaries, size)
|
|
294
|
-
print(f"Set size of {size} for volume {volume_id}")
|
|
295
|
-
else:
|
|
281
|
+
|
|
282
|
+
# Ensure all volume IDs in set_size exist in the available volumes
|
|
283
|
+
for volume_id in set_size.keys():
|
|
284
|
+
if volume_id not in available_volumes:
|
|
296
285
|
raise ValueError(
|
|
297
286
|
f"volume ID of {volume_id} set in set_sizes but not found in available volumes {volumes}"
|
|
298
287
|
)
|
|
299
288
|
|
|
300
|
-
|
|
289
|
+
# Step 1: Preprocess boundaries to find shared surfaces and decide mesh sizes
|
|
290
|
+
boundary_sizes = {} # Dictionary to store the mesh size and count for each boundary
|
|
291
|
+
for volume_id, size in set_size.items():
|
|
292
|
+
boundaries = gmsh.model.getBoundary(
|
|
293
|
+
[(3, volume_id)], recursive=True
|
|
294
|
+
) # dim must be set to 3
|
|
295
|
+
print(f"Boundaries for volume {volume_id}: {boundaries}")
|
|
296
|
+
|
|
297
|
+
for boundary in boundaries:
|
|
298
|
+
boundary_key = (boundary[0], boundary[1]) # (dimension, tag)
|
|
299
|
+
if boundary_key in boundary_sizes:
|
|
300
|
+
# If the boundary is already processed, add the size to the list
|
|
301
|
+
boundary_sizes[boundary_key]["total_size"] += size
|
|
302
|
+
boundary_sizes[boundary_key]["count"] += 1
|
|
303
|
+
else:
|
|
304
|
+
# Otherwise, initialize the boundary with the current size
|
|
305
|
+
boundary_sizes[boundary_key] = {"total_size": size, "count": 1}
|
|
306
|
+
|
|
307
|
+
# Step 2: Calculate the average size for each boundary
|
|
308
|
+
averaged_boundary_sizes = {
|
|
309
|
+
boundary: data["total_size"] / data["count"]
|
|
310
|
+
for boundary, data in boundary_sizes.items()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
# Step 3: Apply mesh sizes to all boundaries
|
|
314
|
+
for boundary, size in averaged_boundary_sizes.items():
|
|
315
|
+
gmsh.model.mesh.setSize([boundary], size)
|
|
316
|
+
print(f"Set mesh size {size} for boundary {boundary}")
|
|
301
317
|
|
|
302
318
|
return gmsh
|
|
303
319
|
|
|
@@ -615,11 +631,13 @@ class CadToDagmc:
|
|
|
615
631
|
scale_factor: float = 1.0,
|
|
616
632
|
imprint: bool = True,
|
|
617
633
|
set_size: dict[int, float] | None = None,
|
|
634
|
+
volumes: Iterable[int] | None = None,
|
|
618
635
|
):
|
|
619
636
|
"""
|
|
620
|
-
Exports an unstructured mesh file in VTK format for use with
|
|
621
|
-
Compatible with the MOAB unstructured mesh
|
|
622
|
-
openmc.UnstructuredMesh(filename="umesh.vtk",
|
|
637
|
+
Exports an unstructured mesh file in VTK format for use with
|
|
638
|
+
openmc.UnstructuredMesh. Compatible with the MOAB unstructured mesh
|
|
639
|
+
library. Example useage openmc.UnstructuredMesh(filename="umesh.vtk",
|
|
640
|
+
library="moab").
|
|
623
641
|
|
|
624
642
|
Parameters:
|
|
625
643
|
-----------
|
|
@@ -648,6 +666,8 @@ class CadToDagmc:
|
|
|
648
666
|
and this can save time.
|
|
649
667
|
set_size: a dictionary of volume ids (int) and target mesh sizes
|
|
650
668
|
(floats) to set for each volume, passed to gmsh.model.mesh.setSize.
|
|
669
|
+
volumes: a list of volume ids (int) to include in the mesh. If left
|
|
670
|
+
as default (None) then all volumes will be included.
|
|
651
671
|
|
|
652
672
|
|
|
653
673
|
Returns:
|
|
@@ -672,17 +692,30 @@ class CadToDagmc:
|
|
|
672
692
|
|
|
673
693
|
gmsh = init_gmsh()
|
|
674
694
|
|
|
675
|
-
gmsh,
|
|
695
|
+
gmsh, volumes_in_model = get_volumes(
|
|
696
|
+
gmsh, imprinted_assembly, method=method, scale_factor=scale_factor
|
|
697
|
+
)
|
|
676
698
|
|
|
677
|
-
gmsh =
|
|
699
|
+
gmsh = set_sizes_for_mesh(
|
|
678
700
|
gmsh=gmsh,
|
|
679
701
|
min_mesh_size=min_mesh_size,
|
|
680
702
|
max_mesh_size=max_mesh_size,
|
|
681
703
|
mesh_algorithm=mesh_algorithm,
|
|
682
|
-
dimensions=3,
|
|
683
704
|
set_size=set_size,
|
|
684
705
|
)
|
|
685
706
|
|
|
707
|
+
if volumes:
|
|
708
|
+
for volume_id in volumes_in_model:
|
|
709
|
+
if volume_id[1] not in volumes:
|
|
710
|
+
gmsh.model.occ.remove([volume_id], recursive=True)
|
|
711
|
+
gmsh.option.setNumber("Mesh.SaveAll", 1)
|
|
712
|
+
gmsh.model.occ.synchronize()
|
|
713
|
+
# Clear the mesh
|
|
714
|
+
gmsh.model.mesh.clear()
|
|
715
|
+
gmsh.option.setNumber("Mesh.SaveElementTagType", 3) # Save only volume elements
|
|
716
|
+
|
|
717
|
+
gmsh.model.mesh.generate(3)
|
|
718
|
+
|
|
686
719
|
# makes the folder if it does not exist
|
|
687
720
|
if Path(filename).parent:
|
|
688
721
|
Path(filename).parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -695,7 +728,7 @@ class CadToDagmc:
|
|
|
695
728
|
|
|
696
729
|
gmsh.finalize()
|
|
697
730
|
|
|
698
|
-
return
|
|
731
|
+
return filename
|
|
699
732
|
|
|
700
733
|
def export_gmsh_mesh_file(
|
|
701
734
|
self,
|
|
@@ -751,15 +784,16 @@ class CadToDagmc:
|
|
|
751
784
|
|
|
752
785
|
gmsh, _ = get_volumes(gmsh, imprinted_assembly, method=method, scale_factor=scale_factor)
|
|
753
786
|
|
|
754
|
-
gmsh =
|
|
787
|
+
gmsh = set_sizes_for_mesh(
|
|
755
788
|
gmsh=gmsh,
|
|
756
789
|
min_mesh_size=min_mesh_size,
|
|
757
790
|
max_mesh_size=max_mesh_size,
|
|
758
791
|
mesh_algorithm=mesh_algorithm,
|
|
759
|
-
dimensions=dimensions,
|
|
760
792
|
set_size=set_size,
|
|
761
793
|
)
|
|
762
794
|
|
|
795
|
+
gmsh.model.mesh.generate(dimensions)
|
|
796
|
+
|
|
763
797
|
# makes the folder if it does not exist
|
|
764
798
|
if Path(filename).parent:
|
|
765
799
|
Path(filename).parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -785,6 +819,8 @@ class CadToDagmc:
|
|
|
785
819
|
scale_factor: float = 1.0,
|
|
786
820
|
imprint: bool = True,
|
|
787
821
|
set_size: dict[int, float] | None = None,
|
|
822
|
+
unstructured_volumes: Iterable[int] | None = None,
|
|
823
|
+
umesh_filename: str = "umesh.vtk",
|
|
788
824
|
) -> str:
|
|
789
825
|
"""Saves a DAGMC h5m file of the geometry
|
|
790
826
|
|
|
@@ -813,9 +849,13 @@ class CadToDagmc:
|
|
|
813
849
|
and this can save time.
|
|
814
850
|
set_size: a dictionary of volume ids (int) and target mesh sizes
|
|
815
851
|
(floats) to set for each volume, passed to gmsh.model.mesh.setSize.
|
|
852
|
+
unstructured_volumes: a list of volume ids to be saved in as an
|
|
853
|
+
unstructured mesh file.
|
|
854
|
+
umesh_filename: the filename to use for the optional unstructured
|
|
855
|
+
mesh file. Only used if unstructured_volumes is not empty.
|
|
816
856
|
|
|
817
857
|
Returns:
|
|
818
|
-
str: the
|
|
858
|
+
str: the filenames(s) for the files created.
|
|
819
859
|
"""
|
|
820
860
|
|
|
821
861
|
assembly = cq.Assembly()
|
|
@@ -852,7 +892,7 @@ class CadToDagmc:
|
|
|
852
892
|
gmsh, imprinted_assembly, method=method, scale_factor=scale_factor
|
|
853
893
|
)
|
|
854
894
|
|
|
855
|
-
gmsh =
|
|
895
|
+
gmsh = set_sizes_for_mesh(
|
|
856
896
|
gmsh=gmsh,
|
|
857
897
|
min_mesh_size=min_mesh_size,
|
|
858
898
|
max_mesh_size=max_mesh_size,
|
|
@@ -860,19 +900,39 @@ class CadToDagmc:
|
|
|
860
900
|
set_size=set_size,
|
|
861
901
|
)
|
|
862
902
|
|
|
863
|
-
|
|
903
|
+
gmsh.model.mesh.generate(2)
|
|
864
904
|
|
|
865
905
|
vertices, triangles_by_solid_by_face = mesh_to_vertices_and_triangles(
|
|
866
|
-
dims_and_vol_ids=
|
|
906
|
+
dims_and_vol_ids=volumes
|
|
867
907
|
)
|
|
868
908
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
# checks and fixes triangle fix_normals within vertices_to_h5m
|
|
872
|
-
return vertices_to_h5m(
|
|
909
|
+
dagmc_filename = vertices_to_h5m(
|
|
873
910
|
vertices=vertices,
|
|
874
911
|
triangles_by_solid_by_face=triangles_by_solid_by_face,
|
|
875
912
|
material_tags=material_tags_in_brep_order,
|
|
876
913
|
h5m_filename=filename,
|
|
877
914
|
implicit_complement_material_tag=implicit_complement_material_tag,
|
|
878
915
|
)
|
|
916
|
+
|
|
917
|
+
if unstructured_volumes:
|
|
918
|
+
# remove all the unused occ volumes, this prevents them being meshed
|
|
919
|
+
for volume_dim, volume_id in volumes:
|
|
920
|
+
if volume_id not in unstructured_volumes:
|
|
921
|
+
gmsh.model.occ.remove([(volume_dim, volume_id)], recursive=True)
|
|
922
|
+
gmsh.option.setNumber("Mesh.SaveAll", 1)
|
|
923
|
+
gmsh.model.occ.synchronize()
|
|
924
|
+
|
|
925
|
+
# removes all the 2D groups so that 2D faces are not included in the vtk file
|
|
926
|
+
all_2d_groups = gmsh.model.getPhysicalGroups(2)
|
|
927
|
+
for entry in all_2d_groups:
|
|
928
|
+
gmsh.model.removePhysicalGroups([entry])
|
|
929
|
+
|
|
930
|
+
gmsh.model.mesh.generate(3)
|
|
931
|
+
gmsh.option.setNumber("Mesh.SaveElementTagType", 3) # Save only volume elements
|
|
932
|
+
gmsh.write(umesh_filename)
|
|
933
|
+
|
|
934
|
+
gmsh.finalize()
|
|
935
|
+
|
|
936
|
+
return dagmc_filename, umesh_filename
|
|
937
|
+
else:
|
|
938
|
+
return dagmc_filename
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cad_to_dagmc
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: Converts CAD files to a DAGMC h5m file
|
|
5
5
|
Author-email: Jonathan Shimwell <mail@jshimwell.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/fusion-energy/cad_to_dagmc
|
|
@@ -55,6 +55,8 @@ Cad-to-dagmc offers a wide range of features including.
|
|
|
55
55
|
- Geometry scaling with ```scale_factor``` argument
|
|
56
56
|
- Model wide mesh size parameters with ```min_mesh_size``` and ```max_mesh_size``` arguments
|
|
57
57
|
- Volume specific mesh sizing parameters with the ```set_size``` argument
|
|
58
|
+
- Unstructured mesh that share the same coordinates as the surface mesh.
|
|
59
|
+
- Volume mesh allows selecting individual volumes in the geometry.
|
|
58
60
|
- Parallel meshing to quickly mesh the geometry using multiple CPU cores
|
|
59
61
|
- Imprint and merging of CAD geometry, or disable with the ```imprint``` argument
|
|
60
62
|
- Add geometry from multiple sources ([STEP](http://www.steptools.com/stds/step/) files, [CadQuery](https://cadquery.readthedocs.io) objects and [Gmsh](https://gmsh.info/) meshes)
|
|
@@ -130,21 +132,10 @@ First ensure hdf5 is installed as this is needed by MOAB pip install command
|
|
|
130
132
|
sudo apt-get install libhdf5-dev
|
|
131
133
|
```
|
|
132
134
|
|
|
133
|
-
Then
|
|
135
|
+
Then install MOAB, currently available from the repo.
|
|
134
136
|
|
|
135
137
|
```
|
|
136
|
-
|
|
137
|
-
cd moab
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Ensure pip is up to date as a new version is needed
|
|
141
|
-
```
|
|
142
|
-
python -m pip install --upgrade pip
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Run the pip install command with cmake arguments.
|
|
146
|
-
```
|
|
147
|
-
pip install . --config-settings=cmake.args=-DENABLE_HDF5=ON
|
|
138
|
+
pip install git+https://bitbucket.org/fathomteam/moab/
|
|
148
139
|
```
|
|
149
140
|
|
|
150
141
|
Then you can install the cad_to_dagmc package with ```pip```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
_version.py,sha256=eeYYTSIkrgfRwSQ7LKo_py3xs3DvzgfWiAtK4K1JM4A,511
|
|
2
|
+
cad_to_dagmc/__init__.py,sha256=fskHUTyCunSpnpJUvBfAYjx4uwDKXHTTiMP6GqnFRf0,494
|
|
3
|
+
cad_to_dagmc/core.py,sha256=dGj5LRRzboQ8CL8VS5dkvIkGLyj5MJWcbkTPtrFk0QQ,36947
|
|
4
|
+
cad_to_dagmc-0.9.2.dist-info/licenses/LICENSE,sha256=B8kznH_777JVNZ3HOKDc4Tj24F7wJ68ledaNYeL9sCw,1070
|
|
5
|
+
cad_to_dagmc-0.9.2.dist-info/METADATA,sha256=8vLnV93ycmV216LiNj38YI4z445pWtdpBKpcESFLLH0,8990
|
|
6
|
+
cad_to_dagmc-0.9.2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
7
|
+
cad_to_dagmc-0.9.2.dist-info/top_level.txt,sha256=zTi8C64SEBsE5WOtPovnxhOzt-E6Oc5nC3RW6M_5aEA,22
|
|
8
|
+
cad_to_dagmc-0.9.2.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
_version.py,sha256=fqtOm8q4HIqAgc-mXbjsKoz34kMK1y3t9LDhc4497WE,511
|
|
2
|
-
cad_to_dagmc/__init__.py,sha256=fskHUTyCunSpnpJUvBfAYjx4uwDKXHTTiMP6GqnFRf0,494
|
|
3
|
-
cad_to_dagmc/core.py,sha256=C3NEy5z4bjbg0SQjodGcZSOVqMAc8g5e0zLoF2gs0Og,34140
|
|
4
|
-
cad_to_dagmc-0.9.0.dist-info/licenses/LICENSE,sha256=B8kznH_777JVNZ3HOKDc4Tj24F7wJ68ledaNYeL9sCw,1070
|
|
5
|
-
cad_to_dagmc-0.9.0.dist-info/METADATA,sha256=J3Q4BXSU_ApF86K8sjDXA_hYT_k5GRRAKXaYc-ksbuw,9092
|
|
6
|
-
cad_to_dagmc-0.9.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
7
|
-
cad_to_dagmc-0.9.0.dist-info/top_level.txt,sha256=zTi8C64SEBsE5WOtPovnxhOzt-E6Oc5nC3RW6M_5aEA,22
|
|
8
|
-
cad_to_dagmc-0.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|