cad-to-dagmc 0.9.0__tar.gz → 0.9.1__tar.gz

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.

Files changed (62) hide show
  1. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/.github/workflows/ci_with_benchmarks.yml +28 -14
  2. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/.github/workflows/ci_with_conda_install.yml +20 -11
  3. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/PKG-INFO +4 -14
  4. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/README.md +3 -13
  5. cad_to_dagmc-0.9.1/examples/surface_and_unstructured_mesh/unstructured_mesh_with_conformal_surface_mesh.py +107 -0
  6. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/from_gmsh_object_with_tag.py +1 -1
  7. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/_version.py +2 -2
  8. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc/core.py +65 -30
  9. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc.egg-info/PKG-INFO +4 -14
  10. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc.egg-info/SOURCES.txt +1 -0
  11. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_h5m_in_transport.py +46 -2
  12. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_mesh_to_dagmc.py +3 -3
  13. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_python_api.py +53 -0
  14. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/.github/workflows/black.yml +0 -0
  15. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/.github/workflows/ci_with_pip_install.yml +0 -0
  16. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/.github/workflows/python-publish.yml +0 -0
  17. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/.gitignore +0 -0
  18. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/CITATION.cff +0 -0
  19. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/LICENSE +0 -0
  20. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/cadquery_assembly.py +0 -0
  21. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/cadquery_assembly_with_scaled_geometry.py +0 -0
  22. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/cadquery_compound.py +0 -0
  23. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/cadquery_object_and_stp_file.py +0 -0
  24. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/cadquery_text.py +0 -0
  25. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/curved_cadquery_object_to_dagmc_surface_mesh.py +0 -0
  26. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/different_resolution_meshes.py +0 -0
  27. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/from_gmsh_mesh_file.py +0 -0
  28. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/from_gmsh_mesh_file_with_tags.py +0 -0
  29. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/multiple_cadquery_objects.py +0 -0
  30. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/multiple_stp_files.py +0 -0
  31. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/single_cadquery_object.py +0 -0
  32. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/single_stp_file.py +0 -0
  33. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/single_stp_file_multiple_volumes.py +0 -0
  34. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/surface_mesh/tagged_mesh.msh +0 -0
  35. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/unstrucutred_volume_mesh/curved_cadquery_object_to_dagmc_volume_mesh.py +0 -0
  36. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/unstrucutred_volume_mesh/different_resolution_meshes.py +0 -0
  37. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/examples/unstrucutred_volume_mesh/simulate_unstrucutred_volume_mesh_with_openmc.py +0 -0
  38. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/pyproject.toml +0 -0
  39. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/setup.cfg +0 -0
  40. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc/__init__.py +0 -0
  41. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc.egg-info/dependency_links.txt +0 -0
  42. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc.egg-info/requires.txt +0 -0
  43. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/src/cad_to_dagmc.egg-info/top_level.txt +0 -0
  44. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/ENDFB-7.1-NNDC_H1.h5 +0 -0
  45. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/ball_reactor.brep +0 -0
  46. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/curved_extrude.stp +0 -0
  47. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/extrude_rectangle.stp +0 -0
  48. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/multi_volume_cylinders.stp +0 -0
  49. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/one_cube.brep +0 -0
  50. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/single_cube.stp +0 -0
  51. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/single_volume_thin.stp +0 -0
  52. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/single_volume_thin.vtk +0 -0
  53. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/tagged_mesh.msh +0 -0
  54. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_brep_file.brep +0 -0
  55. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_file_creation.py +0 -0
  56. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_get_volumes.py +0 -0
  57. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_loading_from_file_vs_shape_object.py +0 -0
  58. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_two_joined_cubes.brep +0 -0
  59. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_two_sep_cubes.brep +0 -0
  60. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/test_version.py +0 -0
  61. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/two_connected_cubes.stp +0 -0
  62. {cad_to_dagmc-0.9.0 → cad_to_dagmc-0.9.1}/tests/two_disconnected_cubes.stp +0 -0
@@ -19,25 +19,42 @@ on:
19
19
  jobs:
20
20
  testing:
21
21
  runs-on: ubuntu-latest
22
+
22
23
  steps:
23
24
  - name: Checkout repository
24
25
  uses: actions/checkout@v4
25
26
 
