Skip to content

Commit 4a8d700

Browse files
authored
Merge pull request openmc-dev#2222 from highness-eu/mixed_ncrystal
Adding support for NCrystal materials in OpenMC
2 parents 0db1d74 + bdafa70 commit 4a8d700

30 files changed

Lines changed: 861 additions & 45 deletions

‎.github/workflows/ci.yml‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ jobs:
2929
mpi: [n, y]
3030
omp: [n, y]
3131
dagmc: [n]
32+
ncrystal: [n]
3233
libmesh: [n]
3334
event: [n]
3435
vectfit: [n]
@@ -47,6 +48,10 @@ jobs:
4748
python-version: '3.10'
4849
mpi: y
4950
omp: y
51+
- ncrystal: y
52+
python-version: '3.10'
53+
mpi: n
54+
omp: n
5055
- libmesh: y
5156
python-version: '3.10'
5257
mpi: y
@@ -64,7 +69,7 @@ jobs:
6469
omp: n
6570
mpi: y
6671
name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }},
67-
mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }},
72+
mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, ncrystal=${{ matrix.ncrystal }},
6873
libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }}
6974
vectfit=${{ matrix.vectfit }})"
7075

@@ -73,6 +78,7 @@ jobs:
7378
PHDF5: ${{ matrix.mpi }}
7479
OMP: ${{ matrix.omp }}
7580
DAGMC: ${{ matrix.dagmc }}
81+
NCRYSTAL: ${{ matrix.ncrystal }}
7682
EVENT: ${{ matrix.event }}
7783
VECTFIT: ${{ matrix.vectfit }}
7884
LIBMESH: ${{ matrix.libmesh }}

‎CMakeLists.txt‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry"
3737
option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF)
3838
option(OPENMC_USE_MPI "Enable MPI" OFF)
3939
option(OPENMC_USE_MCPL "Enable MCPL" OFF)
40+
option(OPENMC_USE_NCRYSTAL "Enable support for NCrystal scattering" OFF)
4041

4142
# Warnings for deprecated options
4243
foreach(OLD_OPT IN ITEMS "openmp" "profile" "coverage" "dagmc" "libmesh")
@@ -99,6 +100,15 @@ macro(find_package_write_status pkg)
99100
endif()
100101
endmacro()
101102

103+
#===============================================================================
104+
# NCrystal Scattering Support
105+
#===============================================================================
106+
107+
if(OPENMC_USE_NCRYSTAL)
108+
find_package(NCrystal REQUIRED)
109+
message(STATUS "Found NCrystal: ${NCrystal_DIR} (version ${NCrystal_VERSION})")
110+
endif()
111+
102112
#===============================================================================
103113
# DAGMC Geometry Support - need DAGMC/MOAB
104114
#===============================================================================
@@ -338,6 +348,7 @@ list(APPEND libopenmc_SOURCES
338348
src/message_passing.cpp
339349
src/mgxs.cpp
340350
src/mgxs_interface.cpp
351+
src/ncrystal_interface.cpp
341352
src/nuclide.cpp
342353
src/output.cpp
343354
src/particle.cpp
@@ -498,6 +509,11 @@ if (OPENMC_USE_MCPL)
498509
target_link_libraries(libopenmc MCPL::mcpl)
499510
endif()
500511

512+
if(OPENMC_USE_NCRYSTAL)
513+
target_compile_definitions(libopenmc PRIVATE NCRYSTAL)
514+
target_link_libraries(libopenmc NCrystal::NCrystal)
515+
endif()
516+
501517
#===============================================================================
502518
# Log build info that this executable can report later
503519
#===============================================================================

‎cmake/OpenMCConfig.cmake.in‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ if(@OPENMC_USE_DAGMC@)
99
find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@)
1010
endif()
1111

12+
if(@OPENMC_USE_NCRYSTAL@)
13+
find_package(NCrystal REQUIRED)
14+
message(STATUS "Found NCrystal: ${NCrystal_DIR} (version ${NCrystal_VERSION})")
15+
endif()
16+
1217
if(@OPENMC_USE_LIBMESH@)
1318
include(FindPkgConfig)
1419
list(APPEND CMAKE_PREFIX_PATH @LIBMESH_PREFIX@)

