Skip to content

Commit 3cded0f

Browse files
pshriwisenuclearkevinpaulromano
authored
Add XDG support for unstructured mesh tallies (#3889)
Co-authored-by: Kevin Sawatzky <66632997+nuclearkevin@users.noreply.github.com> Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
1 parent ef49d52 commit 3cded0f

43 files changed

Lines changed: 1138 additions & 1897 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ jobs:
9696
python-version: ["3.12"]
9797
mpi: [n, y]
9898
omp: [n, y]
99-
dagmc: [n]
100-
libmesh: [n]
10199
event: [n]
102100

103101
include:
@@ -110,33 +108,26 @@ jobs:
110108
- python-version: "3.14t"
111109
omp: n
112110
mpi: n
113-
- dagmc: y
114-
python-version: "3.12"
115-
mpi: y
116-
omp: y
117-
- libmesh: y
118-
python-version: "3.12"
119-
mpi: y
120-
omp: y
121-
- libmesh: y
122-
python-version: "3.12"
111+
- python-version: "3.12"
112+
omp: n
123113
mpi: n
124-
omp: y
114+
umesh_libs: y
125115
- event: y
126116
python-version: "3.12"
127117
omp: y
128118
mpi: n
129119
name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }},
130-
mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }},
131-
libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }}"
120+
mpi=${{ matrix.mpi }}, umesh_libs=${{ matrix.umesh_libs }},
121+
event=${{ matrix.event }}"
132122

133123
env:
134124
MPI: ${{ matrix.mpi }}
135125
PHDF5: ${{ matrix.mpi }}
136126
OMP: ${{ matrix.omp }}
137-
DAGMC: ${{ matrix.dagmc }}
127+
DAGMC: ${{ matrix.umesh_libs }}
128+
XDG: ${{ matrix.umesh_libs }}
138129
EVENT: ${{ matrix.event }}
139-
LIBMESH: ${{ matrix.libmesh }}
130+
LIBMESH: ${{ matrix.umesh_libs }}
140131
NPY_DISABLE_CPU_FEATURES: "AVX512F AVX512_SKX"
141132
OPENBLAS_NUM_THREADS: 1
142133
PYTEST_ADDOPTS: --cov=openmc --cov-report=lcov:coverage-python.lcov
@@ -196,6 +187,12 @@ jobs:
196187
sudo update-alternatives --set mpirun /usr/bin/mpirun.mpich
197188
sudo update-alternatives --set mpi-x86_64-linux-gnu /usr/include/x86_64-linux-gnu/mpich
198189
190+
- name: Optional apt dependencies for XDG
191+
shell: bash
192+
if: ${{ matrix.umesh_libs == 'y' }}
193+
run: |
194+
sudo apt install -y libembree-dev
195+
199196
- name: install
200197
shell: bash
201198
run: |

‎CMakeLists.txt‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ option(OPENMC_BUILD_TESTS "Build tests"
3434
option(OPENMC_ENABLE_PROFILE "Compile with profiling flags" OFF)
3535
option(OPENMC_ENABLE_COVERAGE "Compile with coverage analysis flags" OFF)
3636
option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry" OFF)
37+
option(OPENMC_USE_XDG "Enable support for XDG mesh interfaces" OFF)
3738
option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF)
3839
option(OPENMC_USE_MPI "Enable MPI" OFF)
3940
option(OPENMC_USE_UWUW "Enable UWUW" OFF)
@@ -173,6 +174,15 @@ if(OPENMC_USE_DAGMC)
173174
endif()
174175
endif()
175176