26
- - name: install dependencies and run CSG / DAMGC benchmarks
27
- env:
28
- OPENMC_CROSS_SECTIONS: /home/runner/work/cad_to_dagmc/cad_to_dagmc/cross_sections.xml
29
- shell: bash
27
+ - name: Install system packages
30
28
  run: |
31
- wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
32
- bash Miniforge3.sh -b -p "${HOME}/conda"
33
- source "${HOME}/conda/etc/profile.d/conda.sh"
34
- source "${HOME}/conda/etc/profile.d/mamba.sh"
35
- sudo apt-get --allow-releaseinfo-change update
36
29
  sudo apt-get update -y
37
30
  sudo apt-get upgrade -y
38
31
  sudo apt-get install -y libgl1 libglx-mesa0 libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev libosmesa6 libosmesa6-dev libgles2-mesa-dev libarchive-dev libpangocairo-1.0-0
39
- mamba activate
40
- mamba install -y -c conda-forge "openmc=0.15.0=dagmc*nompi*" trimesh networkx cadquery gmsh python-gmsh
32
+
33
+ - name: Set up Miniforge
34
+ run: |
35
+ wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-$(uname -m).sh"
36
+ bash Miniforge3.sh -b -p "${HOME}/miniforge"
37
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
38
+ conda init bash
39
+ conda config --set always_yes yes --set changeps1 no
40
+ conda update -q conda
41
+
42
+ - name: Create and activate Conda environment
43
+ run: |
44
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
45
+ conda create -n ci-env python=3.11
46
+ conda activate ci-env
47
+ conda install -c conda-forge "openmc=0.15.0=dagmc*nompi*" trimesh networkx cadquery gmsh python-gmsh vtk
48
+ python -m pip install .[tests]
49
+ python -m pip install git+https://github.com/svalinn/pydagmc
50
+
51
+ - name: Run tests
52
+ shell: bash -l {0}
53
+ env:
54
+ OPENMC_CROSS_SECTIONS: /home/runner/work/cad_to_dagmc/cad_to_dagmc/cross_sections.xml
55
+ run: |
56
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
57
+ conda activate ci-env
41
58
  python -m ensurepip --upgrade
42
59
  python -m pip install . --no-deps
43
60
  python -m pip install openmc_data_downloader
@@ -45,7 +62,4 @@ jobs:
45
62
  git clone --single-branch -b main --depth 1 https://github.com/fusion-energy/model_benchmark_zoo.git
46
63
  cd model_benchmark_zoo
47
64
  python -m pip install .[tests]
48
- pip install git+https://github.com/svalinn/pydagmc
49
- conda env export > environment.yml
50
- cat environment.yml
51
65
  pytest tests/test_cad_to_dagmc -v
@@ -31,34 +31,43 @@ jobs:
31
31
  sudo apt-get update -y
32
32
  sudo apt-get upgrade -y
33
33
  sudo apt-get install -y libgl1 libglx-mesa0 libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev libosmesa6 libosmesa6-dev libgles2-mesa-dev libarchive-dev libpangocairo-1.0-0
34
+ - name: Set up Miniforge
35
+ run: |
36
+ wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-$(uname -m).sh"
37
+ bash Miniforge3.sh -b -p "${HOME}/miniforge"
38
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
39
+ conda init bash
40
+ conda config --set always_yes yes --set changeps1 no
41
+ conda update -q conda
34
42
 
35
- - name: Set up Conda
36
- uses: conda-incubator/setup-miniconda@v2
37
- with:
38
- activate-environment: ci-env
39
- miniforge-version: latest
40
- channels: conda-forge
41
-
42
- - name: install dependencies
43
- shell: bash -l {0}
43
+ - name: Create and activate Conda environment
44
44
  run: |
45
- conda install -y -c conda-forge "openmc=0.15.0=dagmc*nompi*" trimesh networkx cadquery gmsh python-gmsh vtk
45
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
46
+ conda create -n ci-env python=3.11
47
+ conda activate ci-env
48
+ conda install -c conda-forge "openmc=0.15.0=dagmc*nompi*" trimesh networkx cadquery gmsh python-gmsh vtk
46
49
  python -m pip install .[tests]
47
50
  python -m pip install git+https://github.com/svalinn/pydagmc
48
-
51
+
49
52
  - name: Test import
50
53
  shell: bash -l {0}
51
54
  run: |
