Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ jobs:
mpi: [n, y]
omp: [n, y]
dagmc: [n]
ncrystal: [n]
libmesh: [n]
event: [n]
vectfit: [n]
Expand All @@ -45,10 +44,6 @@ jobs:
python-version: "3.11"
mpi: y
omp: y
- ncrystal: y
python-version: "3.11"
mpi: n
omp: n
- libmesh: y
python-version: "3.11"
mpi: y
Expand All @@ -66,7 +61,7 @@ jobs:
omp: n
mpi: y
name: "Python ${{ matrix.python-version }} (omp=${{ matrix.omp }},
mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }}, ncrystal=${{ matrix.ncrystal }},
mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }},
libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }}
vectfit=${{ matrix.vectfit }})"

Expand All @@ -75,7 +70,6 @@ jobs:
PHDF5: ${{ matrix.mpi }}
OMP: ${{ matrix.omp }}
DAGMC: ${{ matrix.dagmc }}
NCRYSTAL: ${{ matrix.ncrystal }}
EVENT: ${{ matrix.event }}
VECTFIT: ${{ matrix.vectfit }}
LIBMESH: ${{ matrix.libmesh }}
Expand Down
25 changes: 1 addition & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ option(OPENMC_USE_DAGMC "Enable support for DAGMC (CAD) geometry"
option(OPENMC_USE_LIBMESH "Enable support for libMesh unstructured mesh tallies" OFF)
option(OPENMC_USE_MPI "Enable MPI" OFF)
option(OPENMC_USE_MCPL "Enable MCPL" OFF)
option(OPENMC_USE_NCRYSTAL "Enable support for NCrystal scattering" OFF)
option(OPENMC_USE_UWUW "Enable UWUW" OFF)

message(STATUS "OPENMC_USE_OPENMP ${OPENMC_USE_OPENMP}")
Expand All @@ -48,7 +47,6 @@ message(STATUS "OPENMC_USE_DAGMC ${OPENMC_USE_DAGMC}")
message(STATUS "OPENMC_USE_LIBMESH ${OPENMC_USE_LIBMESH}")
message(STATUS "OPENMC_USE_MPI ${OPENMC_USE_MPI}")
message(STATUS "OPENMC_USE_MCPL ${OPENMC_USE_MCPL}")
message(STATUS "OPENMC_USE_NCRYSTAL ${OPENMC_USE_NCRYSTAL}")
message(STATUS "OPENMC_USE_UWUW ${OPENMC_USE_UWUW}")

# Warnings for deprecated options
Expand Down Expand Up @@ -120,23 +118,6 @@ macro(find_package_write_status pkg)
endif()
endmacro()

#===============================================================================
# NCrystal Scattering Support
#===============================================================================

if(OPENMC_USE_NCRYSTAL)
if(NOT DEFINED "NCrystal_DIR")
#Invocation of "ncrystal-config --show cmakedir" is needed to find NCrystal
#when it is installed from Python wheels:
execute_process(
COMMAND "ncrystal-config" "--show" "cmakedir"
OUTPUT_VARIABLE "NCrystal_DIR" OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
find_package(NCrystal 3.8.0 REQUIRED)
message(STATUS "Found NCrystal: ${NCrystal_DIR} (version ${NCrystal_VERSION})")
endif()

#===============================================================================
# DAGMC Geometry Support - need DAGMC/MOAB
#===============================================================================
Expand Down Expand Up @@ -372,6 +353,7 @@ list(APPEND libopenmc_SOURCES
src/mgxs.cpp
src/mgxs_interface.cpp
src/ncrystal_interface.cpp
src/ncrystal_load.cpp
src/nuclide.cpp
src/output.cpp
src/particle.cpp
Expand Down Expand Up @@ -548,11 +530,6 @@ if (OPENMC_USE_MCPL)
target_link_libraries(libopenmc MCPL::mcpl)
endif()

if(OPENMC_USE_NCRYSTAL)
target_compile_definitions(libopenmc PRIVATE NCRYSTAL)
target_link_libraries(libopenmc NCrystal::NCrystal)
endif()

#===============================================================================
# Log build info that this executable can report later
#===============================================================================
Expand Down
3 changes: 2 additions & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ Dockerfile @shimwell
src/random_ray/ @jtramm

# NCrystal interface
src/ncrystal_interface.cpp @marquezj
src/ncrystal_interface.cpp @marquezj @tkittel
src/ncrystal_load.cpp @marquezj @tkittel

# MCPL interface
src/mcpl_interface.cpp @ebknudsen
13 changes: 0 additions & 13 deletions cmake/OpenMCConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,6 @@ if(@OPENMC_USE_DAGMC@)
find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@)
endif()

if(@OPENMC_USE_NCRYSTAL@)
if(NOT DEFINED "NCrystal_DIR")
#Invocation of "ncrystal-config --show cmakedir" is needed to find NCrystal
#when it is installed from Python wheels:
execute_process(
COMMAND "ncrystal-config" "--show" "cmakedir"
OUTPUT_VARIABLE "NCrystal_DIR" OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
find_package(NCrystal REQUIRED)
message(STATUS "Found NCrystal: ${NCrystal_DIR} (version ${NCrystal_VERSION})")
endif()

if(@OPENMC_USE_LIBMESH@)
include(FindPkgConfig)
list(APPEND CMAKE_PREFIX_PATH @LIBMESH_PREFIX@)
Expand Down
20 changes: 7 additions & 13 deletions docs/source/usersguide/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -284,13 +284,13 @@ Prerequisites

* NCrystal_ library for defining materials with enhanced thermal neutron transport

Adding this option allows the creation of materials from NCrystal, which
replaces the scattering kernel treatment of ACE files with a modular,
on-the-fly approach. To use it `install
<https://github.com/mctools/ncrystal/wiki/Get-NCrystal>`_ NCrystal and
turn on the option in the CMake configuration step::

cmake -DOPENMC_USE_NCRYSTAL=on ..
OpenMC supports the creation of materials from NCrystal, which replaces
the scattering kernel treatment of ACE files with a modular, on-the-fly
approach. OpenMC does not need any particular build option to use this,
but NCrystal must be installed on the system. Refer to `NCrystal
documentation
<https://github.com/mctools/ncrystal/wiki/Get-NCrystal>`_ for how this is
achieved.

* libMesh_ mesh library framework for numerical simulations of partial differential equations

Expand Down Expand Up @@ -393,12 +393,6 @@ OPENMC_USE_MCPL
Turns on support for reading MCPL_ source files and writing MCPL source points
and surface sources. (Default: off)

OPENMC_USE_NCRYSTAL
Turns on support for NCrystal materials. NCrystal must be `installed
<https://github.com/mctools/ncrystal/wiki/Get-NCrystal>`_ and `initialized
<https://github.com/mctools/ncrystal/wiki/Using-NCrystal#setting-up>`_.
(Default: off)

OPENMC_USE_LIBMESH
Enables the use of unstructured mesh tallies with libMesh_. (Default: off)

Expand Down
40 changes: 15 additions & 25 deletions include/openmc/ncrystal_interface.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
#ifndef OPENMC_NCRYSTAL_INTERFACE_H
#define OPENMC_NCRYSTAL_INTERFACE_H

#ifdef NCRYSTAL
#include "NCrystal/NCrystal.hh"
#endif

#include "openmc/ncrystal_load.h"
#include "openmc/particle.h"

#include <cstdint> // for uint64_t
Expand All @@ -17,28 +14,25 @@ namespace openmc {
// Constants
//==============================================================================

extern "C" const bool NCRYSTAL_ENABLED;

//! Energy in [eV] to switch between NCrystal and ENDF
constexpr double NCRYSTAL_MAX_ENERGY {5.0};

//==============================================================================
// Wrapper class an NCrystal material
// Wrapper class for an NCrystal material
//==============================================================================

class NCrystalMat {
public:
//----------------------------------------------------------------------------
// Constructors
NCrystalMat() = default;
NCrystalMat() = default; // empty object
explicit NCrystalMat(const std::string& cfg);

//----------------------------------------------------------------------------
// Methods

#ifdef NCRYSTAL
//! Return configuration string
std::string cfg() const;
//! Return configuration string:
const std::string& cfg() const { return cfg_; }

//! Get cross section from NCrystal material
//
Expand All @@ -52,25 +46,21 @@ class NCrystalMat {
void scatter(Particle& p) const;

//! Whether the object holds a valid NCrystal material
operator bool() const;
#else
operator bool() const { return !cfg_.empty(); }

//----------------------------------------------------------------------------
// Trivial methods when compiling without NCRYSTAL
std::string cfg() const { return ""; }
double xs(const Particle& p) const { return -1.0; }
void scatter(Particle& p) const {}
operator bool() const { return false; }
#endif
NCrystalMat clone() const
{
NCrystalMat c;
c.cfg_ = cfg_;
c.proc_ = proc_.clone();
return c;
}

private:
//----------------------------------------------------------------------------
// Data members (only present when compiling with NCrystal support)
#ifdef NCRYSTAL
std::string cfg_; //!< NCrystal configuration string
std::shared_ptr<const NCrystal::ProcImpl::Process>
ptr_; //!< Pointer to NCrystal material object
#endif
std::string cfg_; //!< NCrystal configuration string
NCrystalScatProc proc_; //!< NCrystal scatter process
};

//==============================================================================
Expand Down
127 changes: 127 additions & 0 deletions include/openmc/ncrystal_load.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//! \file ncrystal_load.h
//! \brief Helper class taking care of loading NCrystal at runtime.

#ifndef OPENMC_NCRYSTAL_LOAD_H
#define OPENMC_NCRYSTAL_LOAD_H

#include <algorithm> // for swap
#include <functional> // for function
#include <memory> // for shared_ptr
#include <utility> // for move

namespace NCrystalVirtualAPI {

// NOTICE: Do NOT make ANY changes in the NCrystalVirtualAPI::VirtAPI_Type1_v1
// class, it is required to stay exactly constant over time and compatible with
// the same definition used to compile the NCrystal library! But changes to
// white space, comments, and formatting is of course allowed. This API was
// introduced in NCrystal 4.1.0.

//! Abstract base class for NCrystal interface which must be declared exactly as
// it is in NCrystal itself.

class VirtAPI_Type1_v1 {
public:
// Note: neutron must be an array of length 4 with values {ekin,ux,uy,uz}
class ScatterProcess;
virtual const ScatterProcess* createScatter(const char* cfgstr) const = 0;
virtual const ScatterProcess* cloneScatter(const ScatterProcess*) const = 0;
virtual void deallocateScatter(const ScatterProcess*) const = 0;
virtual double crossSectionUncached(
const ScatterProcess&, const double* neutron) const = 0;
virtual void sampleScatterUncached(const ScatterProcess&,
std::function<double()>& rng, double* neutron) const = 0;
// Plumbing:
static constexpr unsigned interface_id = 1001;
virtual ~VirtAPI_Type1_v1() = default;
VirtAPI_Type1_v1() = default;
VirtAPI_Type1_v1(const VirtAPI_Type1_v1&) = delete;
VirtAPI_Type1_v1& operator=(const VirtAPI_Type1_v1&) = delete;
VirtAPI_Type1_v1(VirtAPI_Type1_v1&&) = delete;
VirtAPI_Type1_v1& operator=(VirtAPI_Type1_v1&&) = delete;
};

} // namespace NCrystalVirtualAPI

namespace openmc {

using NCrystalAPI = NCrystalVirtualAPI::VirtAPI_Type1_v1;

//! Function which locates and loads NCrystal at runtime using the virtual API
std::shared_ptr<const NCrystalAPI> load_ncrystal_api();

//! Class encapsulating exactly the parts of NCrystal needed by OpenMC

class NCrystalScatProc final {
public:
//! Empty constructor which does not load NCrystal
NCrystalScatProc() {}

//! Load NCrystal and instantiate a scattering process
//! \param cfgstr NCrystal cfg-string defining the material.
NCrystalScatProc(const char* cfgstr)
: api_(load_ncrystal_api()), p_(api_->createScatter(cfgstr))
{}

// Note: Neutron state array is {ekin,ux,uy,uz}

//! Returns total scattering cross section in units of barns per atom.
//! \param neutron_state array {ekin,ux,uy,uz} with ekin (eV) and direction.
double cross_section(const double* neutron_state) const
{
return api_->crossSectionUncached(*p_, neutron_state);
}

//! Returns total scattering cross section in units of barns per atom.
//! \param rng function returning random numbers in the unit interval
//! \param neutron_state array {ekin,ux,uy,uz} with ekin (eV) and direction.
void scatter(std::function<double()>& rng, double* neutron_state) const
{
api_->sampleScatterUncached(*p_, rng, neutron_state);
}

//! Clones the object which is otherwise move-only
NCrystalScatProc clone() const
{
NCrystalScatProc c;
if (p_) {
c.api_ = api_;
c.p_ = api_->cloneScatter(p_);
}
return c;
}

// Plumbing (move-only semantics, but supports explicit clone):
NCrystalScatProc(const NCrystalScatProc&) = delete;
NCrystalScatProc& operator=(const NCrystalScatProc&) = delete;

NCrystalScatProc(NCrystalScatProc&& o) : api_(std::move(o.api_)), p_(nullptr)
{
std::swap(p_, o.p_);
}

NCrystalScatProc& operator=(NCrystalScatProc&& o)
{
if (p_) {
api_->deallocateScatter(p_);
p_ = nullptr;
}
std::swap(api_, o.api_);
std::swap(p_, o.p_);
return *this;
}

~NCrystalScatProc()
{
if (p_)
api_->deallocateScatter(p_);
}

private:
std::shared_ptr<const NCrystalAPI> api_;
const NCrystalAPI::ScatterProcess* p_ = nullptr;
};

} // namespace openmc

#endif
3 changes: 0 additions & 3 deletions openmc/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@
def _dagmc_enabled():
return c_bool.in_dll(_dll, "DAGMC_ENABLED").value

def _ncrystal_enabled():
return c_bool.in_dll(_dll, "NCRYSTAL_ENABLED").value

def _coord_levels():
return c_int.in_dll(_dll, "n_coord_levels").value

Expand Down
6 changes: 5 additions & 1 deletion openmc/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,11 @@ def from_ncrystal(cls, cfg, **kwargs) -> Material:

"""

import NCrystal
try:
import NCrystal
except ModuleNotFoundError as e:
raise RuntimeError('The .from_ncrystal method requires'
' NCrystal to be installed.') from e
nc_mat = NCrystal.createInfo(cfg)

def openmc_natabund(Z):
Expand Down
Loading