‎docs/source/methods/cross_sections.rst‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,27 @@ been selected. There are three methods available:
178178
section data is loaded for a single temperature and is used in the
179179
unresolved resonance and fast energy ranges.
180180

181+
------------------
182+
NCrystal materials
183+
------------------
184+
185+
As an alternative of the standard thermal scattering treatment using
186+
:math:`S(\alpha,\beta)` tables, OpenMC allows to create materials using
187+
NCrystal_. In addition to the regular thermal elastic, and thermal inelastic
188+
processes, NCrystal allows the generation of models for materials that cannot
189+
currently included in ACE files such as oriented single crystals (see the
190+
`NCrystal paper`_), and further extend the physics `using plugins`_. Thermal
191+
scattering kernels are generated on the fly from dynamic and structural data, or
192+
loaded from :math:`S(\alpha,\beta)` tables converted from ENDF6 evaluations.
193+
These kernels are sampled in a direct way using a fast `rejection algorithm`_
194+
that does not require previous processing. A `large library`_ of materials is
195+
already included in the NCrystal distribution, and new materials can be easily
196+
defined from scratch in the `NCMAT format`_ or `combining existing files`_.
197+
198+
The compositions of the materials defined in NCrystal are passed on to OpenMC
199+
all other reactions except for thermal neutron scattering are handled by
200+
continuous energy ACE libraries.
201+
181202
----------------
182203
Multi-Group Data
183204
----------------
@@ -279,3 +300,10 @@ or even isotropic scattering.
279300
.. _ENDF/B data: https://www.nndc.bnl.gov/endf-b8.0/
280301
.. _Leppanen: https://doi.org/10.1016/j.anucene.2009.03.019
281302
.. _algorithms: http://ab-initio.mit.edu/wiki/index.php/Faddeeva_Package
303+
.. _NCrystal: https://github.com/mctools/ncrystal
304+
.. _NCrystal paper: https://doi.org/10.1016/j.cpc.2019.07.015
305+
.. _using plugins: https://doi.org/10.1016/j.cpc.2021.108082
306+
.. _rejection algorithm: https://doi.org/10.1016/j.jcp.2018.11.043
307+
.. _large library: https://github.com/mctools/ncrystal/wiki/Data-library
308+
.. _NCMAT format: https://github.com/mctools/ncrystal/wiki/NCMAT-format
309+
.. _combining existing files: https://github.com/mctools/ncrystal/wiki/Announcement-Release3.0.0#2-multiphase-materials

‎docs/source/usersguide/install.rst‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,17 @@ Prerequisites
271271

272272
cmake -DOPENMC_USE_DAGMC=on -DCMAKE_PREFIX_PATH=/path/to/dagmc/installation ..
273273

274+
* NCrystal_ library for defining materials with enhanced thermal neutron transport
275+
276+
Adding this option allows the creation of materials from NCrystal, which
277+
replaces the scattering kernel treatment of ACE files with a modular,
278+
on-the-fly approach. To use it `install
279+
<https://github.com/mctools/ncrystal/wiki/Get-NCrystal>`_ and `initialize
280+
<https://github.com/mctools/ncrystal/wiki/Using-NCrystal#setting-up>`_
281+
NCrystal and turn on the option in the CMake configuration step:
282+
283+
cmake -DOPENMC_USE_NCRYSTAL=on ..
284+
274285
* libMesh_ mesh library framework for numerical simulations of partial differential equations
275286

276287
This optional dependency enables support for unstructured mesh tally
@@ -294,6 +305,7 @@ Prerequisites
294305
.. _MOAB: https://bitbucket.org/fathomteam/moab
295306
.. _libMesh: https://libmesh.github.io/
296307
.. _libpng: http://www.libpng.org/pub/png/libpng.html
308+
.. _NCrystal: https://github.com/mctools/ncrystal
297309