55
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
56
+ conda activate ci-env
52
57
  python -c "import cad_to_dagmc"
53
58
 
54
59
  - name: Run tests
55
60
  shell: bash -l {0}
56
61
  run: |
62
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
63
+ conda activate ci-env
57
64
  pytest -v tests
58
65
 
59
66
  - name: Run examples
60
67
  shell: bash -l {0}
61
68
  run: |
69
+ source "${HOME}/miniforge/etc/profile.d/conda.sh"
70
+ conda activate ci-env
62
71
  python examples/surface_mesh/cadquery_assembly.py
63
72
  python examples/surface_mesh/cadquery_assembly_with_scaled_geometry.py
64
73
  python examples/surface_mesh/cadquery_compound.py
@@ -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.1
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,7 @@ 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
+ - Volume mesh selected volumes in the geometry (helps ensure conformal volume and surface mesh).
58
59
  - Parallel meshing to quickly mesh the geometry using multiple CPU cores
59
60
  - Imprint and merging of CAD geometry, or disable with the ```imprint``` argument
60
61
  - 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 +131,10 @@ First ensure hdf5 is installed as this is needed by MOAB pip install command
130
131
  sudo apt-get install libhdf5-dev
131
132
  ```
132
133
 
133
- Then clone the latest version of MOAB and cd into the moab directory.
134
+ Then install MOAB, currently available from the repo.
134
135
 
135
136
  ```
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
137
+ pip install git+https://bitbucket.org/fathomteam/moab/
148
138
  ```
149
139
 
150
140
  Then you can install the cad_to_dagmc package with ```pip```
@@ -30,6 +30,7 @@ Cad-to-dagmc offers a wide range of features including.
30
30
  - Geometry scaling with ```scale_factor``` argument
31
31
  - Model wide mesh size parameters with ```min_mesh_size``` and ```max_mesh_size``` arguments
32
32
  - Volume specific mesh sizing parameters with the ```set_size``` argument
33
+ - Volume mesh selected volumes in the geometry (helps ensure conformal volume and surface mesh).
33
34
  - Parallel meshing to quickly mesh the geometry using multiple CPU cores
34
35
  - Imprint and merging of CAD geometry, or disable with the ```imprint``` argument
35
36
  - 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)
@@ -105,21 +106,10 @@ First ensure hdf5 is installed as this is needed by MOAB pip install command
105
106
  sudo apt-get install libhdf5-dev
106
107
  ```
107
108
 
108
- Then clone the latest version of MOAB and cd into the moab directory.
109
+ Then install MOAB, currently available from the repo.
109
110
 
110
111
  ```
111
- git clone master https://bitbucket.org/fathomteam/moab/
112
- cd moab
113
- ```
114
-
115
- Ensure pip is up to date as a new version is needed
116
- ```
117
- python -m pip install --upgrade pip
118
- ```
119
-
120
- Run the pip install command with cmake arguments.
121
- ```
122
- pip install . --config-settings=cmake.args=-DENABLE_HDF5=ON
112
+ pip install git+https://bitbucket.org/fathomteam/moab/
123
113
  ```
124
114
 
125
115
  Then you can install the cad_to_dagmc package with ```pip```
