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 CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.9.0'
21
- __version_tuple__ = version_tuple = (0, 9, 0)
20
+ __version__ = version = '0.9.2'
21
+ __version_tuple__ = version_tuple = (0, 9, 2)
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 mesh_brep(
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
- """Creates a conformal surface meshes of the volumes in a Brep file using Gmsh.
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
- for volume_id, size in set_size.items():
283
- if volume_id in available_volumes:
284
- size = set_size[volume_id]
285
- if isinstance(size, dict):
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
- gmsh.model.mesh.generate(dimensions)
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 openmc.UnstructuredMesh.
621
- Compatible with the MOAB unstructured mesh library. Example useage
622
- openmc.UnstructuredMesh(filename="umesh.vtk", library="moab")
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, _ = get_volumes(gmsh, imprinted_assembly, method=method, scale_factor=scale_factor)
695
+ gmsh, volumes_in_model = get_volumes(
696
+ gmsh, imprinted_assembly, method=method, scale_factor=scale_factor
697
+ )
676
698
 
677
- gmsh = mesh_brep(
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 gmsh
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 = mesh_brep(
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 DAGMC filename saved
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 = mesh_brep(
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
- dims_and_vol_ids = volumes
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=dims_and_vol_ids
906
+ dims_and_vol_ids=volumes
867
907
  )
868
908
 
869
- gmsh.finalize()
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.0
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 clone the latest version of MOAB and cd into the moab directory.
135
+ Then install MOAB, currently available from the repo.
134
136
 
135
137
  ```
136
- git clone master https://bitbucket.org/fathomteam/moab/
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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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,,