298310
Obtaining the Source
299311
--------------------
@@ -362,6 +374,12 @@ OPENMC_USE_DAGMC
362374
should also be defined as `DAGMC_ROOT` in the CMake configuration command.
363375
(Default: off)
364376

377+
OPENMC_USE_NCRYSTAL
378+
Turns on support for NCrystal materials. NCrystal must be
379+
`installed <https://github.com/mctools/ncrystal/wiki/Get-NCrystal>`_ and
380+
`initialized <https://github.com/mctools/ncrystal/wiki/Using-NCrystal#setting-up>`_.
381+
(Default: off)
382+
365383
OPENMC_USE_LIBMESH
366384
Enables the use of unstructured mesh tallies with libMesh_. (Default: off)
367385

‎docs/source/usersguide/materials.rst‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,42 @@ you would need to add hydrogen and oxygen to a material and then assign the
101101

102102
.. _usersguide_naming:
103103

104+
-------------------------
105+
Adding NCrystal materials
106+
-------------------------
107+
108+
Additional support for thermal scattering can be added by using NCrystal_. The
109+
:meth:`Material.from_ncrystal` class method generates a :class:`openmc.Material`
110+
object from an `NCrystal configuration string
111+
<https://github.com/mctools/ncrystal/wiki/Using-NCrystal#uniform-material-configuration-syntax>`_.
112+
Temperature, material composition, and density are passed from the configuration
113+
string and the `NCMAT file
114+
<https://github.com/mctools/ncrystal/wiki/NCMAT-format>`_ that define the
115+
material, e.g.::
116+
117+
mat = openmc.Material.from_ncrystal('Al_sg225.ncmat;temp=300K')
118+
119+
defines a material containing polycrystalline alumnium,
120+
121+
::
122+
123+
mat = openmc.Material.from_ncrystal("""Ge_sg227.ncmat;dcutoff=0.5;mos=40arcsec;
124+
dir1=@crys_hkl:5,1,1@lab:0,0,1;
125+
dir2=@crys_hkl:0,-1,1@lab:0,1,0""")
126+
127+
defines an oriented germanium single crystal with 40 arcsec mosaicity.
128+
129+
NCrystal only handles low energy neutron interactions. Other interactions are
130+
provided by standard ACE files. NCrystal_ comes with a `predefined library
131+
<https://github.com/mctools/ncrystal/wiki/Data-library>`_ but more materials can
132+
be added by creating NCMAT files or on-the-fly in the configuration string.
133+
134+
.. warning:: Currently, NCrystal_ materials cannot be modified after they are created.
135+
Density, temperature and composition should be defined in the
136+
configuration string or the NCMAT file.
137+
138+
.. _NCrystal: https://github.com/mctools/ncrystal
139+
104140
------------------
105141
Naming Conventions
106142
------------------
@@ -222,3 +258,4 @@ been generated, you can tell OpenMC to use this file either by setting
222258
materials.cross_sections = '/path/to/cross_sections.xml'
223259

224260
.. _MCNP: https://mcnp.lanl.gov/
261+