@@ -0,0 +1,107 @@
1
+ # This example makes 3 CAD half spheres
2
+ # Meshes the 3 volumes with different resolutions
3
+ # exports the mesh to a DAGMC unstructured VTK file and a DAGMC h5m file
4
+ # The outer surface of the volume mesh should match the surface of the surface
5
+ # mesh as the same mesh parameters were used in both the surface and volume mesh.
6
+ # Additionally only volume 2 is volume meshed, while all three volumes are surface meshed
7
+
8
+
9
+ import cadquery as cq
10
+ from cad_to_dagmc import CadToDagmc
11
+
12
+ box_cutter = cq.Workplane("XY").moveTo(0, 5).box(20, 10, 20)
13
+ inner_sphere = cq.Workplane("XY").sphere(6).cut(box_cutter)
14
+ middle_sphere = cq.Workplane("XY").sphere(6.1).cut(box_cutter).cut(inner_sphere)
15
+ outer_sphere = cq.Workplane("XY").sphere(10).cut(box_cutter).cut(inner_sphere).cut(middle_sphere)
16
+
17
+ assembly = cq.Assembly()
18
+ assembly.add(inner_sphere, name="inner_sphere")
19
+ assembly.add(middle_sphere, name="middle_sphere")
20
+ assembly.add(outer_sphere, name="outer_sphere")
21
+
22
+
23
+ model = CadToDagmc()
24
+ model.add_cadquery_object(assembly, material_tags=["mat1", "mat2", "mat3"])
25
+
26
+
27
+ h5m_file = model.export_dagmc_h5m_file(
28
+ filename="different_resolution_meshes.h5m",
29
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
30
+ )
31
+
32
+ vtk_file = model.export_unstructured_mesh_file(
33
+ filename="umesh.vtk",
34
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
35
+ volumes=[2], # only mesh volume 2 out of the three volumes
36
+ )
37
+
38
+
39
+ import openmc
40
+
41
+ with open("cross_sections.xml", "w") as file:
42
+ file.write(
43
+ """
44
+ <?xml version='1.0' encoding='UTF-8'?>
45
+ <cross_sections>
46
+ <library materials="H1" path="tests/ENDFB-7.1-NNDC_H1.h5" type="neutron"/>
47
+ </cross_sections>
48
+ """
49
+ )
50
+ openmc.config["cross_sections"] = "cross_sections.xml"
51
+
52
+ umesh = openmc.UnstructuredMesh(vtk_file, library="moab")
53
+ mesh_filter = openmc.MeshFilter(umesh)
54
+ tally = openmc.Tally(name="unstructured_mesh_tally")
55
+ tally.filters = [mesh_filter]
56
+ tally.scores = ["flux"]
57
+ my_tallies = openmc.Tallies([tally])
58
+
59
+
60
+ mat1 = openmc.Material(name="mat1")
61
+ mat1.add_nuclide("H1", 1, percent_type="ao")
62
+ mat1.set_density("g/cm3", 0.001)
63
+ mat2 = openmc.Material(name="mat2")
64
+ mat2.add_nuclide("H1", 1, percent_type="ao")
65
+ mat2.set_density("g/cm3", 0.002)
66
+ mat3 = openmc.Material(name="mat3")
67
+ mat3.add_nuclide("H1", 1, percent_type="ao")
68
+ mat3.set_density("g/cm3", 0.003)
69
+ my_materials = openmc.Materials([mat1, mat2, mat3])
70
+
71
+ dag_univ = openmc.DAGMCUniverse(filename=h5m_file)
72
+ bound_dag_univ = dag_univ.bounded_universe()
73
+ my_geometry = openmc.Geometry(root=bound_dag_univ)
74
+
75
+
76
+ my_settings = openmc.Settings()
77
+ my_settings.batches = 10
78
+ my_settings.particles = 5000
79
+ my_settings.run_mode = "fixed source"
80
+
81
+ # Create a DT point source
82
+ my_source = openmc.IndependentSource()
83
+ my_source.space = openmc.stats.Point(my_geometry.bounding_box.center)
84
+ my_source.angle = openmc.stats.Isotropic()
85
+ my_source.energy = openmc.stats.Discrete([14e6], [1])
86
+ my_settings.source = my_source
87
+
88
+ model = openmc.model.Model(my_geometry, my_materials, my_settings, my_tallies)
89
+ sp_filename = model.run()
90
+
91
+ sp = openmc.StatePoint(sp_filename)
92
+
93
+ tally_result = sp.get_tally(name="unstructured_mesh_tally")
94
+
95
+ # normally with regular meshes I would get the mesh from the tally
96
+ # but with unstructured meshes the tally does not contain the mesh
97
+ # however we can get it from the statepoint file
98
+ # umesh = tally_result.find_filter(openmc.MeshFilter)
99
+ umesh_from_sp = sp.meshes[1]
100
+
101
+ # these trigger internal code in the mesh object so that its centroids and volumes become known.
102
+ # centroids and volumes are needed for the get_values and write_data_to_vtk steps
103
+ centroids = umesh_from_sp.centroids
104
+ mesh_vols = umesh_from_sp.volumes
105
+
106
+ flux_mean = tally_result.get_values(scores=["flux"], value="mean").reshape(umesh_from_sp.dimension)
107
+ umesh_from_sp.write_data_to_vtk(filename="tally.vtk", datasets={"mean": flux_mean})
@@ -1,7 +1,7 @@
1
1
  import cadquery as cq