177+
#===============================================================================
178+
# XDG Mesh and Geometry Support
179+
#===============================================================================
180+
181+
if(OPENMC_USE_XDG)
182+
find_package(XDG REQUIRED PATH_SUFFIXES lib/cmake)
183+
message(STATUS "Found XDG: ${XDG_DIR} (version ${XDG_VERSION})")
184+
endif()
185+
176186
#===============================================================================
177187
# libMesh Unstructured Mesh Support
178188
#===============================================================================
@@ -392,6 +402,7 @@ list(APPEND libopenmc_SOURCES
392402
src/string_utils.cpp
393403
src/summary.cpp
394404
src/surface.cpp
405+
src/xdg.cpp
395406
src/tallies/derivative.cpp
396407
src/tallies/filter.cpp
397408
src/tallies/filter_azimuthal.cpp
@@ -523,6 +534,11 @@ elseif(OPENMC_USE_UWUW)
523534
message(FATAL_ERROR "DAGMC must be enabled when UWUW is enabled.")
524535
endif()
525536

537+
if(OPENMC_USE_XDG)
538+
target_compile_definitions(libopenmc_objects PRIVATE OPENMC_XDG_ENABLED)
539+
target_link_libraries(libopenmc_objects PUBLIC xdg::xdg)
540+
endif()
541+
526542
if(OPENMC_USE_LIBMESH)
527543
target_compile_definitions(libopenmc_objects PRIVATE OPENMC_LIBMESH_ENABLED)
528544
target_link_libraries(libopenmc_objects PUBLIC PkgConfig::LIBMESH)

‎cmake/OpenMCConfig.cmake.in‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ if("@PNG_FOUND@")
2626
find_dependency(PNG)
2727
endif()
2828

29+
if(@OPENMC_USE_XDG@)
30+
find_dependency(XDG REQUIRED HINTS @XDG_DIR@)
31+
endif()
32+
2933
if(@OPENMC_USE_MPI@)
3034
find_dependency(MPI REQUIRED)
3135
endif()

‎docs/source/io_formats/statepoint.rst‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ The current version of the statepoint file format is 18.2.
9999
- **filename** (*char[]*) -- Name of the mesh file.
100100
- **library** (*char[]*) -- Mesh library used to represent the
101101
mesh ("moab" or "libmesh").
102-
- **length_multiplier** (*double*) Scaling factor applied to the mesh.
102+
- **interface** (*char[]*) -- Interface used to operate on the
103+
mesh ("native" or "xdg"). This
104+
dataset is omitted for the native
105+
interface.
106+
- **length_multiplier** (*double*) -- Scaling factor applied to the mesh.
103107
- **options** (*char[]*) -- Special options that control spatial
104108
search data structures used.
105109
- **volumes** (*double[]*) -- Volume of each mesh cell.

‎docs/source/io_formats/tallies.rst‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,10 @@ attributes/sub-elements:
407407
The mesh library used to represent an unstructured mesh. This can be either
408408
"moab" or "libmesh". (For unstructured mesh only.)
409409

410+
:interface:
411+
The interface used to operate on an unstructured mesh. This can be either
412+
"native" or "xdg". The default is "native". (For unstructured mesh only.)
413+
410414
:options:
411415
Special options that control spatial search data structures used. (For
412416
unstructured mesh using MOAB only)

‎docs/source/usersguide/install.rst‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,15 @@ Prerequisites
364364
Note that libMesh is most commonly compiled with MPI support. If that
365365
is the case, then OpenMC should be compiled with MPI support as well.
366366

367+
* XDG_ interface for unstructured mesh operations
368+
369+
XDG provides a common interface for unstructured mesh operations backed
370+
by MOAB or libMesh. The desired mesh libraries must be enabled when XDG
371+
is built. To enable the XDG interface in OpenMC, specify the XDG
372+
installation in ``CMAKE_PREFIX_PATH``::
373+
374+
cmake -DOPENMC_USE_XDG=on -DCMAKE_PREFIX_PATH=/path/to/xdg/installation ..
375+
367376
.. _gcc: https://gcc.gnu.org/
368377
.. _CMake: https://cmake.org
369378
.. _OpenMPI: https://www.open-mpi.org
@@ -372,6 +381,7 @@ Prerequisites
372381
.. _DAGMC: https://svalinn.github.io/DAGMC/index.html
373382
.. _MOAB: https://bitbucket.org/fathomteam/moab
374383
.. _libMesh: https://libmesh.github.io/
384+
.. _XDG: https://github.com/xdg-org/xdg
375385
.. _libpng: http://www.libpng.org/pub/png/libpng.html
376386
.. _MCPL: https://github.com/mctools/mcpl
377387
.. _NCrystal: https://github.com/mctools/ncrystal
@@ -450,6 +460,9 @@ OPENMC_USE_DAGMC
450460
OPENMC_USE_LIBMESH
451461
Enables the use of unstructured mesh tallies with libMesh_. (Default: off)
452462

463+
OPENMC_USE_XDG
464+
Enables the XDG_ interface for unstructured mesh tallies. (Default: off)
465+
453466
OPENMC_USE_MPI
454467
Turns on compiling with MPI (Default: off). For further information on MPI
455468
options, please see the `FindMPI.cmake documentation

‎include/openmc/mesh.h‎

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ class Mesh {
155155

156156
// Factory method for creating meshes from either an XML node or HDF5 group
157157
template<typename T>
158-
static const std::unique_ptr<Mesh>& create(
159-
T dataset, const std::string& mesh_type, const std::string& mesh_library);
158+
static const std::unique_ptr<Mesh>& create(T dataset);
160159

161160
// Methods
162161
//! Perform any preparation needed to support point location within the mesh
@@ -739,15 +738,18 @@ class SphericalMesh : public PeriodicStructuredMesh {
739738
class UnstructuredMesh : public Mesh {
740739

741740
public:
741+
template<typename T>
742+
static std::unique_ptr<UnstructuredMesh> create(T dataset);
743+
742744
// Constructors
743745
UnstructuredMesh() { n_dimension_ = 3; };
744746
UnstructuredMesh(pugi::xml_node node);
745747
UnstructuredMesh(hid_t group);
746748

747749
static const std::string mesh_type;
748-
virtual std::string get_mesh_type() const override;
749750

750751
// Overridden Methods
752+
virtual std::string get_mesh_type() const override;
751753

752754
void surface_bins_crossed(Position r0, Position r1, const Direction& u,
753755
vector<int>& bins) const override;
@@ -756,6 +758,8 @@ class UnstructuredMesh : public Mesh {
756758

757759
std::string bin_label(int bin) const override;
758760

761+
const std::string& interface() const { return interface_; }
762+
759763
// Methods
760764

761765
//! Add a variable to the mesh instance
@@ -800,6 +804,9 @@ class UnstructuredMesh : public Mesh {
800804
//! Get the library used for this unstructured mesh
801805
virtual std::string library() const = 0;
802806

807+
//! Get the mesh filename
808+
virtual const std::string& filename() const { return filename_; }
809+
803810
// Data members
804811
bool output_ {
805812
true}; //!< Write tallies onto the unstructured mesh at the end of a run
@@ -826,12 +833,43 @@ class UnstructuredMesh : public Mesh {
826833
//! \param[in] coords Coordinates of the tetrahedron
827834
//! \param[in] seed Random number generation seed
828835
//! \return Sampled position within the tetrahedron
829-
Position sample_tet(std::array<Position, 4> coords, uint64_t* seed) const;
836+
template<typename V>
837+
Position sample_tet(span<V> coords, uint64_t* seed) const
838+
{
839+
// Uniform distribution
840+
double s = prn(seed);
841+
double t = prn(seed);
842+
double u = prn(seed);
843+
844+
// From PyNE implementation of moab tet sampling C. Rocchini & P. Cignoni
845+
// (2000) Generating Random Points in a Tetrahedron, Journal of Graphics
846+
// Tools, 5:4, 9-12, DOI: 10.1080/10867651.2000.10487528
847+
if (s + t > 1) {
848+
s = 1.0 - s;
849+
t = 1.0 - t;
850+
}
851+
if (s + t + u > 1) {
852+
if (t + u > 1) {
853+
double old_t = t;
854+
t = 1.0 - u;
855+
u = 1.0 - s - old_t;
856+
} else if (t + u <= 1) {
857+
double old_s = s;
858+
s = 1.0 - t - u;
859+
u = old_s + t + u - 1;
860+
}
861+
}
862+
V result = s * (coords[1] - coords[0]) + t * (coords[2] - coords[0]) +
863+
u * (coords[3] - coords[0]) + coords[0];
864+
return {result[0], result[1], result[2]};
865+
}
830866

831867
// Data members
832868
double length_multiplier_ {
833869
-1.0}; //!< Multiplicative factor applied to mesh coordinates
834870
std::string options_; //!< Options for search data structures
871+
std::string interface_ {
872+
"native"}; //!< Name of the interface used for the mesh
835873

836874
//! Determine lower-left and upper-right bounds of mesh
837875
void determine_bounds();

‎include/openmc/xdg.h‎

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#ifndef OPENMC_XDG_H
2+
#define OPENMC_XDG_H
3+
4+
namespace openmc {
5+
extern "C" const bool XDG_ENABLED;
6+
}
7+
8+
#ifdef OPENMC_XDG_ENABLED
9+
10+
#include "xdg/xdg.h"
11+
12+
#include "openmc/mesh.h"
13+
#include "openmc/position.h"
14+
#include "openmc/xml_interface.h"
15+
16+
namespace openmc {
17+
18+
class XDGMesh : public UnstructuredMesh {
19+
20+
public:
21+
//----------------------------------------------------------------------------
22+
// Constructors
23+
XDGMesh() = default;
24+
XDGMesh(pugi::xml_node node);
25+
XDGMesh(hid_t group);
26+
XDGMesh(const std::string& filename, double length_multiplier = 1.0);
27+
XDGMesh(std::shared_ptr<xdg::XDG> external_xdg);
28+
29+
static const std::string mesh_interface;
30+
31+
//----------------------------------------------------------------------------
32+
// Methods
33+
34+
//! Get the underlying XDG instance
35+
//!
36+
//! \return Shared pointer to the XDG instance
37+
const std::shared_ptr<xdg::XDG>& xdg_instance() const { return xdg_; }
38+
39+
//! Check whether a bin index is valid
40+
//!
41+
//! \param[in] bin Bin index to check
42+
//! \return True if the bin index is in [0, n_bins())
43+
bool bin_is_valid(int bin) const { return bin >= 0 && bin < n_bins(); }
44+
45+
//! Convert a mesh bin index to an XDG MeshID
46+
//!
47+
//! \param[in] bin Bin index to convert
48+
//! \return XDG MeshID corresponding to the bin
49+
xdg::MeshID bin_to_mesh_id(int bin) const;
50+
51+
//! Convert an XDG MeshID to a mesh bin index
52+
//!
53+
//! \param[in] id XDG MeshID to convert
54+
//! \return Bin index corresponding to the MeshID, or -1 if invalid
55+
int mesh_id_to_bin(xdg::MeshID id) const;
56+
57+
//! Get the name of the underlying mesh library
58+
//!
59+
//! \return Name of the mesh library being used in XDG
60+
std::string library() const override;
61+
62+
//----------------------------------------------------------------------------
63+
// Overridden Methods
64+
65+
//! Perform any preparation needed to support use in mesh filters
66+
void prepare_for_point_location() override;
67+
68+
Position sample_element(int32_t bin, uint64_t* seed) const override;
69+
70+
void bins_crossed(Position r0, Position r1, const Direction& u,
71+
vector<int>& bins, vector<double>& lengths) const override;
72+
73+
int get_bin(Position r) const override;
74+
75+
int n_bins() const override;
76+
77+
int n_surface_bins() const override;
78+
79+
std::pair<vector<double>, vector<double>> plot(
80+
Position plot_ll, Position plot_ur) const override;
81+
82+
//! Add a score to the mesh instance
83+
void add_score(const std::string& score) override {};
84+
85+
//! Remove all scores from the mesh instance
86+
void remove_scores() override {};
87+
88+
//! Set data for a score
89+
void set_score_data(const std::string& score, const vector<double>& values,
90+
const vector<double>& std_dev) override {};
91+
92+
//! Write the mesh with any current tally data
93+
void write(const std::string& base_filename) const override;
94+
95+
Position centroid(int bin) const override;
96+
97+
int n_vertices() const override;
98+
99+
Position vertex(int id) const override;
100+
101+
std::vector<int> connectivity(int id) const override;
102+
103+
//! Get the volume of a mesh bin
104+
//
105+
//! \param[in] bin Bin to return the volume for
106+
//! \return Volume of the bin
107+
double volume(int bin) const override;
108+
109+
private:
110+
void initialize() override;
111+
112+
int n_surface_bins_ {0}; //!< Number of surface bins in the mesh
113+
114+
//----------------------------------------------------------------------------
115+
// Private data members
116+
std::shared_ptr<xdg::XDG> xdg_; //!< XDG instance
117+
xdg::MeshLibrary mesh_library_ {
118+
xdg::MeshLibrary::LIBMESH}; //!< Mesh library type
119+
};
120+
121+
} // namespace openmc
122+
123+
#endif // OPENMC_XDG_ENABLED
124+
125+
#endif // OPENMC_XDG_H

0 commit comments

Comments
 (0)