‎include/openmc/file_utils.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ namespace openmc {
1414
inline bool dir_exists(const std::string& path)
1515
{
1616
struct stat s;
17-
if (stat(path.c_str(), &s) != 0) return false;
17+
if (stat(path.c_str(), &s) != 0)
18+
return false;
1819

1920
return s.st_mode & S_IFDIR;
2021
}

‎include/openmc/material.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "openmc/bremsstrahlung.h"
1313
#include "openmc/constants.h"
1414
#include "openmc/memory.h" // for unique_ptr
15+
#include "openmc/ncrystal_interface.h"
1516
#include "openmc/particle.h"
1617
#include "openmc/vector.h"
1718

@@ -151,12 +152,17 @@ class Material {
151152
//! \return Temperature in [K]
152153
double temperature() const;
153154

155+
//! Get pointer to NCrystal material object
156+
//! \return Pointer to NCrystal material object
157+
const NCrystalMat& ncrystal_mat() const { return ncrystal_mat_; };
158+
154159
//----------------------------------------------------------------------------
155160
// Data
156161
int32_t id_ {C_NONE}; //!< Unique ID
157162
std::string name_; //!< Name of material
158163
vector<int> nuclide_; //!< Indices in nuclides vector
159164
vector<int> element_; //!< Indices in elements vector
165+
NCrystalMat ncrystal_mat_; //!< NCrystal material object
160166
xt::xtensor<double, 1> atom_density_; //!< Nuclide atom density in [atom/b-cm]
161167
double density_; //!< Total atom density in [atom/b-cm]
162168
double density_gpcc_; //!< Total atom density in [g/cm^3]
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#ifndef OPENMC_NCRYSTAL_INTERFACE_H
2+
#define OPENMC_NCRYSTAL_INTERFACE_H
3+
4+
#ifdef NCRYSTAL
5+
#include "NCrystal/NCRNG.hh"
6+
#include "NCrystal/NCrystal.hh"
7+
#endif
8+
9+
#include "openmc/particle.h"
10+
11+
#include <cstdint> // for uint64_t
12+
#include <limits> // for numeric_limits
13+
#include <string>
14+
15+
namespace openmc {
16+
17+
//==============================================================================
18+
// Constants
19+
//==============================================================================
20+
21+
extern "C" const bool NCRYSTAL_ENABLED;
22+
23+
//! Energy in [eV] to switch between NCrystal and ENDF
24+
constexpr double NCRYSTAL_MAX_ENERGY {5.0};
25+
26+
//==============================================================================
27+
// Wrapper class an NCrystal material
28+
//==============================================================================
29+
30+
class NCrystalMat {
31+
public:
32+
//----------------------------------------------------------------------------
33+
// Constructors
34+
NCrystalMat() = default;
35+
explicit NCrystalMat(const std::string& cfg);
36+
37+
//----------------------------------------------------------------------------
38+
// Methods
39+
40+
#ifdef NCRYSTAL
41+
//! Return configuration string
42+
std::string cfg() const;
43+
44+
//! Get cross section from NCrystal material
45+
//
46+
//! \param[in] p Particle object
47+
//! \return Cross section in [b]
48+
double xs(const Particle& p) const;
49+
50+
// Process scattering event
51+
//
52+
//! \param[in] p Particle object
53+
void scatter(Particle& p) const;
54+
55+
//! Whether the object holds a valid NCrystal material
56+
operator bool() const;
57+
#else
58+
59+
//----------------------------------------------------------------------------
60+
// Trivial methods when compiling without NCRYSTAL
61+
std::string cfg() const
62+
{
63+
return "";
64+
}
65+
double xs(const Particle& p) const
66+
{
67+
return -1.0;
68+
}
69+
void scatter(Particle& p) const {}
70+
operator bool() const
71+
{
72+
return false;
73+
}
74+
#endif
75+
76+
private:
77+
//----------------------------------------------------------------------------
78+
// Data members (only present when compiling with NCrystal support)
79+
#ifdef NCRYSTAL
80+
std::string cfg_; //!< NCrystal configuration string
81+
std::shared_ptr<const NCrystal::ProcImpl::Process>
82+
ptr_; //!< Pointer to NCrystal material object
83+
#endif
84+
};
85+
86+
//==============================================================================
87+
// Functions
88+
//==============================================================================
89+
90+
void ncrystal_update_micro(double xs, NuclideMicroXS& micro);
91+
92+
} // namespace openmc
93+
94+
#endif // OPENMC_NCRYSTAL_INTERFACE_H

‎include/openmc/physics.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p);
9696

9797
void sample_secondary_photons(Particle& p, int i_nuclide);
9898

99-
//!Split or Roulette particles based their weight and the lower weight window
100-
// bound.
99+
//! Split or Roulette particles based their weight and the lower weight window
100+
//! bound.
101+
//
101102
//! \param[in] p, particle to be split or rouletted with the weight window.
102103
void split_particle(Particle& p);
103104

0 commit comments

Comments
 (0)