2
2
  import cad_to_dagmc
3
3
  import gmsh
4
- import assembly_mesh_plugin.plugin
4
+ import assembly_mesh_plugin
5
5
 
6
6
  box_shape1 = cq.Workplane("XY").box(50, 50, 50)
7
7
  box_shape2 = cq.Workplane("XY").moveTo(0, 50).box(50, 50, 100)
@@ -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.1'
21
+ __version_tuple__ = version_tuple = (0, 9, 1)
@@ -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
@@ -234,15 +235,14 @@ def init_gmsh():
234
235
  return gmsh
235
236
 
236
237
 
237
- def mesh_brep(
238
+ def set_sizes_for_mesh(
238
239
  gmsh,
239
240
  min_mesh_size: float | None = None,
240
241
  max_mesh_size: float | None = None,
241
242
  mesh_algorithm: int = 1,
242
- dimensions: int = 2,
243
243
  set_size: dict[int, float] | None = None,
244
244
  ):
245
- """Creates a conformal surface meshes of the volumes in a Brep file using Gmsh.
245
+ """Sets up the mesh sizes for each volume in the mesh.
246
246
 
247
247
  Args:
248
248
  occ_shape: the occ_shape of the Brep file to convert
@@ -252,8 +252,6 @@ def mesh_brep(
252
252
  into gmsh.option.setNumber("Mesh.MeshSizeMax", max_mesh_size)
253
253
  mesh_algorithm: The Gmsh mesh algorithm number to use. Passed into
254
254
  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
255
  set_size: a dictionary of volume ids (int) and target mesh sizes
258
256
  (floats) to set for each volume, passed to gmsh.model.mesh.setSize.
259
257
 
@@ -279,25 +277,42 @@ def mesh_brep(
279
277
  volumes = gmsh.model.getEntities(3)
280
278
  available_volumes = [volume[1] for volume in volumes]
281
279
  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:
280
+
281
+ # Ensure all volume IDs in set_size exist in the available volumes
282
+ for volume_id in set_size.keys():
283
+ if volume_id not in available_volumes:
296
284
  raise ValueError(
297
285
  f"volume ID of {volume_id} set in set_sizes but not found in available volumes {volumes}"
298
286
  )
299
287
 
300
- gmsh.model.mesh.generate(dimensions)
288
+ # Step 1: Preprocess boundaries to find shared surfaces and decide mesh sizes
289
+ boundary_sizes = {} # Dictionary to store the mesh size and count for each boundary
290
+ for volume_id, size in set_size.items():
291
+ boundaries = gmsh.model.getBoundary(
292
+ [(3, volume_id)], recursive=True
293
+ ) # dim must be set to 3
294
+ print(f"Boundaries for volume {volume_id}: {boundaries}")
295
+
296
+ for boundary in boundaries:
297
+ boundary_key = (boundary[0], boundary[1]) # (dimension, tag)
298
+ if boundary_key in boundary_sizes:
299
+ # If the boundary is already processed, add the size to the list
300
+ boundary_sizes[boundary_key]["total_size"] += size
301
+ boundary_sizes[boundary_key]["count"] += 1
302
+ else:
303
+ # Otherwise, initialize the boundary with the current size
304
+ boundary_sizes[boundary_key] = {"total_size": size, "count": 1}
305
+
306
+ # Step 2: Calculate the average size for each boundary
307
+ averaged_boundary_sizes = {
308
+ boundary: data["total_size"] / data["count"]
309
+ for boundary, data in boundary_sizes.items()
310
+ }
311
+
312
+ # Step 3: Apply mesh sizes to all boundaries
313
+ for boundary, size in averaged_boundary_sizes.items():
314
+ gmsh.model.mesh.setSize([boundary], size)
315
+ print(f"Set mesh size {size} for boundary {boundary}")
301
316
 
302
317
  return gmsh
303
318
 
@@ -615,11 +630,13 @@ class CadToDagmc:
615
630
  scale_factor: float = 1.0,
616
631
  imprint: bool = True,
617
632
  set_size: dict[int, float] | None = None,
633
+ volumes: Iterable[int] | None = None,
618
634
  ):
619
635
  """
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")
636
+ Exports an unstructured mesh file in VTK format for use with
637
+ openmc.UnstructuredMesh. Compatible with the MOAB unstructured mesh
638
+ library. Example useage openmc.UnstructuredMesh(filename="umesh.vtk",
639
+ library="moab").
623
640
 
624
641
  Parameters:
625
642
  -----------
@@ -648,6 +665,8 @@ class CadToDagmc:
648
665
  and this can save time.
649
666
  set_size: a dictionary of volume ids (int) and target mesh sizes
650
667
  (floats) to set for each volume, passed to gmsh.model.mesh.setSize.
668
+ volumes: a list of volume ids (int) to include in the mesh. If left
669
+ as default (None) then all volumes will be included.
651
670
 
652
671
 
653
672
  Returns:
@@ -672,17 +691,30 @@ class CadToDagmc:
672
691
 
673
692
  gmsh = init_gmsh()
674
693
 
675
- gmsh, _ = get_volumes(gmsh, imprinted_assembly, method=method, scale_factor=scale_factor)
694
+ gmsh, volumes_in_model = get_volumes(
695
+ gmsh, imprinted_assembly, method=method, scale_factor=scale_factor
696
+ )
676
697
 
677
- gmsh = mesh_brep(
698
+ gmsh = set_sizes_for_mesh(
678
699
  gmsh=gmsh,
679
700
  min_mesh_size=min_mesh_size,
680
701
  max_mesh_size=max_mesh_size,
681
702
  mesh_algorithm=mesh_algorithm,
682
- dimensions=3,
683
703
  set_size=set_size,
684
704
  )
685
705
 
706
+ if volumes:
707
+ for volume_id in volumes_in_model:
708
+ if volume_id[1] not in volumes:
709
+ gmsh.model.occ.remove([volume_id], recursive=True)
710
+ gmsh.option.setNumber("Mesh.SaveAll", 1)
711
+ gmsh.model.occ.synchronize()
712
+ # Clear the mesh
713
+ gmsh.model.mesh.clear()
714
+ gmsh.option.setNumber("Mesh.SaveElementTagType", 3) # Save only volume elements
715
+
716
+ gmsh.model.mesh.generate(3)
717
+
686
718
  # makes the folder if it does not exist
687
719
  if Path(filename).parent:
688
720
  Path(filename).parent.mkdir(parents=True, exist_ok=True)
@@ -695,7 +727,7 @@ class CadToDagmc:
695
727
 
696
728
  gmsh.finalize()
697
729
 
698
- return gmsh
730
+ return filename
699
731
 
700
732
  def export_gmsh_mesh_file(
701
733
  self,
@@ -751,15 +783,16 @@ class CadToDagmc:
751
783
 
752
784
  gmsh, _ = get_volumes(gmsh, imprinted_assembly, method=method, scale_factor=scale_factor)
753
785
 
754
- gmsh = mesh_brep(
786
+ gmsh = set_sizes_for_mesh(
755
787
  gmsh=gmsh,
756
788
  min_mesh_size=min_mesh_size,
757
789
  max_mesh_size=max_mesh_size,
758
790
  mesh_algorithm=mesh_algorithm,
759
- dimensions=dimensions,
760
791
  set_size=set_size,
761
792
  )
762
793
 
794
+ gmsh.model.mesh.generate(dimensions)
795
+
763
796
  # makes the folder if it does not exist
764
797
  if Path(filename).parent:
765
798
  Path(filename).parent.mkdir(parents=True, exist_ok=True)
@@ -852,7 +885,7 @@ class CadToDagmc:
852
885
  gmsh, imprinted_assembly, method=method, scale_factor=scale_factor
853
886
  )
854
887
 
855
- gmsh = mesh_brep(
888
+ gmsh = set_sizes_for_mesh(
856
889
  gmsh=gmsh,
857
890
  min_mesh_size=min_mesh_size,
858
891
  max_mesh_size=max_mesh_size,
@@ -860,6 +893,8 @@ class CadToDagmc:
860
893
  set_size=set_size,
861
894
  )
862
895
 
896
+ gmsh.model.mesh.generate(2)
897
+
863
898
  dims_and_vol_ids = volumes
864
899
 
865
900
  vertices, triangles_by_solid_by_face = mesh_to_vertices_and_triangles(
@@ -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.1
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,7 @@ 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
+ - Volume mesh selected volumes in the geometry (helps ensure conformal volume and surface mesh).
58
59
  - Parallel meshing to quickly mesh the geometry using multiple CPU cores
59
60
  - Imprint and merging of CAD geometry, or disable with the ```imprint``` argument
60
61
  - 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 +131,10 @@ First ensure hdf5 is installed as this is needed by MOAB pip install command
130
131
  sudo apt-get install libhdf5-dev
131
132
  ```
132
133
 
133
- Then clone the latest version of MOAB and cd into the moab directory.
134
+ Then install MOAB, currently available from the repo.
134
135
 
135
136
  ```
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
137
+ pip install git+https://bitbucket.org/fathomteam/moab/
148
138
  ```
149
139
 
150
140
  Then you can install the cad_to_dagmc package with ```pip```
@@ -8,6 +8,7 @@ pyproject.toml
8
8
  .github/workflows/ci_with_conda_install.yml
9
9
  .github/workflows/ci_with_pip_install.yml
10
10
  .github/workflows/python-publish.yml
11
+ examples/surface_and_unstructured_mesh/unstructured_mesh_with_conformal_surface_mesh.py
11
12
  examples/surface_mesh/cadquery_assembly.py
12
13
  examples/surface_mesh/cadquery_assembly_with_scaled_geometry.py
13
14
  examples/surface_mesh/cadquery_compound.py
@@ -22,6 +22,7 @@ def transport_particles_on_h5m_geometry(
22
22
  material_tags: list,
23
23
  nuclides: list = None,
24
24
  cross_sections_xml: str = None,
25
+ vtk_filename: str = None,
25
26
  ):
26
27
  """A function for testing the geometry file with particle transport in
27
28
  DAGMC OpenMC. Requires openmc and either the cross_sections_xml to be
@@ -102,10 +103,16 @@ def transport_particles_on_h5m_geometry(
102
103
  # adds a tally to record the heat deposited in entire geometry
103
104
  cell_tally = openmc.Tally(name="flux")
104
105
  cell_tally.scores = ["flux"]
105
-
106
- # groups the two tallies
107
106
  tallies = openmc.Tallies([cell_tally])
108
107
 
108
+ if vtk_filename:
109
+ umesh_tally = openmc.Tally(name="unstructured_mesh_tally")
110
+ umesh = openmc.UnstructuredMesh(vtk_filename, library="moab")
111
+ mesh_filter = openmc.MeshFilter(umesh)
112
+ umesh_tally.filters = [mesh_filter]
113
+ umesh_tally.scores = ["flux"]
114
+ tallies.append(umesh_tally)
115
+
109
116
  # builds the openmc model
110
117
  my_model = openmc.Model(
111
118
  materials=materials, geometry=geometry, settings=settings, tallies=tallies
@@ -255,3 +262,40 @@ def test_h5m_with_multi_volume_touching():
255
262
  material_tags=mat_tags,
256
263
  nuclides=["H1"] * len(mat_tags),
257
264
  )
265
+
266
+
267
+ @pytest.mark.skipif(openmc is None, reason="openmc tests only required for CI")
268
+ def test_umesh_with_volumes():
269
+ box_cutter = cq.Workplane("XY").moveTo(0, 5).box(20, 10, 20)
270
+ inner_sphere = cq.Workplane("XY").sphere(6).cut(box_cutter)
271
+ middle_sphere = cq.Workplane("XY").sphere(6.1).cut(box_cutter).cut(inner_sphere)
272
+ outer_sphere = (
273
+ cq.Workplane("XY").sphere(10).cut(box_cutter).cut(inner_sphere).cut(middle_sphere)
274
+ )
275
+
276
+ assembly = cq.Assembly()
277
+ assembly.add(inner_sphere, name="inner_sphere")
278
+ assembly.add(middle_sphere, name="middle_sphere")
279
+ assembly.add(outer_sphere, name="outer_sphere")
280
+
281
+ model = CadToDagmc()
282
+ mat_tags = ["mat1", "mat2", "mat3"]
283
+ model.add_cadquery_object(assembly, material_tags=mat_tags)
284
+
285
+ h5m_file = model.export_dagmc_h5m_file(
286
+ filename="dagmc.h5m",
287
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
288
+ )
289
+
290
+ vtk_file = model.export_unstructured_mesh_file(
291
+ filename="umesh_vol_1.vtk",
292
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
293
+ volumes=[1], # only mesh volume 2 out of the three volumes
294
+ )
295
+
296
+ transport_particles_on_h5m_geometry(
297
+ h5m_filename=h5m_file,
298
+ material_tags=mat_tags,
299
+ nuclides=["H1"] * len(mat_tags),
300
+ vtk_filename=vtk_file,
301
+ )
@@ -2,7 +2,7 @@ import gmsh
2
2
  from test_python_api import get_volumes_and_materials_from_h5m
3
3
  from test_h5m_in_transport import transport_particles_on_h5m_geometry
4
4
  import cadquery as cq
5
- import assembly_mesh_plugin.plugin
5
+ import assembly_mesh_plugin
6
6
  import gmsh
7
7
  import pydagmc
8
8
  import math
@@ -47,7 +47,7 @@ def test_mesh_to_dagmc_with_mesh_object():
47
47
  2: "mat:insert",
48
48
  }
49
49
 
50
- model = pydagmc.DAGModel(test_h5m_filename)
50
+ model = pydagmc.Model(test_h5m_filename)
51
51
  v1 = model.volumes_by_id[1] # get volume by id number 1
52
52
  v2 = model.volumes_by_id[2] # get volume by id number 2
53
53
  assert len(model.volumes_by_id) == 2
@@ -89,7 +89,7 @@ def test_mesh_to_dagmc_with_cadquery_object():
89
89
  1: "mat:firstmat",
90
90
  2: "mat:aluminum",
91
91
  }
92
- model = pydagmc.DAGModel(test_h5m_filename)
92
+ model = pydagmc.Model(test_h5m_filename)
93
93
  v1 = model.volumes_by_id[1] # get volume by id number 1
94
94
  v2 = model.volumes_by_id[2] # get volume by id number 2
95
95
  assert len(model.volumes_by_id) == 2
@@ -333,3 +333,56 @@ def test_two_box_scaling_factor_when_adding_cq_object(
333
333
  assert width_x == expected_x_width
334
334
  assert width_y == expected_y_width
335
335
  assert width_z == expected_z_width
336
+
337
+
338
+ def test_unstructured_mesh_with_volumes():
339
+
340
+ box_cutter = cq.Workplane("XY").moveTo(0, 5).box(20, 10, 20)
341
+ inner_sphere = cq.Workplane("XY").sphere(6).cut(box_cutter)
342
+ middle_sphere = cq.Workplane("XY").sphere(6.1).cut(box_cutter).cut(inner_sphere)
343
+ outer_sphere = (
344
+ cq.Workplane("XY").sphere(10).cut(box_cutter).cut(inner_sphere).cut(middle_sphere)
345
+ )
346
+
347
+ assembly = cq.Assembly()
348
+ assembly.add(inner_sphere, name="inner_sphere")
349
+ assembly.add(middle_sphere, name="middle_sphere")
350
+ assembly.add(outer_sphere, name="outer_sphere")
351
+
352
+ model = CadToDagmc()
353
+ model.add_cadquery_object(assembly, material_tags=["mat1", "mat2", "mat3"])
354
+
355
+ filename = model.export_dagmc_h5m_file(
356
+ filename="dagmc.h5m",
357
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
358
+ )
359
+ assert Path(filename).is_file()
360
+
361
+ filename = model.export_unstructured_mesh_file(
362
+ filename="umesh_vol_1.vtk",
363
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
364
+ volumes=[1], # only mesh volume 2 out of the three volumes
365
+ )
366
+ assert Path(filename).is_file()
367
+
368
+ filename = model.export_unstructured_mesh_file(
369
+ filename="umesh_vol_2.vtk",
370
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
371
+ volumes=[2], # only mesh volume 2 out of the three volumes
372
+ )
373
+ assert Path(filename).is_file()
374
+
375
+ filename = model.export_unstructured_mesh_file(
376
+ filename="umesh_vol_3.vtk",
377
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
378
+ volumes=[3], # only mesh volume 2 out of the three volumes
379
+ )
380
+ assert Path(filename).is_file()
381
+
382
+ filename = model.export_unstructured_mesh_file(
383
+ filename="umesh_vol_1_2.vtk",
384
+ set_size={1: 0.9, 2: 0.1, 3: 0.9},
385
+ volumes=[1, 2], # only mesh volume 2 out of the three volumes
386
+ )
387
+
388
+ assert Path(filename).is_file()
File without changes
File without changes
File without changes
File without changes