adding back files to be reviewed

This commit is contained in:
Paul Romano 2019-10-28 11:55:45 -05:00
parent ae28233110
commit bc09d1ef55
1244 changed files with 301904 additions and 0 deletions

View file

@ -0,0 +1,21 @@
#ifndef OPENMC_ANGLE_ENERGY_H
#define OPENMC_ANGLE_ENERGY_H
namespace openmc {
//==============================================================================
//! Abstract type that defines a correlated or uncorrelated angle-energy
//! distribution that is a function of incoming energy. Each derived type must
//! implement a sample() method that returns an outgoing energy and
//! scattering cosine given an incoming energy.
//==============================================================================
class AngleEnergy {
public:
virtual void sample(double E_in, double& E_out, double& mu) const = 0;
virtual ~AngleEnergy() = default;
};
}
#endif // OPENMC_ANGLE_ENERGY_H

42
include/openmc/bank.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef OPENMC_BANK_H
#define OPENMC_BANK_H
#include <cstdint>
#include <vector>
#include "openmc/particle.h"
#include "openmc/position.h"
// Without an explicit instantiation of vector<Bank>, the Intel compiler
// will complain about the threadprivate directive on filter_matches. Note that
// this has to happen *outside* of the openmc namespace
extern template class std::vector<openmc::Particle::Bank>;
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
namespace simulation {
extern std::vector<Particle::Bank> source_bank;
extern std::vector<Particle::Bank> fission_bank;
extern std::vector<Particle::Bank> secondary_bank;
#ifdef _OPENMP
extern std::vector<Particle::Bank> master_fission_bank;
#endif
#pragma omp threadprivate(fission_bank, secondary_bank)
} // namespace simulation
//==============================================================================
// Non-member functions
//==============================================================================
void free_memory_bank();
} // namespace openmc
#endif // OPENMC_BANK_H

View file

@ -0,0 +1,48 @@
#ifndef OPENMC_BREMSSTRAHLUNG_H
#define OPENMC_BREMSSTRAHLUNG_H
#include "openmc/particle.h"
#include "xtensor/xtensor.hpp"
namespace openmc {
//==============================================================================
// Bremsstrahlung classes
//==============================================================================
class BremsstrahlungData {
public:
// Data
xt::xtensor<double, 2> pdf; //!< Bremsstrahlung energy PDF
xt::xtensor<double, 2> cdf; //!< Bremsstrahlung energy CDF
xt::xtensor<double, 1> yield; //!< Photon yield
};
class Bremsstrahlung {
public:
// Data
BremsstrahlungData electron;
BremsstrahlungData positron;
};
//==============================================================================
// Global variables
//==============================================================================
namespace data {
extern xt::xtensor<double, 1> ttb_e_grid; //! energy T of incident electron in [eV]
extern xt::xtensor<double, 1> ttb_k_grid; //! reduced energy W/T of emitted photon
} // namespace data
//==============================================================================
// Global variables
//==============================================================================
void thick_target_bremsstrahlung(Particle& p, double* E_lost);
} // namespace openmc
#endif // OPENMC_BREMSSTRAHLUNG_H

175
include/openmc/capi.h Normal file
View file

@ -0,0 +1,175 @@
#ifndef OPENMC_CAPI_H
#define OPENMC_CAPI_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
int openmc_calculate_volumes();
int openmc_cell_filter_get_bins(int32_t index, const int32_t** cells, int32_t* n);
int openmc_cell_get_fill(int32_t index, int* type, int32_t** indices, int32_t* n);
int openmc_cell_get_id(int32_t index, int32_t* id);
int openmc_cell_get_temperature(int32_t index, const int32_t* instance, double* T);
int openmc_cell_get_name(int32_t index, const char** name);
int openmc_cell_set_name(int32_t index, const char* name);
int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices);
int openmc_cell_set_id(int32_t index, int32_t id);
int openmc_cell_set_temperature(int32_t index, double T, const int32_t* instance);
int openmc_energy_filter_get_bins(int32_t index, const double** energies, size_t* n);
int openmc_energy_filter_set_bins(int32_t index, size_t n, const double* energies);
int openmc_energyfunc_filter_get_energy(int32_t index, size_t* n, const double** energy);
int openmc_energyfunc_filter_get_y(int32_t index, size_t* n, const double** y);
int openmc_energyfunc_filter_set_data(int32_t index, size_t n,
const double* energies, const double* y);
int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_filter_get_id(int32_t index, int32_t* id);
int openmc_filter_get_type(int32_t index, char* type);
int openmc_filter_set_id(int32_t index, int32_t id);
int openmc_finalize();
int openmc_find_cell(const double* xyz, int32_t* index, int32_t* instance);
int openmc_cell_bounding_box(const int32_t index, double* llc, double* urc);
int openmc_global_bounding_box(double* llc, double* urc);
int openmc_fission_bank(void** ptr, int64_t* n);
int openmc_get_cell_index(int32_t id, int32_t* index);
int openmc_get_filter_index(int32_t id, int32_t* index);
void openmc_get_filter_next_id(int32_t* id);
int openmc_get_keff(double k_combined[]);
int openmc_get_material_index(int32_t id, int32_t* index);
int openmc_get_mesh_index(int32_t id, int32_t* index);
int openmc_get_nuclide_index(const char name[], int* index);
int64_t openmc_get_seed();
int openmc_get_tally_index(int32_t id, int32_t* index);
void openmc_get_tally_next_id(int32_t* id);
int openmc_global_tallies(double** ptr);
int openmc_hard_reset();
int openmc_init(int argc, char* argv[], const void* intracomm);
bool openmc_is_statepoint_batch();
int openmc_legendre_filter_get_order(int32_t index, int* order);
int openmc_legendre_filter_set_order(int32_t index, int order);
int openmc_load_nuclide(const char* name);
int openmc_material_add_nuclide(int32_t index, const char name[], double density);
int openmc_material_get_densities(int32_t index, const int** nuclides, const double** densities, int* n);
int openmc_material_get_id(int32_t index, int32_t* id);
int openmc_material_get_fissionable(int32_t index, bool* fissionable);
int openmc_material_get_density(int32_t index, double* density);
int openmc_material_get_volume(int32_t index, double* volume);
int openmc_material_set_density(int32_t index, double density, const char* units);
int openmc_material_set_densities(int32_t index, int n, const char** name, const double* density);
int openmc_material_set_id(int32_t index, int32_t id);
int openmc_material_get_name(int32_t index, const char** name);
int openmc_material_set_name(int32_t index, const char* name);
int openmc_material_set_volume(int32_t index, double volume);
int openmc_material_filter_get_bins(int32_t index, const int32_t** bins, size_t* n);
int openmc_material_filter_set_bins(int32_t index, size_t n, const int32_t* bins);
int openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh);
int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh);
int openmc_mesh_get_id(int32_t index, int32_t* id);
int openmc_mesh_get_dimension(int32_t index, int** id, int* n);
int openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n);
int openmc_mesh_set_id(int32_t index, int32_t id);
int openmc_mesh_set_dimension(int32_t index, int n, const int* dims);
int openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width);
int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh);
int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh);
int openmc_new_filter(const char* type, int32_t* index);
int openmc_next_batch(int* status);
int openmc_nuclide_name(int index, const char** name);
int openmc_plot_geometry();
int openmc_id_map(const void* slice, int32_t* data_out);
int openmc_property_map(const void* slice, double* data_out);
int openmc_reset();
int openmc_run();
void openmc_set_seed(int64_t new_seed);
int openmc_simulation_finalize();
int openmc_simulation_init();
int openmc_source_bank(void** ptr, int64_t* n);
int openmc_spatial_legendre_filter_get_order(int32_t index, int* order);
int openmc_spatial_legendre_filter_get_params(int32_t index, int* axis, double* min, double* max);
int openmc_spatial_legendre_filter_set_order(int32_t index, int order);
int openmc_spatial_legendre_filter_set_params(int32_t index, const int* axis,
const double* min, const double* max);
int openmc_sphharm_filter_get_order(int32_t index, int* order);
int openmc_sphharm_filter_get_cosine(int32_t index, char cosine[]);
int openmc_sphharm_filter_set_order(int32_t index, int order);
int openmc_sphharm_filter_set_cosine(int32_t index, const char cosine[]);
int openmc_statepoint_write(const char* filename, bool* write_source);
int openmc_tally_allocate(int32_t index, const char* type);
int openmc_tally_get_active(int32_t index, bool* active);
int openmc_tally_get_estimator(int32_t index, int* estimator);
int openmc_tally_get_id(int32_t index, int32_t* id);
int openmc_tally_get_filters(int32_t index, const int32_t** indices, size_t* n);
int openmc_tally_get_n_realizations(int32_t index, int32_t* n);
int openmc_tally_get_nuclides(int32_t index, int** nuclides, int* n);
int openmc_tally_get_scores(int32_t index, int** scores, int* n);
int openmc_tally_get_type(int32_t index, int32_t* type);
int openmc_tally_get_writable(int32_t index, bool* writable);
int openmc_tally_reset(int32_t index);
int openmc_tally_results(int32_t index, double** ptr, size_t shape_[3]);
int openmc_tally_set_active(int32_t index, bool active);
int openmc_tally_set_estimator(int32_t index, const char* estimator);
int openmc_tally_set_filters(int32_t index, size_t n, const int32_t* indices);
int openmc_tally_set_id(int32_t index, int32_t id);
int openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides);
int openmc_tally_set_scores(int32_t index, int n, const char** scores);
int openmc_tally_set_type(int32_t index, const char* type);
int openmc_tally_set_writable(int32_t index, bool writable);
int openmc_zernike_filter_get_order(int32_t index, int* order);
int openmc_zernike_filter_get_params(int32_t index, double* x, double* y, double* r);
int openmc_zernike_filter_set_order(int32_t index, int order);
int openmc_zernike_filter_set_params(int32_t index, const double* x,
const double* y, const double* r);
//! Sets the fixed variables that are used for CMFD linear solver
//! \param[in] CSR format index pointer array of loss matrix
//! \param[in] length of indptr
//! \param[in] CSR format index array of loss matrix
//! \param[in] number of non-zero elements in CMFD loss matrix
//! \param[in] dimension n of nxn CMFD loss matrix
//! \param[in] spectral radius of CMFD matrices and tolerances
//! \param[in] indices storing spatial and energy dimensions of CMFD problem
//! \param[in] coremap for problem, storing accelerated regions
extern "C" void openmc_initialize_linsolver(const int* indptr, int len_indptr,
const int* indices, int n_elements,
int dim, double spectral,
const int* cmfd_indices,
const int* map);
//! Runs a Gauss Seidel linear solver to solve CMFD matrix equations
//! linear solver
//! \param[in] CSR format data array of coefficient matrix
//! \param[in] right hand side vector
//! \param[out] unknown vector
//! \param[in] tolerance on final error
//! \return number of inner iterations required to reach convergence
extern "C" int openmc_run_linsolver(const double* A_data, const double* b,
double* x, double tol);
// Error codes
extern int OPENMC_E_UNASSIGNED;
extern int OPENMC_E_ALLOCATE;
extern int OPENMC_E_OUT_OF_BOUNDS;
extern int OPENMC_E_INVALID_SIZE;
extern int OPENMC_E_INVALID_ARGUMENT;
extern int OPENMC_E_INVALID_TYPE;
extern int OPENMC_E_INVALID_ID;
extern int OPENMC_E_GEOMETRY;
extern int OPENMC_E_DATA;
extern int OPENMC_E_PHYSICS;
extern int OPENMC_E_WARNING;
// Global variables
extern char openmc_err_msg[256];
#ifdef __cplusplus
}
#endif
#endif // OPENMC_CAPI_H

300
include/openmc/cell.h Normal file
View file

@ -0,0 +1,300 @@
#ifndef OPENMC_CELL_H
#define OPENMC_CELL_H
#include <cstdint>
#include <limits>
#include <memory> // for unique_ptr
#include <string>
#include <unordered_map>
#include <vector>
#include "hdf5.h"
#include "pugixml.hpp"
#include "dagmc.h"
#include "openmc/constants.h"
#include "openmc/neighbor_list.h"
#include "openmc/position.h"
#include "openmc/surface.h"
namespace openmc {
//==============================================================================
// Constants
//==============================================================================
// TODO: Convert to enum
constexpr int FILL_MATERIAL {1};
constexpr int FILL_UNIVERSE {2};
constexpr int FILL_LATTICE {3};
// TODO: Convert to enum
constexpr int32_t OP_LEFT_PAREN {std::numeric_limits<int32_t>::max()};
constexpr int32_t OP_RIGHT_PAREN {std::numeric_limits<int32_t>::max() - 1};
constexpr int32_t OP_COMPLEMENT {std::numeric_limits<int32_t>::max() - 2};
constexpr int32_t OP_INTERSECTION {std::numeric_limits<int32_t>::max() - 3};
constexpr int32_t OP_UNION {std::numeric_limits<int32_t>::max() - 4};
//==============================================================================
// Global variables
//==============================================================================
class Cell;
class Universe;
class UniversePartitioner;
namespace model {
extern std::vector<std::unique_ptr<Cell>> cells;
extern std::unordered_map<int32_t, int32_t> cell_map;
extern std::vector<std::unique_ptr<Universe>> universes;
extern std::unordered_map<int32_t, int32_t> universe_map;
} // namespace model
//==============================================================================
//! A geometry primitive that fills all space and contains cells.
//==============================================================================
class Universe
{
public:
int32_t id_; //!< Unique ID
std::vector<int32_t> cells_; //!< Cells within this universe
//! \brief Write universe information to an HDF5 group.
//! \param group_id An HDF5 group id.
void to_hdf5(hid_t group_id) const;
BoundingBox bounding_box() const;
std::unique_ptr<UniversePartitioner> partitioner_;
};
//==============================================================================
//! A geometry primitive that links surfaces, universes, and materials
//==============================================================================
class Cell {
public:
//----------------------------------------------------------------------------
// Constructors, destructors, factory functions
explicit Cell(pugi::xml_node cell_node);
Cell() {};
virtual ~Cell() = default;
//----------------------------------------------------------------------------
// Methods
//! \brief Determine if a cell contains the particle at a given location.
//!
//! The bounds of the cell are detemined by a logical expression involving
//! surface half-spaces. At initialization, the expression was converted
//! to RPN notation.
//!
//! The function is split into two cases, one for simple cells (those
//! involving only the intersection of half-spaces) and one for complex cells.
//! Simple cells can be evaluated with short circuit evaluation, i.e., as soon
//! as we know that one half-space is not satisfied, we can exit. This
//! provides a performance benefit for the common case. In
//! contains_complex, we evaluate the RPN expression using a stack, similar to
//! how a RPN calculator would work.
//! \param r The 3D Cartesian coordinate to check.
//! \param u A direction used to "break ties" the coordinates are very
//! close to a surface.
//! \param on_surface The signed index of a surface that the coordinate is
//! known to be on. This index takes precedence over surface sense
//! calculations.
virtual bool
contains(Position r, Direction u, int32_t on_surface) const = 0;
//! Find the oncoming boundary of this cell.
virtual std::pair<double, int32_t>
distance(Position r, Direction u, int32_t on_surface) const = 0;
//! Write all information needed to reconstruct the cell to an HDF5 group.
//! \param group_id An HDF5 group id.
virtual void to_hdf5(hid_t group_id) const = 0;
//! Get the BoundingBox for this cell.
virtual BoundingBox bounding_box() const = 0;
//----------------------------------------------------------------------------
// Accessors
//! Get the temperature of a cell instance
//! \param[in] instance Instance index. If -1 is given, the temperature for
//! the first instance is returned.
//! \return Temperature in [K]
double temperature(int32_t instance = -1) const;
//! Set the temperature of a cell instance
//! \param[in] T Temperature in [K]
//! \param[in] instance Instance index. If -1 is given, the temperature for
//! all instances is set.
void set_temperature(double T, int32_t instance = -1);
//! Get the name of a cell
//! \return Cell name
const std::string& name() const { return name_; };
//! Set the temperature of a cell instance
//! \param[in] name Cell name
void set_name(const std::string& name) { name_ = name; };
//----------------------------------------------------------------------------
// Data members
int32_t id_; //!< Unique ID
std::string name_; //!< User-defined name
int type_; //!< Material, universe, or lattice
int32_t universe_; //!< Universe # this cell is in
int32_t fill_; //!< Universe # filling this cell
int32_t n_instances_{0}; //!< Number of instances of this cell
//! \brief Index corresponding to this cell in distribcell arrays
int distribcell_index_{C_NONE};
//! \brief Material(s) within this cell.
//!
//! May be multiple materials for distribcell.
std::vector<int32_t> material_;
//! \brief Temperature(s) within this cell.
//!
//! The stored values are actually sqrt(k_Boltzmann * T) for each temperature
//! T. The units are sqrt(eV).
std::vector<double> sqrtkT_;
//! Definition of spatial region as Boolean expression of half-spaces
std::vector<std::int32_t> region_;
//! Reverse Polish notation for region expression
std::vector<std::int32_t> rpn_;
bool simple_; //!< Does the region contain only intersections?
//! \brief Neighboring cells in the same universe.
NeighborList neighbors_;
Position translation_ {0, 0, 0}; //!< Translation vector for filled universe
//! \brief Rotational tranfsormation of the filled universe.
//
//! The vector is empty if there is no rotation. Otherwise, the first three
//! values are the rotation angles respectively about the x-, y-, and z-, axes
//! in degrees. The next 9 values give the rotation matrix in row-major
//! order.
std::vector<double> rotation_;
std::vector<int32_t> offset_; //!< Distribcell offset table
};
//==============================================================================
class CSGCell : public Cell
{
public:
CSGCell();
explicit CSGCell(pugi::xml_node cell_node);
bool
contains(Position r, Direction u, int32_t on_surface) const;
std::pair<double, int32_t>
distance(Position r, Direction u, int32_t on_surface) const;
void to_hdf5(hid_t group_id) const;
BoundingBox bounding_box() const;
protected:
bool contains_simple(Position r, Direction u, int32_t on_surface) const;
bool contains_complex(Position r, Direction u, int32_t on_surface) const;
BoundingBox bounding_box_simple() const;
static BoundingBox bounding_box_complex(std::vector<int32_t> rpn);
//! Applies DeMorgan's laws to a section of the RPN
//! \param start Starting point for token modification
//! \param stop Stopping point for token modification
static void apply_demorgan(std::vector<int32_t>::iterator start,
std::vector<int32_t>::iterator stop);
//! Removes complement operators from the RPN
//! \param rpn The rpn to remove complement operators from.
static void remove_complement_ops(std::vector<int32_t>& rpn);
//! Returns the beginning position of a parenthesis block (immediately before
//! two surface tokens) in the RPN given a starting position at the end of
//! that block (immediately after two surface tokens)
//! \param start Starting position of the search
//! \param rpn The rpn being searched
static std::vector<int32_t>::iterator
find_left_parenthesis(std::vector<int32_t>::iterator start,
const std::vector<int32_t>& rpn);
};
//==============================================================================
#ifdef DAGMC
class DAGCell : public Cell
{
public:
DAGCell();
bool contains(Position r, Direction u, int32_t on_surface) const;
std::pair<double, int32_t>
distance(Position r, Direction u, int32_t on_surface) const;
BoundingBox bounding_box() const;
void to_hdf5(hid_t group_id) const;
moab::DagMC* dagmc_ptr_; //!< Pointer to DagMC instance
int32_t dag_index_; //!< DagMC index of cell
};
#endif
//==============================================================================
//! Speeds up geometry searches by grouping cells in a search tree.
//
//! Currently this object only works with universes that are divided up by a
//! bunch of z-planes. It could be generalized to other planes, cylinders,
//! and spheres.
//==============================================================================
class UniversePartitioner
{
public:
explicit UniversePartitioner(const Universe& univ);
//! Return the list of cells that could contain the given coordinates.
const std::vector<int32_t>& get_cells(Position r, Direction u) const;
private:
//! A sorted vector of indices to surfaces that partition the universe
std::vector<int32_t> surfs_;
//! Vectors listing the indices of the cells that lie within each partition
//
//! There are n+1 partitions with n surfaces. `partitions_.front()` gives the
//! cells that lie on the negative side of `surfs_.front()`.
//! `partitions_.back()` gives the cells that lie on the positive side of
//! `surfs_.back()`. Otherwise, `partitions_[i]` gives cells sandwiched
//! between `surfs_[i-1]` and `surfs_[i]`.
std::vector<std::vector<int32_t>> partitions_;
};
//==============================================================================
// Non-member functions
//==============================================================================
void read_cells(pugi::xml_node node);
#ifdef DAGMC
int32_t next_cell(DAGCell* cur_cell, DAGSurface* surf_xed);
#endif
} // namespace openmc
#endif // OPENMC_CELL_H

View file

@ -0,0 +1,10 @@
#ifndef OPENMC_CMFD_SOLVER_H
#define OPENMC_CMFD_SOLVER_H
namespace openmc {
void free_memory_cmfd();
} // namespace openmc
#endif // OPENMC_CMFD_SOLVER_H

431
include/openmc/constants.h Normal file
View file

@ -0,0 +1,431 @@
//! \file constants.h
//! A collection of constants
#ifndef OPENMC_CONSTANTS_H
#define OPENMC_CONSTANTS_H
#include <array>
#include <cmath>
#include <limits>
#include <vector>
namespace openmc {
using double_2dvec = std::vector<std::vector<double>>;
using double_3dvec = std::vector<std::vector<std::vector<double>>>;
using double_4dvec = std::vector<std::vector<std::vector<std::vector<double>>>>;
// ============================================================================
// VERSIONING NUMBERS
// OpenMC major, minor, and release numbers
constexpr int VERSION_MAJOR {0};
constexpr int VERSION_MINOR {11};
constexpr int VERSION_RELEASE {0};
constexpr bool VERSION_DEV {false};
constexpr std::array<int, 3> VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE};
// HDF5 data format
constexpr int HDF5_VERSION[] {3, 0};
// Version numbers for binary files
constexpr std::array<int, 2> VERSION_STATEPOINT {17, 0};
constexpr std::array<int, 2> VERSION_PARTICLE_RESTART {2, 0};
constexpr std::array<int, 2> VERSION_TRACK {2, 0};
constexpr std::array<int, 2> VERSION_SUMMARY {6, 0};
constexpr std::array<int, 2> VERSION_VOLUME {1, 0};
constexpr std::array<int, 2> VERSION_VOXEL {2, 0};
constexpr std::array<int, 2> VERSION_MGXS_LIBRARY {1, 0};
// ============================================================================
// ADJUSTABLE PARAMETERS
// NOTE: This is the only section of the constants module that should ever be
// adjusted. Modifying constants in other sections may cause the code to fail.
// Monoatomic ideal-gas scattering treatment threshold
constexpr double FREE_GAS_THRESHOLD {400.0};
// Significance level for confidence intervals
constexpr double CONFIDENCE_LEVEL {0.95};
// Used for surface current tallies
constexpr double TINY_BIT {1e-8};
// User for precision in geometry
constexpr double FP_PRECISION {1e-14};
constexpr double FP_REL_PRECISION {1e-5};
constexpr double FP_COINCIDENT {1e-12};
// Maximum number of collisions/crossings
constexpr int MAX_EVENTS {1000000};
constexpr int MAX_SAMPLE {100000};
// Maximum number of words in a single line, length of line, and length of
// single word
constexpr int MAX_LINE_LEN {250};
constexpr int MAX_WORD_LEN {150};
// Maximum number of external source spatial resamples to encounter before an
// error is thrown.
constexpr int EXTSRC_REJECT_THRESHOLD {10000};
constexpr double EXTSRC_REJECT_FRACTION {0.05};
// ============================================================================
// MATH AND PHYSICAL CONSTANTS
// Values here are from the Committee on Data for Science and Technology
// (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009).
// TODO: cmath::M_PI has 3 more digits precision than the Fortran constant we
// use so for now we will reuse the Fortran constant until we are OK with
// modifying test results
constexpr double PI {3.1415926535898};
const double SQRT_PI {std::sqrt(PI)};
constexpr double INFTY {std::numeric_limits<double>::max()};
// Physical constants
constexpr double MASS_NEUTRON {1.00866491588}; // mass of a neutron in amu
constexpr double MASS_NEUTRON_EV {939.5654133e6}; // mass of a neutron in eV/c^2
constexpr double MASS_PROTON {1.007276466879}; // mass of a proton in amu
constexpr double MASS_ELECTRON_EV {0.5109989461e6}; // electron mass energy equivalent in eV/c^2
constexpr double FINE_STRUCTURE {137.035999139}; // inverse fine structure constant
constexpr double PLANCK_C {1.2398419739062977e4}; // Planck's constant times c in eV-Angstroms
constexpr double AMU {1.660539040e-27}; // 1 amu in kg
constexpr double C_LIGHT {2.99792458e8}; // speed of light in m/s
constexpr double N_AVOGADRO {0.6022140857}; // Avogadro's number in 10^24/mol
constexpr double K_BOLTZMANN {8.6173303e-5}; // Boltzmann constant in eV/K
// Electron subshell labels
constexpr std::array<const char*, 39> SUBSHELLS = {
"K", "L1", "L2", "L3", "M1", "M2", "M3", "M4", "M5",
"N1", "N2", "N3", "N4", "N5", "N6", "N7", "O1", "O2",
"O3", "O4", "O5", "O6", "O7", "O8", "O9", "P1", "P2",
"P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10", "P11",
"Q1", "Q2", "Q3"
};
// Void material and nuclide
// TODO: refactor and remove
constexpr int MATERIAL_VOID {-1};
constexpr int NUCLIDE_NONE {-1};
// ============================================================================
// CROSS SECTION RELATED CONSTANTS
// Angular distribution type
// TODO: Convert to enum
constexpr int ANGLE_ISOTROPIC {1};
constexpr int ANGLE_32_EQUI {2};
constexpr int ANGLE_TABULAR {3};
constexpr int ANGLE_LEGENDRE {4};
constexpr int ANGLE_HISTOGRAM {5};
// Temperature treatment method
// TODO: Convert to enum?
constexpr int TEMPERATURE_NEAREST {1};
constexpr int TEMPERATURE_INTERPOLATION {2};
// Reaction types
// TODO: Convert to enum
constexpr int REACTION_NONE {0};
constexpr int TOTAL_XS {1};
constexpr int ELASTIC {2};
constexpr int N_NONELASTIC {3};
constexpr int N_LEVEL {4};
constexpr int MISC {5};
constexpr int N_2ND {11};
constexpr int N_2N {16};
constexpr int N_3N {17};
constexpr int N_FISSION {18};
constexpr int N_F {19};
constexpr int N_NF {20};
constexpr int N_2NF {21};
constexpr int N_NA {22};
constexpr int N_N3A {23};
constexpr int N_2NA {24};
constexpr int N_3NA {25};
constexpr int N_NP {28};
constexpr int N_N2A {29};
constexpr int N_2N2A {30};
constexpr int N_ND {32};
constexpr int N_NT {33};
constexpr int N_N3HE {34};
constexpr int N_ND2A {35};
constexpr int N_NT2A {36};
constexpr int N_4N {37};
constexpr int N_3NF {38};
constexpr int N_2NP {41};
constexpr int N_3NP {42};
constexpr int N_N2P {44};
constexpr int N_NPA {45};
constexpr int N_N1 {51};
constexpr int N_N40 {90};
constexpr int N_NC {91};
constexpr int N_DISAPPEAR {101};
constexpr int N_GAMMA {102};
constexpr int N_P {103};
constexpr int N_D {104};
constexpr int N_T {105};
constexpr int N_3HE {106};
constexpr int N_A {107};
constexpr int N_2A {108};
constexpr int N_3A {109};
constexpr int N_2P {111};
constexpr int N_PA {112};
constexpr int N_T2A {113};
constexpr int N_D2A {114};
constexpr int N_PD {115};
constexpr int N_PT {116};
constexpr int N_DA {117};
constexpr int N_5N {152};
constexpr int N_6N {153};
constexpr int N_2NT {154};
constexpr int N_TA {155};
constexpr int N_4NP {156};
constexpr int N_3ND {157};
constexpr int N_NDA {158};
constexpr int N_2NPA {159};
constexpr int N_7N {160};
constexpr int N_8N {161};
constexpr int N_5NP {162};
constexpr int N_6NP {163};
constexpr int N_7NP {164};
constexpr int N_4NA {165};
constexpr int N_5NA {166};
constexpr int N_6NA {167};
constexpr int N_7NA {168};
constexpr int N_4ND {169};
constexpr int N_5ND {170};
constexpr int N_6ND {171};
constexpr int N_3NT {172};
constexpr int N_4NT {173};
constexpr int N_5NT {174};
constexpr int N_6NT {175};
constexpr int N_2N3HE {176};
constexpr int N_3N3HE {177};
constexpr int N_4N3HE {178};
constexpr int N_3N2P {179};
constexpr int N_3N3A {180};
constexpr int N_3NPA {181};
constexpr int N_DT {182};
constexpr int N_NPD {183};
constexpr int N_NPT {184};
constexpr int N_NDT {185};
constexpr int N_NP3HE {186};
constexpr int N_ND3HE {187};
constexpr int N_NT3HE {188};
constexpr int N_NTA {189};
constexpr int N_2N2P {190};
constexpr int N_P3HE {191};
constexpr int N_D3HE {192};
constexpr int N_3HEA {193};
constexpr int N_4N2P {194};
constexpr int N_4N2A {195};
constexpr int N_4NPA {196};
constexpr int N_3P {197};
constexpr int N_N3P {198};
constexpr int N_3N2PA {199};
constexpr int N_5N2P {200};
constexpr int N_XP {203};
constexpr int N_XD {204};
constexpr int N_XT {205};
constexpr int N_X3HE {206};
constexpr int N_XA {207};
constexpr int HEATING {301};
constexpr int DAMAGE_ENERGY {444};
constexpr int COHERENT {502};
constexpr int INCOHERENT {504};
constexpr int PAIR_PROD_ELEC {515};
constexpr int PAIR_PROD {516};
constexpr int PAIR_PROD_NUC {517};
constexpr int PHOTOELECTRIC {522};
constexpr int N_P0 {600};
constexpr int N_PC {649};
constexpr int N_D0 {650};
constexpr int N_DC {699};
constexpr int N_T0 {700};
constexpr int N_TC {749};
constexpr int N_3HE0 {750};
constexpr int N_3HEC {799};
constexpr int N_A0 {800};
constexpr int N_AC {849};
constexpr int N_2N0 {875};
constexpr int N_2NC {891};
constexpr int HEATING_LOCAL {901};
constexpr std::array<int, 6> DEPLETION_RX {N_GAMMA, N_P, N_A, N_2N, N_3N, N_4N};
// Fission neutron emission (nu) type
constexpr int NU_NONE {0}; // No nu values (non-fissionable)
constexpr int NU_POLYNOMIAL {1}; // Nu values given by polynomial
constexpr int NU_TABULAR {2}; // Nu values given by tabular distribution
// Library types
constexpr int LIBRARY_NEUTRON {1};
constexpr int LIBRARY_THERMAL {2};
constexpr int LIBRARY_PHOTON {3};
constexpr int LIBRARY_MULTIGROUP {4};
// Probability table parameters
constexpr int URR_CUM_PROB {0};
constexpr int URR_TOTAL {1};
constexpr int URR_ELASTIC {2};
constexpr int URR_FISSION {3};
constexpr int URR_N_GAMMA {4};
constexpr int URR_HEATING {5};
// Maximum number of partial fission reactions
constexpr int PARTIAL_FISSION_MAX {4};
// Resonance elastic scattering methods
// TODO: Convert to enum
enum class ResScatMethod {
rvs, // Relative velocity sampling
dbrc, // Doppler broadening rejection correction
cxs // Constant cross section
};
// Electron treatments
// TODO: Convert to enum
constexpr int ELECTRON_LED {1}; // Local Energy Deposition
constexpr int ELECTRON_TTB {2}; // Thick Target Bremsstrahlung
// ============================================================================
// MULTIGROUP RELATED
// MGXS Table Types
// TODO: Convert to enum
constexpr int MGXS_ISOTROPIC {1}; // Isotroically weighted data
constexpr int MGXS_ANGLE {2}; // Data by angular bins
// Flag to denote this was a macroscopic data object
constexpr double MACROSCOPIC_AWR {-2.};
// Number of mu bins to use when converting Legendres to tabular type
constexpr int DEFAULT_NMU {33};
// Mgxs::get_xs enumerated types
// TODO: Convert to enum
constexpr int MG_GET_XS_TOTAL {0};
constexpr int MG_GET_XS_ABSORPTION {1};
constexpr int MG_GET_XS_INVERSE_VELOCITY {2};
constexpr int MG_GET_XS_DECAY_RATE {3};
constexpr int MG_GET_XS_SCATTER {4};
constexpr int MG_GET_XS_SCATTER_MULT {5};
constexpr int MG_GET_XS_SCATTER_FMU_MULT {6};
constexpr int MG_GET_XS_SCATTER_FMU {7};
constexpr int MG_GET_XS_FISSION {8};
constexpr int MG_GET_XS_KAPPA_FISSION {9};
constexpr int MG_GET_XS_PROMPT_NU_FISSION {10};
constexpr int MG_GET_XS_DELAYED_NU_FISSION {11};
constexpr int MG_GET_XS_NU_FISSION {12};
constexpr int MG_GET_XS_CHI_PROMPT {13};
constexpr int MG_GET_XS_CHI_DELAYED {14};
// ============================================================================
// TALLY-RELATED CONSTANTS
// Tally result entries
constexpr int RESULT_VALUE {0};
constexpr int RESULT_SUM {1};
constexpr int RESULT_SUM_SQ {2};
// Tally type
// TODO: Convert to enum
constexpr int TALLY_VOLUME {1};
constexpr int TALLY_MESH_SURFACE {2};
constexpr int TALLY_SURFACE {3};
// Tally estimator types
// TODO: Convert to enum
constexpr int ESTIMATOR_ANALOG {1};
constexpr int ESTIMATOR_TRACKLENGTH {2};
constexpr int ESTIMATOR_COLLISION {3};
// Event types for tallies
// TODO: Convert to enum
constexpr int EVENT_SURFACE {-2};
constexpr int EVENT_LATTICE {-1};
constexpr int EVENT_KILL {0};
constexpr int EVENT_SCATTER {1};
constexpr int EVENT_ABSORB {2};
// Tally score type -- if you change these, make sure you also update the
// _SCORES dictionary in openmc/capi/tally.py
// TODO: Convert to enum
constexpr int SCORE_FLUX {-1}; // flux
constexpr int SCORE_TOTAL {-2}; // total reaction rate
constexpr int SCORE_SCATTER {-3}; // scattering rate
constexpr int SCORE_NU_SCATTER {-4}; // scattering production rate
constexpr int SCORE_ABSORPTION {-5}; // absorption rate
constexpr int SCORE_FISSION {-6}; // fission rate
constexpr int SCORE_NU_FISSION {-7}; // neutron production rate
constexpr int SCORE_KAPPA_FISSION {-8}; // fission energy production rate
constexpr int SCORE_CURRENT {-9}; // current
constexpr int SCORE_EVENTS {-10}; // number of events
constexpr int SCORE_DELAYED_NU_FISSION {-11}; // delayed neutron production rate
constexpr int SCORE_PROMPT_NU_FISSION {-12}; // prompt neutron production rate
constexpr int SCORE_INVERSE_VELOCITY {-13}; // flux-weighted inverse velocity
constexpr int SCORE_FISS_Q_PROMPT {-14}; // prompt fission Q-value
constexpr int SCORE_FISS_Q_RECOV {-15}; // recoverable fission Q-value
constexpr int SCORE_DECAY_RATE {-16}; // delayed neutron precursor decay rate
// Tally map bin finding
constexpr int NO_BIN_FOUND {-1};
// Tally filter and map types
// TODO: Refactor to remove or convert to enum
constexpr int FILTER_UNIVERSE {1};
constexpr int FILTER_MATERIAL {2};
constexpr int FILTER_CELL {3};
// Mesh types
constexpr int MESH_REGULAR {1};
// Tally surface current directions
constexpr int OUT_LEFT {1}; // x min
constexpr int IN_LEFT {2}; // x min
constexpr int OUT_RIGHT {3}; // x max
constexpr int IN_RIGHT {4}; // x max
constexpr int OUT_BACK {5}; // y min
constexpr int IN_BACK {6}; // y min
constexpr int OUT_FRONT {7}; // y max
constexpr int IN_FRONT {8}; // y max
constexpr int OUT_BOTTOM {9}; // z min
constexpr int IN_BOTTOM {10}; // z min
constexpr int OUT_TOP {11}; // z max
constexpr int IN_TOP {12}; // z max
// Global tally parameters
constexpr int N_GLOBAL_TALLIES {4};
constexpr int K_COLLISION {0};
constexpr int K_ABSORPTION {1};
constexpr int K_TRACKLENGTH {2};
constexpr int LEAKAGE {3};
// Miscellaneous
constexpr int C_NONE {-1};
constexpr int F90_NONE {0}; //TODO: replace usage of this with C_NONE
// Interpolation rules
enum class Interpolation {
histogram = 1, lin_lin = 2, lin_log = 3, log_lin = 4, log_log = 5
};
// Run modes
constexpr int RUN_MODE_FIXEDSOURCE {1};
constexpr int RUN_MODE_EIGENVALUE {2};
constexpr int RUN_MODE_PLOTTING {3};
constexpr int RUN_MODE_PARTICLE {4};
constexpr int RUN_MODE_VOLUME {5};
// ============================================================================
// CMFD CONSTANTS
// For non-accelerated regions on coarse mesh overlay
constexpr int CMFD_NOACCEL {-1};
} // namespace openmc
#endif // OPENMC_CONSTANTS_H

View file

@ -0,0 +1,17 @@
#ifndef OPENMC_CONTAINER_UTIL_H
#define OPENMC_CONTAINER_UTIL_H
#include <algorithm> // for find
#include <iterator> // for begin, end
namespace openmc {
template<class C, class T>
inline bool contains(const C& v, const T& x)
{
return std::end(v) != std::find(std::begin(v), std::end(v), x);
}
}
#endif // OPENMC_CONTAINER_UTIL_H

View file

@ -0,0 +1,77 @@
#ifndef OPENMC_CROSS_SECTIONS_H
#define OPENMC_CROSS_SECTIONS_H
#include "pugixml.hpp"
#include <string>
#include <map>
#include <vector>
namespace openmc {
//==============================================================================
// Library class
//==============================================================================
class Library {
public:
// Types, enums
enum class Type {
neutron = 1, photon = 3, thermal = 2, multigroup = 4, wmp = 5
};
// Constructors
Library() { };
Library(pugi::xml_node node, const std::string& directory);
// Comparison operator (for using in map)
bool operator<(const Library& other) {
return path_ < other.path_;
}
// Data members
Type type_; //!< Type of data library
std::vector<std::string> materials_; //!< Materials contained in library
std::string path_; //!< File path to library
};
using LibraryKey = std::pair<Library::Type, std::string>;
//==============================================================================
// Global variable declarations
//==============================================================================
namespace data {
//!< Data libraries
extern std::vector<Library> libraries;
//! Maps (type, name) to index in libraries
extern std::map<LibraryKey, std::size_t> library_map;
} // namespace data
//==============================================================================
// Non-member functions
//==============================================================================
//! Read cross sections file (either XML or multigroup H5) and populate data
//! libraries
void read_cross_sections_xml();
//! Load nuclide and thermal scattering data from HDF5 files
//
//! \param[in] nuc_temps Temperatures for each nuclide in [K]
//! \param[in] thermal_temps Temperatures for each thermal scattering table in [K]
void read_ce_cross_sections(const std::vector<std::vector<double>>& nuc_temps,
const std::vector<std::vector<double>>& thermal_temps);
//! Read cross_sections.xml and populate data libraries
void read_ce_cross_sections_xml();
void library_clear();
} // namespace openmc
#endif // OPENMC_CROSS_SECTIONS_H

43
include/openmc/dagmc.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef OPENMC_DAGMC_H
#define OPENMC_DAGMC_H
namespace openmc {
extern "C" const bool dagmc_enabled;
}
#ifdef DAGMC
#include "DagMC.hpp"
#include "openmc/xml_interface.h"
#include "openmc/position.h"
namespace openmc {
namespace simulation {
extern moab::DagMC::RayHistory history; //!< facet history for DagMC particles
extern Direction last_dir; //!< last direction passed to DagMC's ray_fire
#pragma omp threadprivate(history, last_dir)
}
namespace model {
extern moab::DagMC* DAG;
}
//==============================================================================
// Non-member functions
//==============================================================================
void load_dagmc_geometry();
void free_memory_dagmc();
void read_geometry_dagmc();
bool read_uwuw_materials(pugi::xml_document& doc);
bool get_uwuw_materials_xml(std::string& s);
} // namespace openmc
#endif // DAGMC
#endif // OPENMC_DAGMC_H

View file

@ -0,0 +1,197 @@
//! \file distribution.h
//! Univariate probability distributions
#ifndef OPENMC_DISTRIBUTION_H
#define OPENMC_DISTRIBUTION_H
#include <cstddef> // for size_t
#include <memory> // for unique_ptr
#include <vector> // for vector
#include "pugixml.hpp"
#include "openmc/constants.h"
namespace openmc {
//==============================================================================
//! Abstract class representing a univariate probability distribution
//==============================================================================
class Distribution {
public:
virtual ~Distribution() = default;
virtual double sample() const = 0;
};
//==============================================================================
//! A discrete distribution (probability mass function)
//==============================================================================
class Discrete : public Distribution {
public:
explicit Discrete(pugi::xml_node node);
Discrete(const double* x, const double* p, int n);
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
// Properties
const std::vector<double>& x() const { return x_; }
const std::vector<double>& p() const { return p_; }
private:
std::vector<double> x_; //!< Possible outcomes
std::vector<double> p_; //!< Probability of each outcome
//! Normalize distribution so that probabilities sum to unity
void normalize();
};
//==============================================================================
//! Uniform distribution over the interval [a,b]
//==============================================================================
class Uniform : public Distribution {
public:
explicit Uniform(pugi::xml_node node);
Uniform(double a, double b) : a_{a}, b_{b} {};
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
private:
double a_; //!< Lower bound of distribution
double b_; //!< Upper bound of distribution
};
//==============================================================================
//! Maxwellian distribution of form c*E*exp(-E/theta)
//==============================================================================
class Maxwell : public Distribution {
public:
explicit Maxwell(pugi::xml_node node);
Maxwell(double theta) : theta_{theta} { };
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
private:
double theta_; //!< Factor in exponential [eV]
};
//==============================================================================
//! Watt fission spectrum with form c*exp(-E/a)*sinh(sqrt(b*E))
//==============================================================================
class Watt : public Distribution {
public:
explicit Watt(pugi::xml_node node);
Watt(double a, double b) : a_{a}, b_{b} { };
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
private:
double a_; //!< Factor in exponential [eV]
double b_; //!< Factor in square root [1/eV]
};
//==============================================================================
//! Normal distributions with form 1/2*std_dev*sqrt(pi) exp (-(e-E0)/2*std_dev)^2
//==============================================================================
class Normal : public Distribution {
public:
explicit Normal(pugi::xml_node node);
Normal(double mean_value, double std_dev) : mean_value_{mean_value}, std_dev_{std_dev} { };
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
private:
double mean_value_; //!< middle of distribution [eV]
double std_dev_; //!< standard deviation [eV]
};
//==============================================================================
//! Muir (fusion) spectrum derived from Normal with extra params e0 is mean
//! std dev is sqrt(4*e0*kt/m)
//==============================================================================
class Muir : public Distribution {
public:
explicit Muir(pugi::xml_node node);
Muir(double e0, double m_rat, double kt) : e0_{e0}, m_rat_{m_rat}, kt_{kt} { };
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
private:
// example DT fusion m_rat = 5 (D = 2 + T = 3)
// ion temp = 20000 eV
// mean neutron energy 14.08e6 eV
double e0_; //!< mean neutron energy [eV]
double m_rat_; //!< ratio of reactant masses relative to atomic mass unit
double kt_; //!< ion temperature [eV]
};
//==============================================================================
//! Histogram or linear-linear interpolated tabular distribution
//==============================================================================
class Tabular : public Distribution {
public:
explicit Tabular(pugi::xml_node node);
Tabular(const double* x, const double* p, int n, Interpolation interp,
const double* c=nullptr);
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
// x property
std::vector<double>& x() { return x_; }
const std::vector<double>& x() const { return x_; }
private:
std::vector<double> x_; //!< tabulated independent variable
std::vector<double> p_; //!< tabulated probability density
std::vector<double> c_; //!< cumulative distribution at tabulated values
Interpolation interp_; //!< interpolation rule
//! Initialize tabulated probability density function
//! \param x Array of values for independent variable
//! \param p Array of tabulated probabilities
//! \param n Number of tabulated values
void init(const double* x, const double* p, std::size_t n,
const double* c=nullptr);
};
//==============================================================================
//! Equiprobable distribution
//==============================================================================
class Equiprobable : public Distribution {
public:
explicit Equiprobable(pugi::xml_node node);
Equiprobable(const double* x, int n) : x_{x, x+n} { };
//! Sample a value from the distribution
//! \return Sampled value
double sample() const;
private:
std::vector<double> x_; //! Possible outcomes
};
using UPtrDist = std::unique_ptr<Distribution>;
//! Return univariate probability distribution specified in XML file
//! \param[in] node XML node representing distribution
//! \return Unique pointer to distribution
UPtrDist distribution_from_xml(pugi::xml_node node);
} // namespace openmc
#endif // OPENMC_DISTRIBUTION_H

View file

@ -0,0 +1,40 @@
//! \file distribution_angle.h
//! Angle distribution dependent on incident particle energy
#ifndef OPENMC_DISTRIBUTION_ANGLE_H
#define OPENMC_DISTRIBUTION_ANGLE_H
#include <vector> // for vector
#include "hdf5.h"
#include "openmc/distribution.h"
namespace openmc {
//==============================================================================
//! Angle distribution that depends on incident particle energy
//==============================================================================
class AngleDistribution {
public:
AngleDistribution() = default;
explicit AngleDistribution(hid_t group);
//! Sample an angle given an incident particle energy
//! \param[in] E Particle energy in [eV]
//! \return Cosine of the angle in the range [-1,1]
double sample(double E) const;
//! Determine whether angle distribution is empty
//! \return Whether distribution is empty
bool empty() const { return energy_.empty(); }
private:
std::vector<double> energy_;
std::vector<UPtrDist> distribution_;
};
} // namespace openmc
#endif // OPENMC_DISTRIBUTION_ANGLE_H

View file

@ -0,0 +1,152 @@
//! \file distribution_energy.h
//! Energy distributions that depend on incident particle energy
#ifndef OPENMC_DISTRIBUTION_ENERGY_H
#define OPENMC_DISTRIBUTION_ENERGY_H
#include <vector>
#include "xtensor/xtensor.hpp"
#include "hdf5.h"
#include "openmc/constants.h"
#include "openmc/endf.h"
namespace openmc {
//===============================================================================
//! Abstract class defining an energy distribution that is a function of the
//! incident energy of a projectile. Each derived type must implement a sample()
//! function that returns a sampled outgoing energy given an incoming energy
//===============================================================================
class EnergyDistribution {
public:
virtual double sample(double E) const = 0;
virtual ~EnergyDistribution() = default;
};
//===============================================================================
//! Discrete photon energy distribution
//===============================================================================
class DiscretePhoton : public EnergyDistribution {
public:
explicit DiscretePhoton(hid_t group);
//! Sample energy distribution
//! \param[in] E Incident particle energy in [eV]
//! \return Sampled energy in [eV]
double sample(double E) const;
private:
int primary_flag_; //!< Indicator of whether the photon is a primary or
//!< non-primary photon.
double energy_; //!< Photon energy or binding energy
double A_; //!< Atomic weight ratio of the target nuclide
};
//===============================================================================
//! Level inelastic scattering distribution
//===============================================================================
class LevelInelastic : public EnergyDistribution {
public:
explicit LevelInelastic(hid_t group);
//! Sample energy distribution
//! \param[in] E Incident particle energy in [eV]
//! \return Sampled energy in [eV]
double sample(double E) const;
private:
double threshold_; //!< Energy threshold in lab, (A + 1)/A * |Q|
double mass_ratio_; //!< (A/(A+1))^2
};
//===============================================================================
//! An energy distribution represented as a tabular distribution with histogram
//! or linear-linear interpolation. This corresponds to ACE law 4, which NJOY
//! produces for a number of ENDF energy distributions.
//===============================================================================
class ContinuousTabular : public EnergyDistribution {
public:
explicit ContinuousTabular(hid_t group);
//! Sample energy distribution
//! \param[in] E Incident particle energy in [eV]
//! \return Sampled energy in [eV]
double sample(double E) const;
private:
//! Outgoing energy for a single incoming energy
struct CTTable {
Interpolation interpolation; //!< Interpolation law
int n_discrete; //!< Number of of discrete energies
xt::xtensor<double, 1> e_out; //!< Outgoing energies in [eV]
xt::xtensor<double, 1> p; //!< Probability density
xt::xtensor<double, 1> c; //!< Cumulative distribution
};
int n_region_; //!< Number of inteprolation regions
std::vector<int> breakpoints_; //!< Breakpoints between regions
std::vector<Interpolation> interpolation_; //!< Interpolation laws
std::vector<double> energy_; //!< Incident energy in [eV]
std::vector<CTTable> distribution_; //!< Distributions for each incident energy
};
//===============================================================================
//! Evaporation spectrum corresponding to ACE law 9 and ENDF File 5, LF=9.
//===============================================================================
class Evaporation : public EnergyDistribution {
public:
explicit Evaporation(hid_t group);
//! Sample energy distribution
//! \param[in] E Incident particle energy in [eV]
//! \return Sampled energy in [eV]
double sample(double E) const;
private:
Tabulated1D theta_; //!< Incoming energy dependent parameter
double u_; //!< Restriction energy
};
//===============================================================================
//! Energy distribution of neutrons emitted from a Maxwell fission spectrum.
//! This corresponds to ACE law 7 and ENDF File 5, LF=7.
//===============================================================================
class MaxwellEnergy : public EnergyDistribution {
public:
explicit MaxwellEnergy(hid_t group);
//! Sample energy distribution
//! \param[in] E Incident particle energy in [eV]
//! \return Sampled energy in [eV]
double sample(double E) const;
private:
Tabulated1D theta_; //!< Incoming energy dependent parameter
double u_; //!< Restriction energy
};
//===============================================================================
//! Energy distribution of neutrons emitted from a Watt fission spectrum. This
//! corresponds to ACE law 11 and ENDF File 5, LF=11.
//===============================================================================
class WattEnergy : public EnergyDistribution {
public:
explicit WattEnergy(hid_t group);
//! Sample energy distribution
//! \param[in] E Incident particle energy in [eV]
//! \return Sampled energy in [eV]
double sample(double E) const;
private:
Tabulated1D a_; //!< Energy-dependent 'a' parameter
Tabulated1D b_; //!< Energy-dependent 'b' parameter
double u_; //!< Restriction energy
};
} // namespace openmc
#endif // OPENMC_DISTRIBUTION_ENERGY_H

View file

@ -0,0 +1,80 @@
#ifndef DISTRIBUTION_MULTI_H
#define DISTRIBUTION_MULTI_H
#include <memory>
#include "pugixml.hpp"
#include "openmc/distribution.h"
#include "openmc/position.h"
namespace openmc {
//==============================================================================
//! Probability density function for points on the unit sphere. Extensions of
//! this type are used to sample angular distributions for starting sources
//==============================================================================
class UnitSphereDistribution {
public:
UnitSphereDistribution() { };
explicit UnitSphereDistribution(Direction u) : u_ref_{u} { };
explicit UnitSphereDistribution(pugi::xml_node node);
virtual ~UnitSphereDistribution() = default;
//! Sample a direction from the distribution
//! \return Direction sampled
virtual Direction sample() const = 0;
Direction u_ref_ {0.0, 0.0, 1.0}; //!< reference direction
};
//==============================================================================
//! Explicit distribution of polar and azimuthal angles
//==============================================================================
class PolarAzimuthal : public UnitSphereDistribution {
public:
PolarAzimuthal(Direction u, UPtrDist mu, UPtrDist phi);
explicit PolarAzimuthal(pugi::xml_node node);
//! Sample a direction from the distribution
//! \return Direction sampled
Direction sample() const;
private:
UPtrDist mu_; //!< Distribution of polar angle
UPtrDist phi_; //!< Distribution of azimuthal angle
};
//==============================================================================
//! Uniform distribution on the unit sphere
//==============================================================================
class Isotropic : public UnitSphereDistribution {
public:
Isotropic() { };
//! Sample a direction from the distribution
//! \return Sampled direction
Direction sample() const;
};
//==============================================================================
//! Monodirectional distribution
//==============================================================================
class Monodirectional : public UnitSphereDistribution {
public:
Monodirectional(Direction u) : UnitSphereDistribution{u} { };
explicit Monodirectional(pugi::xml_node node) : UnitSphereDistribution{node} { };
//! Sample a direction from the distribution
//! \return Sampled direction
Direction sample() const;
};
using UPtrAngle = std::unique_ptr<UnitSphereDistribution>;
} // namespace openmc
#endif // DISTRIBUTION_MULTI_H

View file

@ -0,0 +1,81 @@
#ifndef OPENMC_DISTRIBUTION_SPATIAL_H
#define OPENMC_DISTRIBUTION_SPATIAL_H
#include "pugixml.hpp"
#include "openmc/distribution.h"
#include "openmc/position.h"
namespace openmc {
//==============================================================================
//! Probability density function for points in Euclidean space
//==============================================================================
class SpatialDistribution {
public:
virtual ~SpatialDistribution() = default;
//! Sample a position from the distribution
virtual Position sample() const = 0;
};
//==============================================================================
//! Distribution of points specified by independent distributions in x,y,z
//==============================================================================
class CartesianIndependent : public SpatialDistribution {
public:
explicit CartesianIndependent(pugi::xml_node node);
//! Sample a position from the distribution
//! \return Sampled position
Position sample() const;
private:
UPtrDist x_; //!< Distribution of x coordinates
UPtrDist y_; //!< Distribution of y coordinates
UPtrDist z_; //!< Distribution of z coordinates
};
//==============================================================================
//! Uniform distribution of points over a box
//==============================================================================
class SpatialBox : public SpatialDistribution {
public:
explicit SpatialBox(pugi::xml_node node, bool fission=false);
//! Sample a position from the distribution
//! \return Sampled position
Position sample() const;
// Properties
bool only_fissionable() const { return only_fissionable_; }
private:
Position lower_left_; //!< Lower-left coordinates of box
Position upper_right_; //!< Upper-right coordinates of box
bool only_fissionable_ {false}; //!< Only accept sites in fissionable region?
};
//==============================================================================
//! Distribution at a single point
//==============================================================================
class SpatialPoint : public SpatialDistribution {
public:
SpatialPoint() : r_{} { };
SpatialPoint(Position r) : r_{r} { };
explicit SpatialPoint(pugi::xml_node node);
//! Sample a position from the distribution
//! \return Sampled position
Position sample() const;
private:
Position r_; //!< Single position at which sites are generated
};
using UPtrSpace = std::unique_ptr<SpatialDistribution>;
} // namespace openmc
#endif // OPENMC_DISTRIBUTION_SPATIAL_H

View file

@ -0,0 +1,92 @@
//! \file eigenvalue.h
//! \brief Data/functions related to k-eigenvalue calculations
#ifndef OPENMC_EIGENVALUE_H
#define OPENMC_EIGENVALUE_H
#include <array>
#include <cstdint> // for int64_t
#include <vector>
#include "xtensor/xtensor.hpp"
#include <hdf5.h>
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
namespace simulation {
extern double keff_generation; //!< Single-generation k on each processor
extern std::array<double, 2> k_sum; //!< Used to reduce sum and sum_sq
extern std::vector<double> entropy; //!< Shannon entropy at each generation
extern xt::xtensor<double, 1> source_frac; //!< Source fraction for UFS
} // namespace simulation
//==============================================================================
// Non-member functions
//==============================================================================
//! Collect/normalize the tracklength keff from each process
void calculate_generation_keff();
//! Calculate mean/standard deviation of keff during active generations
//!
//! This function sets the global variables keff and keff_std which represent
//! the mean and standard deviation of the mean of k-effective over active
//! generations. It also broadcasts the value from the master process.
void calculate_average_keff();
#ifdef _OPENMP
//! Join threadprivate fission banks into a single fission bank
//!
//! Note that this operation is necessarily sequential to preserve the order of
//! the bank when using varying numbers of threads.
void join_bank_from_threads();
#endif
//! Calculates a minimum variance estimate of k-effective
//!
//! The minimum variance estimate is based on a linear combination of the
//! collision, absorption, and tracklength estimates. The theory behind this can
//! be found in M. Halperin, "Almost linearly-optimum combination of unbiased
//! estimates," J. Am. Stat. Assoc., 56, 36-43 (1961),
//! doi:10.1080/01621459.1961.10482088. The implementation here follows that
//! described in T. Urbatsch et al., "Estimation and interpretation of keff
//! confidence intervals in MCNP," Nucl. Technol., 111, 169-182 (1995).
//!
//! \param[out] k_combined Estimate of k-effective and its standard deviation
//! \return Error status
extern "C" int openmc_get_keff(double* k_combined);
//! Sample/redistribute source sites from accumulated fission sites
void synchronize_bank();
//! Calculates the Shannon entropy of the fission source distribution to assess
//! source convergence
void shannon_entropy();
//! Determines the source fraction in each UFS mesh cell and reweights the
//! source bank so that the sum of the weights is equal to n_particles. The
//! 'source_frac' variable is used later to bias the production of fission sites
void ufs_count_sites();
//! Get UFS weight corresponding to particle's location
extern "C" double ufs_get_weight(const Particle* p);
//! Write data related to k-eigenvalue to statepoint
//! \param[in] group HDF5 group
void write_eigenvalue_hdf5(hid_t group);
//! Read data related to k-eigenvalue from statepoint
//! \param[in] group HDF5 group
void read_eigenvalue_hdf5(hid_t group);
} // namespace openmc
#endif // OPENMC_EIGENVALUE_H

133
include/openmc/endf.h Normal file
View file

@ -0,0 +1,133 @@
//! \file endf.h
//! Classes and functions related to the ENDF-6 format
#ifndef OPENMC_ENDF_H
#define OPENMC_ENDF_H
#include <memory>
#include <vector>
#include "hdf5.h"
#include "openmc/constants.h"
namespace openmc {
//! Convert integer representing interpolation law to enum
//! \param[in] i Intereger (e.g. 1=histogram, 2=lin-lin)
//! \return Corresponding enum value
Interpolation int2interp(int i);
//! Determine whether MT number corresponds to a fission reaction
//! \param[in] MT ENDF MT value
//! \return Whether corresponding reaction is a fission reaction
bool is_fission(int MT);
//! Determine if a given MT number is that of a disappearance reaction, i.e., a
//! reaction with no neutron in the exit channel
//! \param[in] MT ENDF MT value
//! \return Whether corresponding reaction is a disappearance reaction
bool is_disappearance(int MT);
//! Determine if a given MT number is that of an inelastic scattering reaction
//! \param[in] MT ENDF MT value
//! \return Whether corresponding reaction is an inelastic scattering reaction
bool is_inelastic_scatter(int MT);
//==============================================================================
//! Abstract one-dimensional function
//==============================================================================
class Function1D {
public:
virtual double operator()(double x) const = 0;
virtual ~Function1D() = default;
};
//==============================================================================
//! One-dimensional function expressed as a polynomial
//==============================================================================
class Polynomial : public Function1D {
public:
//! Construct polynomial from HDF5 data
//! \param[in] dset Dataset containing coefficients
explicit Polynomial(hid_t dset);
//! Evaluate the polynomials
//! \param[in] x independent variable
//! \return Polynomial evaluated at x
double operator()(double x) const override;
private:
std::vector<double> coef_; //!< Polynomial coefficients
};
//==============================================================================
//! One-dimensional interpolable function
//==============================================================================
class Tabulated1D : public Function1D {
public:
Tabulated1D() = default;
//! Construct function from HDF5 data
//! \param[in] dset Dataset containing tabulated data
explicit Tabulated1D(hid_t dset);
//! Evaluate the tabulated function
//! \param[in] x independent variable
//! \return Function evaluated at x
double operator()(double x) const override;
// Accessors
const std::vector<double>& x() const { return x_; }
const std::vector<double>& y() const { return y_; }
private:
std::size_t n_regions_ {0}; //!< number of interpolation regions
std::vector<int> nbt_; //!< values separating interpolation regions
std::vector<Interpolation> int_; //!< interpolation schemes
std::size_t n_pairs_; //!< number of (x,y) pairs
std::vector<double> x_; //!< values of abscissa
std::vector<double> y_; //!< values of ordinate
};
//==============================================================================
//! Coherent elastic scattering data from a crystalline material
//==============================================================================
class CoherentElasticXS : public Function1D {
public:
explicit CoherentElasticXS(hid_t dset);
double operator()(double E) const override;
const std::vector<double>& bragg_edges() const { return bragg_edges_; }
const std::vector<double>& factors() const { return factors_; }
private:
std::vector<double> bragg_edges_; //!< Bragg edges in [eV]
std::vector<double> factors_; //!< Partial sums of structure factors [eV-b]
};
//==============================================================================
//! Incoherent elastic scattering cross section
//==============================================================================
class IncoherentElasticXS : public Function1D {
public:
explicit IncoherentElasticXS(hid_t dset);
double operator()(double E) const override;
private:
double bound_xs_; //!< Characteristic bound xs in [b]
double debye_waller_; //!< Debye-Waller integral divided by atomic mass in [eV^-1]
};
//! Read 1D function from HDF5 dataset
//! \param[in] group HDF5 group containing dataset
//! \param[in] name Name of dataset
//! \return Unique pointer to 1D function
std::unique_ptr<Function1D> read_function(hid_t group, const char* name);
} // namespace openmc
#endif // OPENMC_ENDF_H

71
include/openmc/error.h Normal file
View file

@ -0,0 +1,71 @@
#ifndef OPENMC_ERROR_H
#define OPENMC_ERROR_H
#include <cstring>
#include <string>
#include <sstream>
#include "openmc/capi.h"
#ifdef __GNUC__
#define UNREACHABLE() __builtin_unreachable()
#else
#define UNREACHABLE() (void)0
#endif
namespace openmc {
inline void
set_errmsg(const char* message)
{
std::strcpy(openmc_err_msg, message);
}
inline void
set_errmsg(const std::string& message)
{
std::strcpy(openmc_err_msg, message.c_str());
}
inline void
set_errmsg(const std::stringstream& message)
{
std::strcpy(openmc_err_msg, message.str().c_str());
}
[[noreturn]] void fatal_error(const std::string& message, int err=-1);
[[noreturn]] inline
void fatal_error(const std::stringstream& message)
{
fatal_error(message.str());
}
[[noreturn]] inline
void fatal_error(const char* message)
{
fatal_error(std::string{message, std::strlen(message)});
}
void warning(const std::string& message);
inline
void warning(const std::stringstream& message)
{
warning(message.str());
}
void write_message(const std::string& message, int level=0);
inline
void write_message(const std::stringstream& message, int level)
{
write_message(message.str(), level);
}
#ifdef OPENMC_MPI
extern "C" void abort_mpi(int code);
#endif
} // namespace openmc
#endif // OPENMC_ERROR_H

View file

@ -0,0 +1,20 @@
#ifndef OPENMC_FILE_UTILS_H
#define OPENMC_FILE_UTILS_H
#include <fstream> // for ifstream
#include <string>
namespace openmc {
//! Determine if a file exists
//! \param[in] filename Path to file
//! \return Whether file exists
inline bool file_exists(const std::string& filename)
{
std::ifstream s {filename};
return s.good();
}
} // namespace openmc
#endif // OPENMC_FILE_UTILS_H

View file

@ -0,0 +1,8 @@
#ifndef OPENMC_FINALIZE_H
#define OPENMC_FINALIZE_H
namespace openmc {
} // namespace openmc
#endif // OPENMC_FINALIZE_H

80
include/openmc/geometry.h Normal file
View file

@ -0,0 +1,80 @@
#ifndef OPENMC_GEOMETRY_H
#define OPENMC_GEOMETRY_H
#include <array>
#include <cmath>
#include <cstdint>
#include <vector>
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
namespace model {
extern int root_universe; //!< Index of root universe
extern int n_coord_levels; //!< Number of CSG coordinate levels
extern std::vector<int64_t> overlap_check_count;
} // namespace model
//==============================================================================
// Information about nearest boundary crossing
//==============================================================================
struct BoundaryInfo {
double distance {INFINITY}; //!< distance to nearest boundary
int surface_index {0}; //!< if boundary is surface, index in surfaces vector
int coord_level; //!< coordinate level after crossing boundary
std::array<int, 3> lattice_translation {}; //!< which way lattice indices will change
};
//==============================================================================
//! Check two distances by coincidence tolerance
//==============================================================================
inline bool coincident(double d1, double d2) {
return std::abs(d1 - d2) < FP_COINCIDENT;
}
//==============================================================================
//! Check for overlapping cells at a particle's position.
//==============================================================================
bool check_cell_overlap(Particle* p, bool error=true);
//==============================================================================
//! Locate a particle in the geometry tree and set its geometry data fields.
//!
//! \param p A particle to be located. This function will populate the
//! geometry-dependent data fields of the particle.
//! \param use_neighbor_lists If true, neighbor lists will be used to accelerate
//! the geometry search, but this only works if the cell attribute of the
//! particle's lowest coordinate level is valid and meaningful.
//! \return True if the particle's location could be found and ascribed to a
//! valid geometry coordinate stack.
//==============================================================================
bool find_cell(Particle* p, bool use_neighbor_lists);
//==============================================================================
//! Move a particle into a new lattice tile.
//==============================================================================
void cross_lattice(Particle* p, const BoundaryInfo& boundary);
//==============================================================================
//! Find the next boundary a particle will intersect.
//==============================================================================
BoundaryInfo distance_to_boundary(Particle* p);
} // namespace openmc
#endif // OPENMC_GEOMETRY_H

View file

@ -0,0 +1,118 @@
//! \file geometry_aux.h
//! Auxilary functions for geometry initialization and general data handling.
#ifndef OPENMC_GEOMETRY_AUX_H
#define OPENMC_GEOMETRY_AUX_H
#include <cstdint>
#include <string>
#include <vector>
namespace openmc {
void read_geometry_xml();
//==============================================================================
//! Replace Universe, Lattice, and Material IDs with indices.
//==============================================================================
void adjust_indices();
//==============================================================================
//! Assign defaults to cells with undefined temperatures.
//==============================================================================
void assign_temperatures();
//==============================================================================
//! \brief Obtain a list of temperatures that each nuclide/thermal scattering
//! table appears at in the model. Later, this list is used to determine the
//! actual temperatures to read (which may be different if interpolation is
//! used)
//!
//! \param[out] nuc_temps Vector of temperatures for each nuclide
//! \param[out] thermal_temps Vector of tempratures for each thermal scattering
//! table
//==============================================================================
void get_temperatures(std::vector<std::vector<double>>& nuc_temps,
std::vector<std::vector<double>>& thermal_temps);
//==============================================================================
//! \brief Perform final setup for geometry
//!
//! \param[out] nuc_temps Vector of temperatures for each nuclide
//! \param[out] thermal_temps Vector of tempratures for each thermal scattering
//! table
//==============================================================================
void finalize_geometry(std::vector<std::vector<double>>& nuc_temps,
std::vector<std::vector<double>>& thermal_temps);
//==============================================================================
//! Figure out which Universe is the root universe.
//!
//! This function looks for a universe that is not listed in a Cell::fill or in
//! a Lattice.
//! \return The index of the root universe.
//==============================================================================
int32_t find_root_universe();
//==============================================================================
//! Populate all data structures needed for distribcells.
//==============================================================================
void prepare_distribcell();
//==============================================================================
//! Recursively search through the geometry and count cell instances.
//!
//! This function will update the Cell::n_instances value for each cell in the
//! geometry.
//! \param univ_indx The index of the universe to begin searching from (probably
//! the root universe).
//==============================================================================
void count_cell_instances(int32_t univ_indx);
//==============================================================================
//! Recursively search through universes and count universe instances.
//! \param search_univ The index of the universe to begin searching from.
//! \param target_univ_id The ID of the universe to be counted.
//! \return The number of instances of target_univ_id in the geometry tree under
//! search_univ.
//==============================================================================
int count_universe_instances(int32_t search_univ, int32_t target_univ_id);
//==============================================================================
//! Build a character array representing the path to a distribcell instance.
//! \param target_cell The index of the Cell in the global Cell array.
//! \param map The index of the distribcell mapping corresponding to the target
//! cell.
//! \param target_offset An instance number for a distributed cell.
//! \return The unique traversal through the geometry tree that leads to the
//! desired instance of the target cell.
//==============================================================================
std::string
distribcell_path(int32_t target_cell, int32_t map, int32_t target_offset);
//==============================================================================
//! Determine the maximum number of nested coordinate levels in the geometry.
//! \param univ The index of the universe to begin seraching from (probably the
//! root universe).
//! \return The number of coordinate levels.
//==============================================================================
int maximum_levels(int32_t univ);
//==============================================================================
//! Deallocates global vectors and maps for cells, universes, and lattices.
//==============================================================================
void free_memory_geometry();
} // namespace openmc
#endif // OPENMC_GEOMETRY_AUX_H

View file

@ -0,0 +1,508 @@
#ifndef OPENMC_HDF5_INTERFACE_H
#define OPENMC_HDF5_INTERFACE_H
#include <algorithm> // for min
#include <array>
#include <complex>
#include <cstddef>
#include <cstring> // for strlen
#include <string>
#include <sstream>
#include <type_traits>
#include <vector>
#include "hdf5.h"
#include "hdf5_hl.h"
#include "xtensor/xadapt.hpp"
#include "xtensor/xarray.hpp"
#include "openmc/position.h"
#include "openmc/error.h"
namespace openmc {
//==============================================================================
// Low-level internal functions
//==============================================================================
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id,
void* buffer);
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
hid_t mem_type_id, const void* buffer);
void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id,
void* buffer, bool indep);
void write_dataset(hid_t group_id, int ndim, const hsize_t* dims, const char* name,
hid_t mem_type_id, const void* buffer, bool indep);
bool using_mpio_device(hid_t obj_id);
//==============================================================================
// Normal functions that are used to read/write files
//==============================================================================
hid_t create_group(hid_t parent_id, const std::string& name);
inline hid_t create_group(hid_t parent_id, const std::stringstream& name)
{return create_group(parent_id, name.str());}
hid_t file_open(const std::string& filename, char mode, bool parallel=false);
void write_string(hid_t group_id, const char* name, const std::string& buffer,
bool indep);
std::vector<hsize_t> attribute_shape(hid_t obj_id, const char* name);
std::vector<std::string> dataset_names(hid_t group_id);
void ensure_exists(hid_t obj_id, const char* name, bool attribute=false);
std::vector<std::string> group_names(hid_t group_id);
std::vector<hsize_t> object_shape(hid_t obj_id);
std::string object_name(hid_t obj_id);
//==============================================================================
// Fortran compatibility functions
//==============================================================================
extern "C" {
bool attribute_exists(hid_t obj_id, const char* name);
size_t attribute_typesize(hid_t obj_id, const char* name);
hid_t create_group(hid_t parent_id, const char* name);
void close_dataset(hid_t dataset_id);
void close_group(hid_t group_id);
int dataset_ndims(hid_t dset);
size_t dataset_typesize(hid_t obj_id, const char* name);
hid_t file_open(const char* filename, char mode, bool parallel);
void file_close(hid_t file_id);
void get_name(hid_t obj_id, char* name);
int get_num_datasets(hid_t group_id);
int get_num_groups(hid_t group_id);
void get_datasets(hid_t group_id, char* name[]);
void get_groups(hid_t group_id, char* name[]);
void get_shape(hid_t obj_id, hsize_t* dims);
void get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims);
bool object_exists(hid_t object_id, const char* name);
hid_t open_dataset(hid_t group_id, const char* name);
hid_t open_group(hid_t group_id, const char* name);
void read_attr_double(hid_t obj_id, const char* name, double* buffer);
void read_attr_int(hid_t obj_id, const char* name, int* buffer);
void read_attr_string(hid_t obj_id, const char* name, size_t slen,
char* buffer);
void read_complex(hid_t obj_id, const char* name,
std::complex<double>* buffer, bool indep);
void read_double(hid_t obj_id, const char* name, double* buffer,
bool indep);
void read_int(hid_t obj_id, const char* name, int* buffer,
bool indep);
void read_llong(hid_t obj_id, const char* name, long long* buffer,
bool indep);
void read_string(hid_t obj_id, const char* name, size_t slen,
char* buffer, bool indep);
void read_tally_results(hid_t group_id, hsize_t n_filter,
hsize_t n_score, double* results);
void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims,
const char* name, const double* buffer);
void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims,
const char* name, const int* buffer);
void write_attr_string(hid_t obj_id, const char* name, const char* buffer);
void write_double(hid_t group_id, int ndim, const hsize_t* dims,
const char* name, const double* buffer, bool indep);
void write_int(hid_t group_id, int ndim, const hsize_t* dims,
const char* name, const int* buffer, bool indep);
void write_llong(hid_t group_id, int ndim, const hsize_t* dims,
const char* name, const long long* buffer, bool indep);
void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen,
const char* name, char const* buffer, bool indep);
void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score,
const double* results);
} // extern "C"
//==============================================================================
// Template struct used to map types to HDF5 datatype IDs, which are stored
// using the type hid_t. By having a single static data member, the template can
// be specialized for each type we know of. The specializations appear in the
// .cpp file since they are definitions.
//==============================================================================
template<typename T>
struct H5TypeMap { static const hid_t type_id; };
//==============================================================================
// Templates/overloads for read_attribute
//==============================================================================
// Scalar version
template<typename T>
void read_attribute(hid_t obj_id, const char* name, T& buffer)
{
read_attr(obj_id, name, H5TypeMap<T>::type_id, &buffer);
}
// array version
template<typename T, std::size_t N> inline void
read_attribute(hid_t obj_id, const char* name, std::array<T, N>& buffer)
{
read_attr(obj_id, name, H5TypeMap<T>::type_id, buffer.data());
}
// vector version
template<typename T>
void read_attribute(hid_t obj_id, const char* name, std::vector<T>& vec)
{
// Get shape of attribute array
auto shape = attribute_shape(obj_id, name);
// Allocate new array to read data into
std::size_t size = 1;
for (const auto x : shape)
size *= x;
vec.resize(size);
// Read data from attribute
read_attr(obj_id, name, H5TypeMap<T>::type_id, vec.data());
}
// Generic array version
template<typename T>
void read_attribute(hid_t obj_id, const char* name, xt::xarray<T>& arr)
{
// Get shape of attribute array
auto shape = attribute_shape(obj_id, name);
// Allocate new array to read data into
std::size_t size = 1;
for (const auto x : shape)
size *= x;
std::vector<T> buffer(size);
// Read data from attribute
read_attr(obj_id, name, H5TypeMap<T>::type_id, buffer.data());
// Adapt array into xarray
arr = xt::adapt(buffer, shape);
}
// overload for std::string
inline void
read_attribute(hid_t obj_id, const char* name, std::string& str)
{
// Create buffer to read data into
auto n = attribute_typesize(obj_id, name);
char* buffer = new char[n];
// Read attribute and set string
read_attr_string(obj_id, name, n, buffer);
str = std::string{buffer, n};
delete[] buffer;
}
// overload for std::vector<std::string>
inline void
read_attribute(hid_t obj_id, const char* name, std::vector<std::string>& vec)
{
auto dims = attribute_shape(obj_id, name);
auto m = dims[0];
// Allocate a C char array to get strings
auto n = attribute_typesize(obj_id, name);
char* buffer = new char[m*n];
// Read char data in attribute
read_attr_string(obj_id, name, n, buffer);
for (int i = 0; i < m; ++i) {
// Determine proper length of string -- strlen doesn't work because
// buffer[i] might not have any null characters
std::size_t k = 0;
for (; k < n; ++k) if (buffer[i*n + k] == '\0') break;
// Create string based on (char*, size_t) constructor
vec.emplace_back(&buffer[i*n], k);
}
delete[] buffer;
}
//==============================================================================
// Templates/overloads for read_dataset and related methods
//==============================================================================
// Template for scalars. We need to be careful that the compiler does not use
// this version of read_dataset for vectors, arrays, or other non-scalar types.
// enable_if_t allows us to conditionally remove the function from overload
// resolution when the type T doesn't meet a certain criterion.
template<typename T> inline
std::enable_if_t<std::is_scalar<std::decay_t<T>>::value>
read_dataset(hid_t obj_id, const char* name, T& buffer, bool indep=false)
{
read_dataset(obj_id, name, H5TypeMap<T>::type_id, &buffer, indep);
}
// overload for std::string
inline void
read_dataset(hid_t obj_id, const char* name, std::string& str, bool indep=false)
{
// Create buffer to read data into
auto n = dataset_typesize(obj_id, name);
char* buffer = new char[n];
// Read attribute and set string
read_string(obj_id, name, n, buffer, indep);
str = std::string{buffer, n};
}
// array version
template<typename T, std::size_t N> inline void
read_dataset(hid_t dset, const char* name, std::array<T, N>& buffer, bool indep=false)
{
read_dataset(dset, name, H5TypeMap<T>::type_id, buffer.data(), indep);
}
// vector version
template <typename T>
void read_dataset(hid_t dset, std::vector<T>& vec, bool indep=false)
{
// Get shape of dataset
std::vector<hsize_t> shape = object_shape(dset);
// Resize vector to appropriate size
vec.resize(shape[0]);
// Read data into vector
read_dataset(dset, nullptr, H5TypeMap<T>::type_id, vec.data(), indep);
}
template <typename T>
void read_dataset(hid_t obj_id, const char* name, std::vector<T>& vec, bool indep=false)
{
hid_t dset = open_dataset(obj_id, name);
read_dataset(dset, vec, indep);
close_dataset(dset);
}
template <typename T>
void read_dataset(hid_t dset, xt::xarray<T>& arr, bool indep=false)
{
// Get shape of dataset
std::vector<hsize_t> shape = object_shape(dset);
// Allocate space in the array to read data into
std::size_t size = 1;
for (const auto x : shape)
size *= x;
arr.resize(shape);
// Read data from attribute
read_dataset(dset, nullptr, H5TypeMap<T>::type_id, arr.data(), indep);
}
template<>
void read_dataset(hid_t dset, xt::xarray<std::complex<double>>& arr, bool indep);
template <typename T>
void read_dataset(hid_t obj_id, const char* name, xt::xarray<T>& arr, bool indep=false)
{
// Open dataset and read array
hid_t dset = open_dataset(obj_id, name);
read_dataset(dset, arr, indep);
close_dataset(dset);
}
template <typename T, std::size_t N>
void read_dataset(hid_t obj_id, const char* name, xt::xtensor<T, N>& arr, bool indep=false)
{
// Open dataset and read array
hid_t dset = open_dataset(obj_id, name);
// Get shape of dataset
std::vector<hsize_t> hsize_t_shape = object_shape(dset);
close_dataset(dset);
// cast from hsize_t to size_t
std::vector<size_t> shape(hsize_t_shape.size());
for (int i = 0; i < shape.size(); i++) {
shape[i] = static_cast<size_t>(hsize_t_shape[i]);
}
// Allocate new xarray to read data into
xt::xarray<T> xarr(shape);
// Read data from the dataset
read_dataset(obj_id, name, xarr);
// Copy into xtensor
arr = xarr;
}
// overload for Position
inline void
read_dataset(hid_t obj_id, const char* name, Position& r, bool indep=false)
{
std::array<double, 3> x;
read_dataset(obj_id, name, x, indep);
r.x = x[0];
r.y = x[1];
r.z = x[2];
}
template <typename T, std::size_t N>
void read_dataset_as_shape(hid_t obj_id, const char* name,
xt::xtensor<T, N>& arr, bool indep=false)
{
hid_t dset = open_dataset(obj_id, name);
// Allocate new array to read data into
std::size_t size = 1;
for (const auto x : arr.shape())
size *= x;
std::vector<T> buffer(size);
// Read data from attribute
read_dataset(dset, nullptr, H5TypeMap<T>::type_id, buffer.data(), indep);
// Adapt into xarray
arr = xt::adapt(buffer, arr.shape());
close_dataset(dset);
}
template <typename T, std::size_t N>
void read_nd_vector(hid_t obj_id, const char* name, xt::xtensor<T, N>& result,
bool must_have=false)
{
if (object_exists(obj_id, name)) {
read_dataset_as_shape(obj_id, name, result, true);
} else if (must_have) {
fatal_error(std::string("Must provide " + std::string(name) + "!"));
}
}
//==============================================================================
// Templates/overloads for write_attribute
//==============================================================================
template<typename T> inline void
write_attribute(hid_t obj_id, const char* name, T buffer)
{
write_attr(obj_id, 0, nullptr, name, H5TypeMap<T>::type_id, &buffer);
}
inline void
write_attribute(hid_t obj_id, const char* name, const char* buffer)
{
write_attr_string(obj_id, name, buffer);
}
inline void
write_attribute(hid_t obj_id, const char* name, const std::string& buffer)
{
write_attr_string(obj_id, name, buffer.c_str());
}
template<typename T, std::size_t N> inline void
write_attribute(hid_t obj_id, const char* name, const std::array<T, N>& buffer)
{
hsize_t dims[] {N};
write_attr(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data());
}
template<typename T> inline void
write_attribute(hid_t obj_id, const char* name, const std::vector<T>& buffer)
{
hsize_t dims[] {buffer.size()};
write_attr(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data());
}
inline void
write_attribute(hid_t obj_id, const char* name, Position r)
{
std::array<double, 3> buffer {r.x, r.y, r.z};
write_attribute(obj_id, name, buffer);
}
//==============================================================================
// Templates/overloads for write_dataset
//==============================================================================
// Template for scalars (ensured by SFINAE)
template<typename T> inline
std::enable_if_t<std::is_scalar<std::decay_t<T>>::value>
write_dataset(hid_t obj_id, const char* name, T buffer)
{
write_dataset(obj_id, 0, nullptr, name, H5TypeMap<T>::type_id, &buffer, false);
}
inline void
write_dataset(hid_t obj_id, const char* name, const char* buffer)
{
write_string(obj_id, name, buffer, false);
}
template<typename T, std::size_t N> inline void
write_dataset(hid_t obj_id, const char* name, const std::array<T, N>& buffer)
{
hsize_t dims[] {N};
write_dataset(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data(), false);
}
inline void
write_dataset(hid_t obj_id, const char* name, const std::vector<std::string>& buffer)
{
auto n {buffer.size()};
hsize_t dims[] {n};
// Determine length of longest string, including \0
size_t m = 1;
for (const auto& s : buffer) {
m = std::max(m, s.size() + 1);
}
// Copy data into contiguous buffer
char* temp = new char[n*m];
std::fill(temp, temp + n*m, '\0');
for (int i = 0; i < n; ++i) {
std::copy(buffer[i].begin(), buffer[i].end(), temp + i*m);
}
// Write 2D data
write_string(obj_id, 1, dims, m, name, temp, false);
// Free temp array
delete[] temp;
}
template<typename T> inline void
write_dataset(hid_t obj_id, const char* name, const std::vector<T>& buffer)
{
hsize_t dims[] {buffer.size()};
write_dataset(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data(), false);
}
// Template for xarray, xtensor, etc.
template<typename D> inline void
write_dataset(hid_t obj_id, const char* name, const xt::xcontainer<D>& arr)
{
using T = typename D::value_type;
auto s = arr.shape();
std::vector<hsize_t> dims {s.cbegin(), s.cend()};
write_dataset(obj_id, dims.size(), dims.data(), name, H5TypeMap<T>::type_id,
arr.data(), false);
}
inline void
write_dataset(hid_t obj_id, const char* name, Position r)
{
std::array<double, 3> buffer {r.x, r.y, r.z};
write_dataset(obj_id, name, buffer);
}
inline void
write_dataset(hid_t obj_id, const char* name, std::string buffer)
{
write_string(obj_id, name, buffer.c_str(), false);
}
} // namespace openmc
#endif // OPENMC_HDF5_INTERFACE_H

View file

@ -0,0 +1,18 @@
#ifndef OPENMC_INITIALIZE_H
#define OPENMC_INITIALIZE_H
#ifdef OPENMC_MPI
#include "mpi.h"
#endif
namespace openmc {
int parse_command_line(int argc, char* argv[]);
#ifdef OPENMC_MPI
void initialize_mpi(MPI_Comm intracomm);
#endif
void read_input_xml();
}
#endif // OPENMC_INITIALIZE_H

294
include/openmc/lattice.h Normal file
View file

@ -0,0 +1,294 @@
#ifndef OPENMC_LATTICE_H
#define OPENMC_LATTICE_H
#include <array>
#include <cstdint>
#include <memory> // for unique_ptr
#include <string>
#include <unordered_map>
#include <vector>
#include "hdf5.h"
#include "pugixml.hpp"
#include "openmc/constants.h"
#include "openmc/position.h"
namespace openmc {
//==============================================================================
// Module constants
//==============================================================================
constexpr int32_t NO_OUTER_UNIVERSE{-1};
enum class LatticeType {
rect, hex
};
//==============================================================================
// Global variables
//==============================================================================
class Lattice;
namespace model {
extern std::vector<std::unique_ptr<Lattice>> lattices;
extern std::unordered_map<int32_t, int32_t> lattice_map;
} // namespace model
//==============================================================================
//! \class Lattice
//! \brief Abstract type for ordered array of universes.
//==============================================================================
class LatticeIter;
class ReverseLatticeIter;
class Lattice
{
public:
int32_t id_; //!< Universe ID number
std::string name_; //!< User-defined name
LatticeType type_;
std::vector<int32_t> universes_; //!< Universes filling each lattice tile
int32_t outer_ {NO_OUTER_UNIVERSE}; //!< Universe tiled outside the lattice
std::vector<int32_t> offsets_; //!< Distribcell offset table
explicit Lattice(pugi::xml_node lat_node);
virtual ~Lattice() {}
virtual int32_t& operator[](std::array<int, 3> i_xyz) = 0;
virtual LatticeIter begin();
LatticeIter end();
virtual ReverseLatticeIter rbegin();
ReverseLatticeIter rend();
//! Convert internal universe values from IDs to indices using universe_map.
void adjust_indices();
//! Allocate offset table for distribcell.
void allocate_offset_table(int n_maps)
{offsets_.resize(n_maps * universes_.size(), C_NONE);}
//! Populate the distribcell offset tables.
int32_t fill_offset_table(int32_t offset, int32_t target_univ_id, int map);
//! \brief Check lattice indices.
//! \param i_xyz[3] The indices for a lattice tile.
//! \return true if the given indices fit within the lattice bounds. False
//! otherwise.
virtual bool are_valid_indices(const int i_xyz[3]) const = 0;
bool
are_valid_indices(std::array<int, 3> i_xyz) const
{
int i_xyz_[3] {i_xyz[0], i_xyz[1], i_xyz[2]};
return are_valid_indices(i_xyz_);
}
//! \brief Find the next lattice surface crossing
//! \param r A 3D Cartesian coordinate.
//! \param u A 3D Cartesian direction.
//! \param i_xyz The indices for a lattice tile.
//! \return The distance to the next crossing and an array indicating how the
//! lattice indices would change after crossing that boundary.
virtual std::pair<double, std::array<int, 3>>
distance(Position r, Direction u, const std::array<int, 3>& i_xyz) const
= 0;
//! \brief Find the lattice tile indices for a given point.
//! \param r A 3D Cartesian coordinate.
//! \return An array containing the indices of a lattice tile.
virtual std::array<int, 3> get_indices(Position r, Direction u) const = 0;
//! \brief Get coordinates local to a lattice tile.
//! \param r A 3D Cartesian coordinate.
//! \param i_xyz The indices for a lattice tile.
//! \return Local 3D Cartesian coordinates.
virtual Position
get_local_position(Position r, const std::array<int, 3> i_xyz) const = 0;
//! \brief Check flattened lattice index.
//! \param indx The index for a lattice tile.
//! \return true if the given index fit within the lattice bounds. False
//! otherwise.
virtual bool is_valid_index(int indx) const
{return (indx >= 0) && (indx < universes_.size());}
//! \brief Get the distribcell offset for a lattice tile.
//! \param The map index for the target cell.
//! \param i_xyz[3] The indices for a lattice tile.
//! \return Distribcell offset i.e. the largest instance number for the target
//! cell found in the geometry tree under this lattice tile.
virtual int32_t& offset(int map, const int i_xyz[3]) = 0;
//! \brief Convert an array index to a useful human-readable string.
//! \param indx The index for a lattice tile.
//! \return A string representing the lattice tile.
virtual std::string index_to_string(int indx) const = 0;
//! \brief Write lattice information to an HDF5 group.
//! \param group_id An HDF5 group id.
void to_hdf5(hid_t group_id) const;
protected:
bool is_3d_; //!< Has divisions along the z-axis?
virtual void to_hdf5_inner(hid_t group_id) const = 0;
};
//==============================================================================
//! An iterator over lattice universes.
//==============================================================================
class LatticeIter
{
public:
int indx_; //!< An index to a Lattice universes or offsets array.
LatticeIter(Lattice &lat, int indx)
: indx_(indx), lat_(lat)
{}
bool operator==(const LatticeIter &rhs) {return (indx_ == rhs.indx_);}
bool operator!=(const LatticeIter &rhs) {return !(*this == rhs);}
int32_t& operator*() {return lat_.universes_[indx_];}
LatticeIter& operator++()
{
while (indx_ < lat_.universes_.size()) {
++indx_;
if (lat_.is_valid_index(indx_)) return *this;
}
indx_ = lat_.universes_.size();
return *this;
}
protected:
Lattice& lat_;
};
//==============================================================================
//! A reverse iterator over lattice universes.
//==============================================================================
class ReverseLatticeIter : public LatticeIter
{
public:
ReverseLatticeIter(Lattice &lat, int indx)
: LatticeIter {lat, indx}
{}
ReverseLatticeIter& operator++()
{
while (indx_ > -1) {
--indx_;
if (lat_.is_valid_index(indx_)) return *this;
}
indx_ = -1;
return *this;
}
};
//==============================================================================
class RectLattice : public Lattice
{
public:
explicit RectLattice(pugi::xml_node lat_node);
int32_t& operator[](std::array<int, 3> i_xyz);
bool are_valid_indices(const int i_xyz[3]) const;
std::pair<double, std::array<int, 3>>
distance(Position r, Direction u, const std::array<int, 3>& i_xyz) const;
std::array<int, 3> get_indices(Position r, Direction u) const;
Position
get_local_position(Position r, const std::array<int, 3> i_xyz) const;
int32_t& offset(int map, const int i_xyz[3]);
std::string index_to_string(int indx) const;
void to_hdf5_inner(hid_t group_id) const;
private:
std::array<int, 3> n_cells_; //!< Number of cells along each axis
Position lower_left_; //!< Global lower-left corner of the lattice
Position pitch_; //!< Lattice tile width along each axis
// Convenience aliases
int &nx {n_cells_[0]};
int &ny {n_cells_[1]};
int &nz {n_cells_[2]};
};
//==============================================================================
class HexLattice : public Lattice
{
public:
explicit HexLattice(pugi::xml_node lat_node);
int32_t& operator[](std::array<int, 3> i_xyz);
LatticeIter begin();
ReverseLatticeIter rbegin();
bool are_valid_indices(const int i_xyz[3]) const;
std::pair<double, std::array<int, 3>>
distance(Position r, Direction u, const std::array<int, 3>& i_xyz) const;
std::array<int, 3> get_indices(Position r, Direction u) const;
Position
get_local_position(Position r, const std::array<int, 3> i_xyz) const;
bool is_valid_index(int indx) const;
int32_t& offset(int map, const int i_xyz[3]);
std::string index_to_string(int indx) const;
void to_hdf5_inner(hid_t group_id) const;
private:
enum class Orientation {
y, //!< Flat side of lattice parallel to y-axis
x //!< Flat side of lattice parallel to x-axis
};
//! Fill universes_ vector for 'y' orientation
void fill_lattice_y(const std::vector<std::string>& univ_words);
//! Fill universes_ vector for 'x' orientation
void fill_lattice_x(const std::vector<std::string>& univ_words);
int n_rings_; //!< Number of radial tile positions
int n_axial_; //!< Number of axial tile positions
Orientation orientation_; //!< Orientation of lattice
Position center_; //!< Global center of lattice
std::array<double, 2> pitch_; //!< Lattice tile width and height
};
//==============================================================================
// Non-member functions
//==============================================================================
void read_lattices(pugi::xml_node node);
} // namespace openmc
#endif // OPENMC_LATTICE_H

204
include/openmc/material.h Normal file
View file

@ -0,0 +1,204 @@
#ifndef OPENMC_MATERIAL_H
#define OPENMC_MATERIAL_H
#include <memory> // for unique_ptr
#include <string>
#include <unordered_map>
#include <vector>
#include <gsl/gsl>
#include <hdf5.h>
#include "pugixml.hpp"
#include "xtensor/xtensor.hpp"
#include "openmc/bremsstrahlung.h"
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
class Material;
namespace model {
extern std::vector<std::unique_ptr<Material>> materials;
extern std::unordered_map<int32_t, int32_t> material_map;
} // namespace model
//==============================================================================
//! A substance with constituent nuclides and thermal scattering data
//==============================================================================
class Material
{
public:
//----------------------------------------------------------------------------
// Types
struct ThermalTable {
int index_table; //!< Index of table in data::thermal_scatt
int index_nuclide; //!< Index in nuclide_
double fraction; //!< How often to use table
};
//----------------------------------------------------------------------------
// Constructors, destructors, factory functions
Material() {};
explicit Material(pugi::xml_node material_node);
~Material();
//----------------------------------------------------------------------------
// Methods
void calculate_xs(Particle& p) const;
//! Assign thermal scattering tables to specific nuclides within the material
//! so the code knows when to apply bound thermal scattering data
void init_thermal();
//! Set up mapping between global nuclides vector and indices in nuclide_
void init_nuclide_index();
//! Finalize the material, assigning tables, normalize density, etc.
void finalize();
//! Write material data to HDF5
void to_hdf5(hid_t group) const;
//! Add nuclide to the material
//
//! \param[in] nuclide Name of the nuclide
//! \param[in] density Density of the nuclide in [atom/b-cm]
void add_nuclide(const std::string& nuclide, double density);
//! Set atom densities for the material
//
//! \param[in] name Name of each nuclide
//! \param[in] density Density of each nuclide in [atom/b-cm]
void set_densities(const std::vector<std::string>& name,
const std::vector<double>& density);
//----------------------------------------------------------------------------
// Accessors
//! Get density in [atom/b-cm]
//! \return Density in [atom/b-cm]
double density() const { return density_; }
//! Get density in [g/cm^3]
//! \return Density in [g/cm^3]
double density_gpcc() const { return density_gpcc_; }
//! Get name
//! \return Material name
const std::string& name() const { return name_; }
//! Set name
void set_name(const std::string& name) { name_ = name; }
//! Set total density of the material
//
//! \param[in] density Density value
//! \param[in] units Units of density
void set_density(double density, gsl::cstring_span units);
//! Get nuclides in material
//! \return Indices into the global nuclides vector
gsl::span<const int> nuclides() const { return {nuclide_.data(), nuclide_.size()}; }
//! Get densities of each nuclide in material
//! \return Densities in [atom/b-cm]
gsl::span<const double> densities() const { return {atom_density_.data(), atom_density_.size()}; }
//! Get ID of material
//! \return ID of material
int32_t id() const { return id_; }
//! Assign a unique ID to the material
//! \param[in] Unique ID to assign. A value of -1 indicates that an ID
//! should be automatically assigned.
void set_id(int32_t id);
//! Get whether material is fissionable
//! \return Whether material is fissionable
bool fissionable() const { return fissionable_; }
//! Get volume of material
//! \return Volume in [cm^3]
double volume() const;
//----------------------------------------------------------------------------
// Data
int32_t id_ {-1}; //!< Unique ID
std::string name_; //!< Name of material
std::vector<int> nuclide_; //!< Indices in nuclides vector
std::vector<int> element_; //!< Indices in elements vector
xt::xtensor<double, 1> atom_density_; //!< Nuclide atom density in [atom/b-cm]
double density_; //!< Total atom density in [atom/b-cm]
double density_gpcc_; //!< Total atom density in [g/cm^3]
double volume_ {-1.0}; //!< Volume in [cm^3]
bool fissionable_ {false}; //!< Does this material contain fissionable nuclides
bool depletable_ {false}; //!< Is the material depletable?
std::vector<bool> p0_; //!< Indicate which nuclides are to be treated with iso-in-lab scattering
// To improve performance of tallying, we store an array (direct address
// table) that indicates for each nuclide in data::nuclides the index of the
// corresponding nuclide in the nuclide_ vector. If it is not present in the
// material, the entry is set to -1.
std::vector<int> mat_nuclide_index_;
// Thermal scattering tables
std::vector<ThermalTable> thermal_tables_;
//! \brief Default temperature for cells containing this material.
//!
//! A negative value indicates no default temperature was specified.
double temperature_ {-1};
std::unique_ptr<Bremsstrahlung> ttb_;
private:
//----------------------------------------------------------------------------
// Private methods
//! Calculate the collision stopping power
void collision_stopping_power(double* s_col, bool positron);
//! Initialize bremsstrahlung data
void init_bremsstrahlung();
//! Normalize density
void normalize_density();
void calculate_neutron_xs(Particle& p) const;
void calculate_photon_xs(Particle& p) const;
//----------------------------------------------------------------------------
// Private data members
gsl::index index_;
};
//==============================================================================
// Non-member functions
//==============================================================================
//! Calculate Sternheimer adjustment factor
double sternheimer_adjustment(const std::vector<double>& f, const
std::vector<double>& e_b_sq, double e_p_sq, double n_conduction, double
log_I, double tol, int max_iter);
//! Calculate density effect correction
double density_effect(const std::vector<double>& f, const std::vector<double>&
e_b_sq, double e_p_sq, double n_conduction, double rho, double E, double tol,
int max_iter);
//! Read material data from materials.xml
void read_materials_xml();
void free_memory_material();
} // namespace openmc
#endif // OPENMC_MATERIAL_H

View file

@ -0,0 +1,277 @@
//! \file math_functions.h
//! A collection of elementary math functions.
#ifndef OPENMC_MATH_FUNCTIONS_H
#define OPENMC_MATH_FUNCTIONS_H
#include <cmath>
#include <complex>
#include <cstdlib>
#include "openmc/constants.h"
#include "openmc/position.h"
#include "openmc/random_lcg.h"
namespace openmc {
//==============================================================================
//! Calculate the percentile of the standard normal distribution with a
//! specified probability level.
//!
//! \param p The probability level
//! \return The requested percentile
//==============================================================================
extern "C" double normal_percentile(double p);
//==============================================================================
//! Calculate the percentile of the Student's t distribution with a specified
//! probability level and number of degrees of freedom.
//!
//! \param p The probability level
//! \param df The degrees of freedom
//! \return The requested percentile
//==============================================================================
extern "C" double t_percentile(double p, int df);
//==============================================================================
//! Calculate the n-th order Legendre polynomials at the value of x.
//!
//! \param n The maximum order requested
//! \param x The value to evaluate at; x is expected to be within [-1,1]
//! \param pnx The requested Legendre polynomials of order 0 to n (inclusive)
//! evaluated at x.
//==============================================================================
extern "C" void calc_pn_c(int n, double x, double pnx[]);
//==============================================================================
//! Find the value of f(x) given a set of Legendre coefficients and the value
//! of x.
//!
//! \param n The maximum order of the expansion
//! \param data The polynomial expansion coefficient data; without the (2l+1)/2
//! factor.
//! \param x The value to evaluate at; x is expected to be within [-1,1]
//! \return The requested Legendre polynomials of order 0 to n (inclusive)
//! evaluated at x
//==============================================================================
extern "C" double evaluate_legendre(int n, const double data[], double x);
//==============================================================================
//! Calculate the n-th order real spherical harmonics for a given angle (in
//! terms of (u,v,w)) for all 0<=n and -m<=n<=n.
//!
//! \param n The maximum order requested
//! \param uvw[3] The direction the harmonics are requested at
//! \param rn The requested harmonics of order 0 to n (inclusive)
//! evaluated at uvw.
//==============================================================================
extern "C" void calc_rn_c(int n, const double uvw[3], double rn[]);
void calc_rn(int n, Direction u, double rn[]);
//==============================================================================
//! Calculate the n-th order modified Zernike polynomial moment for a given
//! angle (rho, theta) location on the unit disk.
//!
//! This procedure uses the modified Kintner's method for calculating Zernike
//! polynomials as outlined in Chong, C. W., Raveendran, P., & Mukundan,
//! R. (2003). A comparative analysis of algorithms for fast computation of
//! Zernike moments. Pattern Recognition, 36(3), 731-742.
//! The normalization of the polynomials is such that the integral of Z_pq^2
//! over the unit disk is exactly pi.
//!
//! \param n The maximum order requested
//! \param rho The radial parameter to specify location on the unit disk
//! \param phi The angle parameter to specify location on the unit disk
//! \param zn The requested moments of order 0 to n (inclusive)
//! evaluated at rho and phi.
//==============================================================================
extern "C" void calc_zn(int n, double rho, double phi, double zn[]);
//==============================================================================
//! Calculate only the even radial components of n-th order modified Zernike
//! polynomial moment with azimuthal dependency m = 0 for a given angle
//! (rho, theta) location on the unit disk.
//!
//! Since m = 0, n could only be even orders. Z_q0 = R_q0
//!
//! This procedure uses the modified Kintner's method for calculating Zernike
//! polynomials as outlined in Chong, C. W., Raveendran, P., & Mukundan,
//! R. (2003). A comparative analysis of algorithms for fast computation of
//! Zernike moments. Pattern Recognition, 36(3), 731-742.
//! The normalization of the polynomials is such that the integral of Z_pq^2
//! over the unit disk is exactly pi.
//!
//! \param n The maximum order requested
//! \param rho The radial parameter to specify location on the unit disk
//! \param phi The angle parameter to specify location on the unit disk
//! \param zn_rad The requested moments of order 0 to n (inclusive)
//! evaluated at rho and phi when m = 0.
//==============================================================================
extern "C" void calc_zn_rad(int n, double rho, double zn_rad[]);
//==============================================================================
//! Rotate the direction cosines through a polar angle whose cosine is mu and
//! through an azimuthal angle sampled uniformly.
//!
//! This is done with direct sampling rather than rejection sampling as is done
//! in MCNP and Serpent.
//!
//! \param uvw[3] The initial, and final, direction vector
//! \param mu The cosine of angle in lab or CM
//! \param phi The azimuthal angle; will randomly chosen angle if a nullptr
//! is passed
//==============================================================================
extern "C" void rotate_angle_c(double uvw[3], double mu, const double* phi);
Direction rotate_angle(Direction u, double mu, const double* phi);
//==============================================================================
//! Samples an energy from the Maxwell fission distribution based on a direct
//! sampling scheme.
//!
//! The probability distribution function for a Maxwellian is given as
//! p(x) = 2/(T*sqrt(pi))*sqrt(x/T)*exp(-x/T). This PDF can be sampled using
//! rule C64 in the Monte Carlo Sampler LA-9721-MS.
//!
//! \param T The tabulated function of the incoming energy
//! \return The sampled outgoing energy
//==============================================================================
extern "C" double maxwell_spectrum(double T);
//==============================================================================
//! Samples an energy from a Watt energy-dependent fission distribution.
//!
//! Although fitted parameters exist for many nuclides, generally the
//! continuous tabular distributions (LAW 4) should be used in lieu of the Watt
//! spectrum. This direct sampling scheme is an unpublished scheme based on the
//! original Watt spectrum derivation (See F. Brown's MC lectures).
//!
//! \param a Watt parameter a
//! \param b Watt parameter b
//! \return The sampled outgoing energy
//==============================================================================
extern "C" double watt_spectrum(double a, double b);
//==============================================================================
//! Samples an energy from the Gaussian energy-dependent fission distribution.
//!
//! Samples from a Normal distribution with a given mean and standard deviation
//! The PDF is defined as s(x) = (1/2*sigma*sqrt(2) * e-((mu-x)/2*sigma)^2
//! Its sampled according to
//! http://www-pdg.lbl.gov/2009/reviews/rpp2009-rev-monte-carlo-techniques.pdf
//! section 33.4.4
//!
//! @param mean mean of the Gaussian distribution
//! @param std_dev standard deviation of the Gaussian distribution
//! @result The sampled outgoing energy
//==============================================================================
extern "C" double normal_variate(double mean, double std_dev);
//==============================================================================
//! Samples an energy from the Muir (Gaussian) energy-dependent distribution.
//!
//! This is another form of the Gaussian distribution but with more easily
//! modifiable parameters
//! https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-05411-MS
//!
//! @param e0 peak neutron energy [eV]
//! @param m_rat ratio of the fusion reactants to AMU
//! @param kt the ion temperature of the reactants [eV]
//! @result The sampled outgoing energy
//==============================================================================
extern "C" double muir_spectrum(double e0, double m_rat, double kt);
//==============================================================================
//! Doppler broadens the windowed multipole curvefit.
//!
//! The curvefit is a polynomial of the form a/E + b/sqrt(E) + c + d sqrt(E)...
//!
//! \param E The energy to evaluate the broadening at
//! \param dopp sqrt(atomic weight ratio / kT) with kT given in eV
//! \param n The number of components to the polynomial
//! \param factors The output leading coefficient
//==============================================================================
extern "C" void broaden_wmp_polynomials(double E, double dopp, int n, double factors[]);
//==============================================================================
//! Constructs a natural cubic spline.
//!
//! Given a tabulated function y_i = f(x_i), this computes the second
//! derivative of the interpolating function at each x_i, which can then be
//! used in any subsequent calls to spline_interpolate or spline_integrate for
//! the same set of x and y values.
//!
//! \param n Number of points
//! \param x Values of the independent variable, which must be strictly
//! increasing.
//! \param y Values of the dependent variable.
//! \param[out] z The second derivative of the interpolating function at each
//! value of x.
//==============================================================================
void spline(int n, const double x[], const double y[], double z[]);
//==============================================================================
//! Determine the cubic spline interpolated y-value for a given x-value.
//!
//! \param n Number of points
//! \param x Values of the independent variable, which must be strictly
//! increasing.
//! \param y Values of the dependent variable.
//! \param z The second derivative of the interpolating function at each
//! value of x.
//! \param xint Point at which to evaluate the cubic spline polynomial
//! \return Interpolated value
//==============================================================================
double spline_interpolate(int n, const double x[], const double y[],
const double z[], double xint);
//==============================================================================
//! Evaluate the definite integral of the interpolating cubic spline between
//! the given endpoints.
//!
//! \param n Number of points
//! \param x Values of the independent variable, which must be strictly
//! increasing.
//! \param y Values of the dependent variable.
//! \param z The second derivative of the interpolating function at each
//! value of x.
//! \param xa Lower limit of integration
//! \param xb Upper limit of integration
//! \return Integral
//==============================================================================
double spline_integrate(int n, const double x[], const double y[],
const double z[], double xa, double xb);
//! Evaluate the Faddeeva function
//!
//! \param z Complex argument
//! \return Faddeeva function evaluated at z
std::complex<double> faddeeva(std::complex<double> z);
//! Evaluate derivative of the Faddeeva function
//!
//! \param z Complex argument
//! \param order Order of the derivative
//! \return Derivative of Faddeeva function evaluated at z
std::complex<double> w_derivative(std::complex<double> z, int order);
} // namespace openmc
#endif // OPENMC_MATH_FUNCTIONS_H

246
include/openmc/mesh.h Normal file
View file

@ -0,0 +1,246 @@
//! \file mesh.h
//! \brief Mesh types used for tallies, Shannon entropy, CMFD, etc.
#ifndef OPENMC_MESH_H
#define OPENMC_MESH_H
#include <memory> // for unique_ptr
#include <vector>
#include <unordered_map>
#include "hdf5.h"
#include "pugixml.hpp"
#include "xtensor/xtensor.hpp"
#include "openmc/particle.h"
#include "openmc/position.h"
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
class Mesh;
namespace model {
extern std::vector<std::unique_ptr<Mesh>> meshes;
extern std::unordered_map<int32_t, int32_t> mesh_map;
} // namespace model
class Mesh
{
public:
// Constructors and destructor
Mesh() = default;
Mesh(pugi::xml_node node);
virtual ~Mesh() = default;
// Methods
//! Determine which bins were crossed by a particle
//
//! \param[in] p Particle to check
//! \param[out] bins Bins that were crossed
//! \param[out] lengths Fraction of tracklength in each bin
virtual void bins_crossed(const Particle* p, std::vector<int>& bins,
std::vector<double>& lengths) const = 0;
//! Determine which surface bins were crossed by a particle
//
//! \param[in] p Particle to check
//! \param[out] bins Surface bins that were crossed
virtual void
surface_bins_crossed(const Particle* p, std::vector<int>& bins) const = 0;
//! Get bin at a given position in space
//
//! \param[in] r Position to get bin for
//! \return Mesh bin
virtual int get_bin(Position r) const = 0;
//! Get bin given mesh indices
//
//! \param[in] Array of mesh indices
//! \return Mesh bin
virtual int get_bin_from_indices(const int* ijk) const = 0;
//! Get mesh indices given a position
//
//! \param[in] r Position to get indices for
//! \param[out] ijk Array of mesh indices
//! \param[out] in_mesh Whether position is in mesh
virtual void get_indices(Position r, int* ijk, bool* in_mesh) const = 0;
//! Get mesh indices corresponding to a mesh bin
//
//! \param[in] bin Mesh bin
//! \param[out] ijk Mesh indices
virtual void get_indices_from_bin(int bin, int* ijk) const = 0;
//! Get the number of mesh cells.
virtual int n_bins() const = 0;
//! Get the number of mesh cell surfaces.
virtual int n_surface_bins() const = 0;
//! Find the mesh lines that intersect an axis-aligned slice plot
//
//! \param[in] plot_ll The lower-left coordinates of the slice plot.
//! \param[in] plot_ur The upper-right coordinates of the slice plot.
//! \return A pair of vectors indicating where the mesh lines lie along each
//! of the plot's axes. For example an xy-slice plot will get back a vector
//! of x-coordinates and another of y-coordinates. These vectors may be
//! empty for low-dimensional meshes.
virtual std::pair<std::vector<double>, std::vector<double>>
plot(Position plot_ll, Position plot_ur) const = 0;
//! Write mesh data to an HDF5 group
//
//! \param[in] group HDF5 group
virtual void to_hdf5(hid_t group) const = 0;
// Data members
int id_ {-1}; //!< User-specified ID
int n_dimension_; //!< Number of dimensions
xt::xtensor<double, 1> lower_left_; //!< Lower-left coordinates of mesh
xt::xtensor<double, 1> upper_right_; //!< Upper-right coordinates of mesh
};
//==============================================================================
//! Tessellation of n-dimensional Euclidean space by congruent squares or cubes
//==============================================================================
class RegularMesh : public Mesh
{
public:
// Constructors
RegularMesh() = default;
RegularMesh(pugi::xml_node node);
// Overriden methods
void bins_crossed(const Particle* p, std::vector<int>& bins,
std::vector<double>& lengths) const override;
void surface_bins_crossed(const Particle* p, std::vector<int>& bins)
const override;
int get_bin(Position r) const override;
int get_bin_from_indices(const int* ijk) const override;
void get_indices(Position r, int* ijk, bool* in_mesh) const override;
void get_indices_from_bin(int bin, int* ijk) const override;
int n_bins() const override;
int n_surface_bins() const override;
std::pair<std::vector<double>, std::vector<double>>
plot(Position plot_ll, Position plot_ur) const override;
void to_hdf5(hid_t group) const override;
// New methods
//! Check where a line segment intersects the mesh and if it intersects at all
//
//! \param[in,out] r0 In: starting position, out: intersection point
//! \param[in] r1 Ending position
//! \param[out] ijk Indices of the mesh bin containing the intersection point
//! \return Whether the line segment connecting r0 and r1 intersects mesh
bool intersects(Position& r0, Position r1, int* ijk) const;
//! Count number of bank sites in each mesh bin / energy bin
//
//! \param[in] bank Array of bank sites
//! \param[out] Whether any bank sites are outside the mesh
//! \return Array indicating number of sites in each mesh/energy bin
xt::xtensor<double, 1> count_sites(const std::vector<Particle::Bank>& bank,
bool* outside) const;
// Data members
double volume_frac_; //!< Volume fraction of each mesh element
xt::xtensor<int, 1> shape_; //!< Number of mesh elements in each dimension
xt::xtensor<double, 1> width_; //!< Width of each mesh element
private:
bool intersects_1d(Position& r0, Position r1, int* ijk) const;
bool intersects_2d(Position& r0, Position r1, int* ijk) const;
bool intersects_3d(Position& r0, Position r1, int* ijk) const;
};
class RectilinearMesh : public Mesh
{
public:
// Constructors
RectilinearMesh(pugi::xml_node node);
// Overriden methods
void bins_crossed(const Particle* p, std::vector<int>& bins,
std::vector<double>& lengths) const override;
void surface_bins_crossed(const Particle* p, std::vector<int>& bins)
const override;
int get_bin(Position r) const override;
int get_bin_from_indices(const int* ijk) const override;
void get_indices(Position r, int* ijk, bool* in_mesh) const override;
void get_indices_from_bin(int bin, int* ijk) const override;
int n_bins() const override;
int n_surface_bins() const override;
std::pair<std::vector<double>, std::vector<double>>
plot(Position plot_ll, Position plot_ur) const override;
void to_hdf5(hid_t group) const override;
// New methods
//! Check where a line segment intersects the mesh and if it intersects at all
//
//! \param[in,out] r0 In: starting position, out: intersection point
//! \param[in] r1 Ending position
//! \param[out] ijk Indices of the mesh bin containing the intersection point
//! \return Whether the line segment connecting r0 and r1 intersects mesh
bool intersects(Position& r0, Position r1, int* ijk) const;
// Data members
xt::xtensor<int, 1> shape_; //!< Number of mesh elements in each dimension
private:
std::vector<std::vector<double>> grid_;
};
//==============================================================================
// Non-member functions
//==============================================================================
//! Read meshes from either settings/tallies
//
//! \param[in] root XML node
void read_meshes(pugi::xml_node root);
//! Write mesh data to an HDF5 group
//
//! \param[in] group HDF5 group
void meshes_to_hdf5(hid_t group);
void free_memory_mesh();
} // namespace openmc
#endif // OPENMC_MESH_H

View file

@ -0,0 +1,23 @@
#ifndef OPENMC_MESSAGE_PASSING_H
#define OPENMC_MESSAGE_PASSING_H
#ifdef OPENMC_MPI
#include <mpi.h>
#endif
namespace openmc {
namespace mpi {
extern int rank;
extern int n_procs;
extern bool master;
#ifdef OPENMC_MPI
extern MPI_Datatype bank;
extern MPI_Comm intracomm;
#endif
} // namespace mpi
} // namespace openmc
#endif // OPENMC_MESSAGE_PASSING_H

183
include/openmc/mgxs.h Normal file
View file

@ -0,0 +1,183 @@
//! \file mgxs.h
//! A collection of classes for Multi-Group Cross Section data
#ifndef OPENMC_MGXS_H
#define OPENMC_MGXS_H
#include <string>
#include <vector>
#include "xtensor/xtensor.hpp"
#include "openmc/constants.h"
#include "openmc/hdf5_interface.h"
#include "openmc/xsdata.h"
namespace openmc {
//==============================================================================
// Cache contains the cached data for an MGXS object
//==============================================================================
struct CacheData {
double sqrtkT; // last temperature corresponding to t
int t; // temperature index
int a; // angle index
// last angle that corresponds to a
double u;
double v;
double w;
};
//==============================================================================
// MGXS contains the mgxs data for a nuclide/material
//==============================================================================
class Mgxs {
private:
xt::xtensor<double, 1> kTs; // temperature in eV (k * T)
int scatter_format; // flag for if this is legendre, histogram, or tabular
int num_delayed_groups; // number of delayed neutron groups
int num_groups; // number of energy groups
std::vector<XsData> xs; // Cross section data
// MGXS Incoming Flux Angular grid information
bool is_isotropic; // used to skip search for angle indices if isotropic
int n_pol;
int n_azi;
std::vector<double> polar;
std::vector<double> azimuthal;
//! \brief Initializes the Mgxs object metadata
//!
//! @param in_name Name of the object.
//! @param in_awr atomic-weight ratio.
//! @param in_kTs temperatures (in units of eV) that data is available.
//! @param in_fissionable Is this item fissionable or not.
//! @param in_scatter_format Denotes whether Legendre, Tabular, or
//! Histogram scattering is used.
//! @param in_is_isotropic Is this an isotropic or angular with respect to
//! the incoming particle.
//! @param in_polar Polar angle grid.
//! @param in_azimuthal Azimuthal angle grid.
void
init(const std::string& in_name, double in_awr, const std::vector<double>& in_kTs,
bool in_fissionable, int in_scatter_format, bool in_is_isotropic,
const std::vector<double>& in_polar, const std::vector<double>& in_azimuthal);
//! \brief Initializes the Mgxs object metadata from the HDF5 file
//!
//! @param xs_id HDF5 group id for the cross section data.
//! @param temperature Temperatures to read.
//! @param temps_to_read Resultant list of temperatures in the library
//! to read which correspond to the requested temperatures.
//! @param order_dim Resultant dimensionality of the scattering order.
void
metadata_from_hdf5(hid_t xs_id, const std::vector<double>& temperature,
std::vector<int>& temps_to_read, int& order_dim);
//! \brief Performs the actual act of combining the microscopic data for a
//! single temperature.
//!
//! @param micros Microscopic objects to combine.
//! @param scalars Scalars to multiply the microscopic data by.
//! @param micro_ts The temperature index of the microscopic objects that
//! corresponds to the temperature of interest.
//! @param this_t The temperature index of the macroscopic object.
void
combine(const std::vector<Mgxs*>& micros, const std::vector<double>& scalars,
const std::vector<int>& micro_ts, int this_t);
//! \brief Checks to see if this and that are able to be combined
//!
//! This comparison is used when building macroscopic cross sections
//! from microscopic cross sections.
//! @param that The other Mgxs to compare to this one.
//! @return True if they can be combined, False otherwise.
bool equiv(const Mgxs& that);
public:
std::string name; // name of dataset, e.g., UO2
double awr; // atomic weight ratio
bool fissionable; // Is this fissionable
std::vector<CacheData> cache; // index and data cache
Mgxs() = default;
//! \brief Constructor that loads the Mgxs object from the HDF5 file
//!
//! @param xs_id HDF5 group id for the cross section data.
//! @param temperature Temperatures to read.
Mgxs(hid_t xs_id, const std::vector<double>& temperature);
//! \brief Constructor that initializes and populates all data to build a
//! macroscopic cross section from microscopic cross section.
//!
//! @param in_name Name of the object.
//! @param mat_kTs temperatures (in units of eV) that data is needed.
//! @param micros Microscopic objects to combine.
//! @param atom_densities Atom densities of those microscopic quantities.
Mgxs(const std::string& in_name, const std::vector<double>& mat_kTs,
const std::vector<Mgxs*>& micros, const std::vector<double>& atom_densities);
//! \brief Provides a cross section value given certain parameters
//!
//! @param xstype Type of cross section requested, according to the
//! enumerated constants.
//! @param gin Incoming energy group.
//! @param gout Outgoing energy group; use nullptr if irrelevant, or if a
//! sum is requested.
//! @param mu Cosine of the change-in-angle, for scattering quantities;
//! use nullptr if irrelevant.
//! @param dg delayed group index; use nullptr if irrelevant.
//! @return Requested cross section value.
double
get_xs(int xstype, int gin, const int* gout, const double* mu,
const int* dg);
//! \brief Samples the fission neutron energy and if prompt or delayed.
//!
//! @param gin Incoming energy group.
//! @param dg Sampled delayed group index.
//! @param gout Sampled outgoing energy group.
void
sample_fission_energy(int gin, int& dg, int& gout);
//! \brief Samples the outgoing energy and angle from a scatter event.
//!
//! @param gin Incoming energy group.
//! @param gout Sampled outgoing energy group.
//! @param mu Sampled cosine of the change-in-angle.
//! @param wgt Weight of the particle to be adjusted.
void
sample_scatter(int gin, int& gout, double& mu, double& wgt);
//! \brief Calculates cross section quantities needed for tracking.
//!
//! @param gin Incoming energy group.
//! @param sqrtkT Temperature of the material.
//! @param u Incoming particle direction.
//! @param total_xs Resultant total cross section.
//! @param abs_xs Resultant absorption cross section.
//! @param nu_fiss_xs Resultant nu-fission cross section.
void
calculate_xs(int gin, double sqrtkT, Direction u,
double& total_xs, double& abs_xs, double& nu_fiss_xs);
//! \brief Sets the temperature index in cache given a temperature
//!
//! @param sqrtkT Temperature of the material.
void
set_temperature_index(double sqrtkT);
//! \brief Sets the angle index in cache given a direction
//!
//! @param u Incoming particle direction.
void
set_angle_index(Direction u);
};
} // namespace openmc
#endif // OPENMC_MGXS_H

View file

@ -0,0 +1,81 @@
//! \file mgxs_interface.h
//! A collection of C interfaces to the C++ Mgxs class
#ifndef OPENMC_MGXS_INTERFACE_H
#define OPENMC_MGXS_INTERFACE_H
#include "hdf5_interface.h"
#include "mgxs.h"
#include <vector>
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
namespace data {
extern std::vector<Mgxs> nuclides_MG;
extern std::vector<Mgxs> macro_xs;
extern int num_energy_groups;
extern int num_delayed_groups;
extern std::vector<double> energy_bins;
extern std::vector<double> energy_bin_avg;
extern std::vector<double> rev_energy_bins;
} // namespace data
//==============================================================================
// Mgxs data loading interface methods
//==============================================================================
void read_mgxs();
void
add_mgxs(hid_t file_id, const std::string& name,
const std::vector<double>& temperature);
void create_macro_xs();
std::vector<std::vector<double>> get_mat_kTs();
void read_mg_cross_sections_header();
//==============================================================================
// Mgxs tracking/transport/tallying interface methods
//==============================================================================
extern "C" void
calculate_xs_c(int i_mat, int gin, double sqrtkT, Direction u,
double& total_xs, double& abs_xs, double& nu_fiss_xs);
double
get_nuclide_xs(int index, int xstype, int gin, const int* gout,
const double* mu, const int* dg);
inline double
get_nuclide_xs(int index, int xstype, int gin)
{return get_nuclide_xs(index, xstype, gin, nullptr, nullptr, nullptr);}
double
get_macro_xs(int index, int xstype, int gin, const int* gout,
const double* mu, const int* dg);
inline double
get_macro_xs(int index, int xstype, int gin)
{return get_macro_xs(index, xstype, gin, nullptr, nullptr, nullptr);}
//==============================================================================
// General Mgxs methods
//==============================================================================
extern "C" void
get_name_c(int index, int name_len, char* name);
extern "C" double
get_awr_c(int index);
} // namespace openmc
#endif // OPENMC_MGXS_INTERFACE_H

View file

@ -0,0 +1,68 @@
#ifndef OPENMC_NEIGHBOR_LIST_H
#define OPENMC_NEIGHBOR_LIST_H
#include <algorithm>
#include <cstdint>
#include <forward_list>
#include <mutex>
#include "openmc/openmp_interface.h"
namespace openmc {
//==============================================================================
//! A threadsafe, dynamic container for listing neighboring cells.
//
//! This container is a reduced interface for a linked list with an added OpenMP
//! lock for write operations. It allows for threadsafe dynamic growth; any
//! number of threads can safely read data without locks or reference counting.
//==============================================================================
class NeighborList
{
public:
using value_type = int32_t;
using const_iterator = std::forward_list<value_type>::const_iterator;
// Attempt to add an element.
//
// If the relevant OpenMP lock is currently owned by another thread, this
// function will return without actually modifying the data. It has been
// found that returning the transport calculation and possibly re-adding the
// element later is slightly faster than waiting on the lock to be released.
void push_back(int new_elem)
{
// Try to acquire the lock.
std::unique_lock<OpenMPMutex> lock(mutex_, std::try_to_lock);
if (lock) {
// It is possible another thread already added this element to the list
// while this thread was searching for a cell so make sure the given
// element isn't a duplicate before adding it.
if (std::find(list_.cbegin(), list_.cend(), new_elem) == list_.cend()) {
// Find the end of the list and add the the new element there.
if (!list_.empty()) {
auto it1 = list_.cbegin();
auto it2 = ++list_.cbegin();
while (it2 != list_.cend()) it1 = it2++;
list_.insert_after(it1, new_elem);
} else {
list_.push_front(new_elem);
}
}
}
}
const_iterator cbegin() const
{return list_.cbegin();}
const_iterator cend() const
{return list_.cend();}
private:
std::forward_list<value_type> list_;
OpenMPMutex mutex_;
};
} // namespace openmc
#endif // OPENMC_NEIGHBOR_LIST_H

148
include/openmc/nuclide.h Normal file
View file

@ -0,0 +1,148 @@
//! \file nuclide.h
//! \brief Nuclide type and other associated types/data
#ifndef OPENMC_NUCLIDE_H
#define OPENMC_NUCLIDE_H
#include <array>
#include <memory> // for unique_ptr
#include <unordered_map>
#include <vector>
#include <hdf5.h>
#include "openmc/constants.h"
#include "openmc/endf.h"
#include "openmc/particle.h"
#include "openmc/reaction.h"
#include "openmc/reaction_product.h"
#include "openmc/urr.h"
#include "openmc/wmp.h"
namespace openmc {
//==============================================================================
// Data for a nuclide
//==============================================================================
class Nuclide {
public:
// Types, aliases
using EmissionMode = ReactionProduct::EmissionMode;
struct EnergyGrid {
std::vector<int> grid_index;
std::vector<double> energy;
};
// Constructors
Nuclide(hid_t group, const std::vector<double>& temperature, int i_nuclide);
//! Initialize logarithmic grid for energy searches
void init_grid();
void calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle& p);
void calculate_sab_xs(int i_sab, double sab_frac, Particle& p);
// Methods
double nu(double E, EmissionMode mode, int group=0) const;
void calculate_elastic_xs(Particle& p) const;
//! Determines the microscopic 0K elastic cross section at a trial relative
//! energy used in resonance scattering
double elastic_xs_0K(double E) const;
//! \brief Determines cross sections in the unresolved resonance range
//! from probability tables.
void calculate_urr_xs(int i_temp, Particle& p) const;
// Data members
std::string name_; //!< Name of nuclide, e.g. "U235"
int Z_; //!< Atomic number
int A_; //!< Mass number
int metastable_; //!< Metastable state
double awr_; //!< Atomic weight ratio
int i_nuclide_; //!< Index in the nuclides array
// Temperature dependent cross section data
std::vector<double> kTs_; //!< temperatures in eV (k*T)
std::vector<EnergyGrid> grid_; //!< Energy grid at each temperature
std::vector<xt::xtensor<double, 2>> xs_; //!< Cross sections at each temperature
// Multipole data
std::unique_ptr<WindowedMultipole> multipole_;
// Fission data
bool fissionable_ {false}; //!< Whether nuclide is fissionable
bool has_partial_fission_ {false}; //!< has partial fission reactions?
std::vector<Reaction*> fission_rx_; //!< Fission reactions
int n_precursor_ {0}; //!< Number of delayed neutron precursors
std::unique_ptr<Function1D> total_nu_; //!< Total neutron yield
std::unique_ptr<Function1D> fission_q_prompt_; //!< Prompt fission energy release
std::unique_ptr<Function1D> fission_q_recov_; //!< Recoverable fission energy release
// Resonance scattering information
bool resonant_ {false};
std::vector<double> energy_0K_;
std::vector<double> elastic_0K_;
std::vector<double> xs_cdf_;
// Unresolved resonance range information
bool urr_present_ {false};
int urr_inelastic_ {C_NONE};
std::vector<UrrData> urr_data_;
std::vector<std::unique_ptr<Reaction>> reactions_; //!< Reactions
std::array<size_t, 902> reaction_index_; //!< Index of each reaction
std::vector<int> index_inelastic_scatter_;
private:
void create_derived();
static int XS_TOTAL;
static int XS_ABSORPTION;
static int XS_FISSION;
static int XS_NU_FISSION;
static int XS_PHOTON_PROD;
};
//==============================================================================
// Non-member functions
//==============================================================================
//! Checks for the right version of nuclear data within HDF5 files
void check_data_version(hid_t file_id);
bool multipole_in_range(const Nuclide* nuc, double E);
//==============================================================================
// Global variables
//==============================================================================
namespace data {
// Minimum/maximum transport energy for each particle type. Order corresponds to
// that of the ParticleType enum
extern std::array<double, 2> energy_min;
extern std::array<double, 2> energy_max;
//! Minimum temperature in [K] that nuclide data is available at
extern double temperature_min;
//! Maximum temperature in [K] that nuclide data is available at
extern double temperature_max;
extern std::vector<std::unique_ptr<Nuclide>> nuclides;
extern std::unordered_map<std::string, int> nuclide_map;
} // namespace data
//==============================================================================
// Non-member functions
//==============================================================================
void nuclides_clear();
} // namespace openmc
#endif // OPENMC_NUCLIDE_H

View file

@ -0,0 +1,77 @@
#ifndef OPENMC_OPENMP_INTERFACE_H
#define OPENMC_OPENMP_INTERFACE_H
#ifdef _OPENMP
#include <omp.h>
#endif
namespace openmc {
//==============================================================================
//! An object used to prevent concurrent access to a piece of data.
//
//! This type meets the C++ "Lockable" requirements.
//==============================================================================
class OpenMPMutex
{
public:
OpenMPMutex()
{
#ifdef _OPEMP
omp_init_lock(&mutex_);
#endif
}
~OpenMPMutex()
{
#ifdef _OPEMP
omp_destroy_lock(&mutex_);
#endif
}
// Mutexes cannot be copied. We need to explicitly delete the copy
// constructor and copy assignment operator to ensure the compiler doesn't
// "help" us by implicitly trying to copy the underlying mutexes.
OpenMPMutex(const OpenMPMutex&) = delete;
OpenMPMutex& operator= (const OpenMPMutex&) = delete;
//! Lock the mutex.
//
//! This function blocks execution until the lock succeeds.
void lock()
{
#ifdef _OPEMP
omp_set_lock(&mutex_);
#endif
}
//! Try to lock the mutex and indicate success.
//
//! This function does not block. It returns immediately and gives false if
//! the lock is unavailable.
bool try_lock() noexcept
{
#ifdef _OPEMP
return omp_test_lock(&mutex_);
#else
return true;
#endif
}
//! Unlock the mutex.
void unlock() noexcept
{
#ifdef _OPEMP
omp_unset_lock(&mutex_);
#endif
}
private:
#ifdef _OPEMP
omp_lock_t mutex_;
#endif
};
} // namespace openmc
#endif // OPENMC_OPENMP_INTERFACE_H

62
include/openmc/output.h Normal file
View file

@ -0,0 +1,62 @@
//! \file output.h
//! Functions for ASCII output.
#ifndef OPENMC_OUTPUT_H
#define OPENMC_OUTPUT_H
#include <string>
#include "openmc/particle.h"
namespace openmc {
//! \brief Display the main title banner as well as information about the
//! program developers, version, and date/time which the problem was run.
void title();
//! Display a header block.
//
//! \param msg The main text of the header
//! \param level The lowest verbosity level at which this header is printed
void header(const char* msg, int level);
//! Retrieve a time stamp.
//
//! \return current time stamp (format: "yyyy-mm-dd hh:mm:ss")
std::string time_stamp();
//! Display the attributes of a particle.
extern "C" void print_particle(Particle* p);
//! Display plot information.
void print_plot();
//! Display information regarding cell overlap checking.
void print_overlap_check();
//! Display information about command line usage of OpenMC
void print_usage();
//! Display current version and copright/license information
void print_version();
//! Display header listing what physical values will displayed
void print_columns();
//! Display information about a generation of neutrons
void print_generation();
//! \brief Display last batch's tallied value of the neutron multiplication
//! factor as well as the average value if we're in active batches
void print_batch_keff();
//! Display time elapsed for various stages of a run
void print_runtime();
//! Display results for global tallies including k-effective estimators
void print_results();
void write_tallies();
} // namespace openmc
#endif // OPENMC_OUTPUT_H

292
include/openmc/particle.h Normal file
View file

@ -0,0 +1,292 @@
#ifndef OPENMC_PARTICLE_H
#define OPENMC_PARTICLE_H
//! \file particle.h
//! \brief Particle type
#include <array>
#include <cstdint>
#include <memory> // for unique_ptr
#include <sstream>
#include <string>
#include <vector>
#include "openmc/constants.h"
#include "openmc/position.h"
namespace openmc {
//==============================================================================
// Constants
//==============================================================================
// Since cross section libraries come with different numbers of delayed groups
// (e.g. ENDF/B-VII.1 has 6 and JEFF 3.1.1 has 8 delayed groups) and we don't
// yet know what cross section library is being used when the tallies.xml file
// is read in, we want to have an upper bound on the size of the array we
// use to store the bins for delayed group tallies.
constexpr int MAX_DELAYED_GROUPS {8};
// Maximum number of lost particles
constexpr int MAX_LOST_PARTICLES {10};
// Maximum number of lost particles, relative to the total number of particles
constexpr double REL_MAX_LOST_PARTICLES {1.0e-6};
constexpr double CACHE_INVALID {-1.0};
//==============================================================================
// Class declarations
//==============================================================================
class LocalCoord {
public:
void rotate(const std::vector<double>& rotation);
//! clear data from a single coordinate level
void reset();
Position r; //!< particle position
Direction u; //!< particle direction
int cell {-1};
int universe {-1};
int lattice {-1};
int lattice_x {-1};
int lattice_y {-1};
int lattice_z {-1};
bool rotated {false}; //!< Is the level rotated?
};
//==============================================================================
//! Cached microscopic cross sections for a particular nuclide at the current
//! energy
//==============================================================================
struct NuclideMicroXS {
// Microscopic cross sections in barns
double total; //!< total cross section
double absorption; //!< absorption (disappearance)
double fission; //!< fission
double nu_fission; //!< neutron production from fission
double elastic; //!< If sab_frac is not 1 or 0, then this value is
//!< averaged over bound and non-bound nuclei
double thermal; //!< Bound thermal elastic & inelastic scattering
double thermal_elastic; //!< Bound thermal elastic scattering
double photon_prod; //!< microscopic photon production xs
// Cross sections for depletion reactions (note that these are not stored in
// macroscopic cache)
double reaction[DEPLETION_RX.size()];
// Indicies and factors needed to compute cross sections from the data tables
int index_grid; //!< Index on nuclide energy grid
int index_temp; //!< Temperature index for nuclide
double interp_factor; //!< Interpolation factor on nuc. energy grid
int index_sab {-1}; //!< Index in sab_tables
int index_temp_sab; //!< Temperature index for sab_tables
double sab_frac; //!< Fraction of atoms affected by S(a,b)
bool use_ptable; //!< In URR range with probability tables?
// Energy and temperature last used to evaluate these cross sections. If
// these values have changed, then the cross sections must be re-evaluated.
double last_E {0.0}; //!< Last evaluated energy
double last_sqrtkT {0.0}; //!< Last temperature in sqrt(Boltzmann constant
//!< * temperature (eV))
};
//==============================================================================
//! Cached microscopic photon cross sections for a particular element at the
//! current energy
//==============================================================================
struct ElementMicroXS {
int index_grid; //!< index on element energy grid
double last_E {0.0}; //!< last evaluated energy in [eV]
double interp_factor; //!< interpolation factor on energy grid
double total; //!< microscopic total photon xs
double coherent; //!< microscopic coherent xs
double incoherent; //!< microscopic incoherent xs
double photoelectric; //!< microscopic photoelectric xs
double pair_production; //!< microscopic pair production xs
};
//==============================================================================
// MACROXS contains cached macroscopic cross sections for the material a
// particle is traveling through
//==============================================================================
struct MacroXS {
double total; //!< macroscopic total xs
double absorption; //!< macroscopic absorption xs
double fission; //!< macroscopic fission xs
double nu_fission; //!< macroscopic production xs
double photon_prod; //!< macroscopic photon production xs
// Photon cross sections
double coherent; //!< macroscopic coherent xs
double incoherent; //!< macroscopic incoherent xs
double photoelectric; //!< macroscopic photoelectric xs
double pair_production; //!< macroscopic pair production xs
};
//============================================================================
//! State of a particle being transported through geometry
//============================================================================
class Particle {
public:
//==========================================================================
// Aliases and type definitions
//! Particle types
enum class Type {
neutron, photon, electron, positron
};
//! Saved ("banked") state of a particle
struct Bank {
Position r;
Direction u;
double E;
double wgt;
int delayed_group;
Type particle;
};
//==========================================================================
// Constructors
Particle();
//==========================================================================
// Methods and accessors
// Accessors for position in global coordinates
Position& r() { return coord_[0].r; }
const Position& r() const { return coord_[0].r; }
// Accessors for position in local coordinates
Position& r_local() { return coord_[n_coord_ - 1].r; }
const Position& r_local() const { return coord_[n_coord_ - 1].r; }
// Accessors for direction in global coordinates
Direction& u() { return coord_[0].u; }
const Direction& u() const { return coord_[0].u; }
// Accessors for direction in local coordinates
Direction& u_local() { return coord_[n_coord_ - 1].u; }
const Direction& u_local() const { return coord_[n_coord_ - 1].u; }
//! resets all coordinate levels for the particle
void clear();
//! create a secondary particle
//
//! stores the current phase space attributes of the particle in the
//! secondary bank and increments the number of sites in the secondary bank.
//! \param u Direction of the secondary particle
//! \param E Energy of the secondary particle in [eV]
//! \param type Particle type
void create_secondary(Direction u, double E, Type type);
//! initialize from a source site
//
//! initializes a particle from data stored in a source site. The source
//! site may have been produced from an external source, from fission, or
//! simply as a secondary particle.
//! \param src Source site data
void from_source(const Bank* src);
//! Transport a particle from birth to death
void transport();
//! Cross a surface and handle boundary conditions
void cross_surface();
//! mark a particle as lost and create a particle restart file
//! \param message A warning message to display
void mark_as_lost(const char* message);
void mark_as_lost(const std::string& message)
{mark_as_lost(message.c_str());}
void mark_as_lost(const std::stringstream& message)
{mark_as_lost(message.str());}
//! create a particle restart HDF5 file
void write_restart() const;
//==========================================================================
// Data members
// Cross section caches
std::vector<NuclideMicroXS> neutron_xs_; //!< Microscopic neutron cross sections
std::vector<ElementMicroXS> photon_xs_; //!< Microscopic photon cross sections
MacroXS macro_xs_; //!< Macroscopic cross sections
int64_t id_; //!< Unique ID
Type type_ {Type::neutron}; //!< Particle type (n, p, e, etc.)
int n_coord_ {1}; //!< number of current coordinate levels
int cell_instance_; //!< offset for distributed properties
std::vector<LocalCoord> coord_; //!< coordinates for all levels
// Particle coordinates before crossing a surface
int n_coord_last_ {1}; //!< number of current coordinates
std::vector<int> cell_last_; //!< coordinates for all levels
// Energy data
double E_; //!< post-collision energy in eV
double E_last_; //!< pre-collision energy in eV
int g_ {0}; //!< post-collision energy group (MG only)
int g_last_; //!< pre-collision energy group (MG only)
// Other physical data
double wgt_ {1.0}; //!< particle weight
double mu_; //!< angle of scatter
bool alive_ {true}; //!< is particle alive?
// Other physical data
Position r_last_current_; //!< coordinates of the last collision or
//!< reflective/periodic surface crossing for
//!< current tallies
Position r_last_; //!< previous coordinates
Direction u_last_; //!< previous direction coordinates
double wgt_last_ {1.0}; //!< pre-collision particle weight
double wgt_absorb_ {0.0}; //!< weight absorbed for survival biasing
// What event took place
bool fission_ {false}; //!< did particle cause implicit fission
int event_; //!< scatter, absorption
int event_nuclide_; //!< index in nuclides array
int event_mt_; //!< reaction MT
int delayed_group_ {0}; //!< delayed group
// Post-collision physical data
int n_bank_ {0}; //!< number of fission sites banked
int n_bank_second_ {0}; //!< number of secondary particles banked
double wgt_bank_ {0.0}; //!< weight of fission sites banked
int n_delayed_bank_[MAX_DELAYED_GROUPS]; //!< number of delayed fission
//!< sites banked
// Indices for various arrays
int surface_ {0}; //!< index for surface particle is on
int cell_born_ {-1}; //!< index for cell particle was born in
int material_ {-1}; //!< index for current material
int material_last_ {-1}; //!< index for last material
// Temperature of current cell
double sqrtkT_ {-1.0}; //!< sqrt(k_Boltzmann * temperature) in eV
double sqrtkT_last_ {0.0}; //!< last temperature
// Statistical data
int n_collision_ {0}; //!< number of collisions
// Track output
bool write_track_ {false};
};
} // namespace openmc
#endif // OPENMC_PARTICLE_H

View file

@ -0,0 +1,10 @@
#ifndef OPENMC_PARTICLE_RESTART_H
#define OPENMC_PARTICLE_RESTART_H
namespace openmc {
void run_particle_restart();
} // namespace openmc
#endif // OPENMC_PARTICLE_RESTART_H

126
include/openmc/photon.h Normal file
View file

@ -0,0 +1,126 @@
#ifndef OPENMC_PHOTON_H
#define OPENMC_PHOTON_H
#include "openmc/endf.h"
#include "openmc/particle.h"
#include <hdf5.h>
#include "xtensor/xtensor.hpp"
#include <string>
#include <unordered_map>
#include <utility> // for pair
#include <vector>
namespace openmc {
//==============================================================================
//! Photon interaction data for a single element
//==============================================================================
class ElectronSubshell {
public:
// Constructors
ElectronSubshell() { };
int index_subshell; //!< index in SUBSHELLS
int threshold;
double n_electrons;
double binding_energy;
xt::xtensor<double, 1> cross_section;
// Transition data
int n_transitions;
xt::xtensor<int, 2> transition_subshells;
xt::xtensor<double, 1> transition_energy;
xt::xtensor<double, 1> transition_probability;
};
class PhotonInteraction {
public:
// Constructors
PhotonInteraction(hid_t group, int i_element);
// Methods
void calculate_xs(Particle& p) const;
void compton_scatter(double alpha, bool doppler, double* alpha_out,
double* mu, int* i_shell) const;
double rayleigh_scatter(double alpha) const;
void pair_production(double alpha, double* E_electron, double* E_positron,
double* mu_electron, double* mu_positron) const;
void atomic_relaxation(const ElectronSubshell& shell, Particle& p) const;
// Data members
std::string name_; //!< Name of element, e.g. "Zr"
int Z_; //!< Atomic number
int i_element_; //!< Index in global elements vector
// Microscopic cross sections
xt::xtensor<double, 1> energy_;
xt::xtensor<double, 1> coherent_;
xt::xtensor<double, 1> incoherent_;
xt::xtensor<double, 1> photoelectric_total_;
xt::xtensor<double, 1> pair_production_total_;
xt::xtensor<double, 1> pair_production_electron_;
xt::xtensor<double, 1> pair_production_nuclear_;
xt::xtensor<double, 1> heating_;
// Form factors
Tabulated1D incoherent_form_factor_;
Tabulated1D coherent_int_form_factor_;
Tabulated1D coherent_anomalous_real_;
Tabulated1D coherent_anomalous_imag_;
// Photoionization and atomic relaxation data
std::unordered_map<int, int> shell_map_; //!< Given a shell designator, e.g. 3, this
//!< dictionary gives an index in shells_
std::vector<ElectronSubshell> shells_;
// Compton profile data
xt::xtensor<double, 2> profile_pdf_;
xt::xtensor<double, 2> profile_cdf_;
xt::xtensor<double, 1> binding_energy_;
xt::xtensor<double, 1> electron_pdf_;
// Stopping power data
double I_; // mean excitation energy
xt::xtensor<int, 1> n_electrons_;
xt::xtensor<double, 1> ionization_energy_;
xt::xtensor<double, 1> stopping_power_radiative_;
// Bremsstrahlung scaled DCS
xt::xtensor<double, 2> dcs_;
private:
void compton_doppler(double alpha, double mu, double* E_out, int* i_shell) const;
};
//==============================================================================
// Non-member functions
//==============================================================================
std::pair<double, double> klein_nishina(double alpha);
void free_memory_photon();
//==============================================================================
// Global variables
//==============================================================================
namespace data {
extern xt::xtensor<double, 1> compton_profile_pz; //! Compton profile momentum grid
//! Photon interaction data for each element
extern std::vector<PhotonInteraction> elements;
extern std::unordered_map<std::string, int> element_map;
} // namespace data
} // namespace openmc
#endif // OPENMC_PHOTON_H

93
include/openmc/physics.h Normal file
View file

@ -0,0 +1,93 @@
#ifndef OPENMC_PHYSICS_H
#define OPENMC_PHYSICS_H
#include "openmc/bank.h"
#include "openmc/nuclide.h"
#include "openmc/particle.h"
#include "openmc/position.h"
#include "openmc/reaction.h"
#include <vector>
namespace openmc {
//==============================================================================
// Non-member functions
//==============================================================================
//! Sample a nuclide and reaction and then calls the appropriate routine
void collision(Particle* p);
//! Samples an incident neutron reaction
void sample_neutron_reaction(Particle* p);
//! Samples an element based on the macroscopic cross sections for each nuclide
//! within a material and then samples a reaction for that element and calls the
//! appropriate routine to process the physics.
void sample_photon_reaction(Particle* p);
//! Terminates the particle and either deposits all energy locally
//! (electron_treatment = ELECTRON_LED) or creates secondary bremsstrahlung
//! photons from electron deflections with charged particles (electron_treatment
//! = ELECTRON_TTB).
void sample_electron_reaction(Particle* p);
//! Terminates the particle and either deposits all energy locally
//! (electron_treatment = ELECTRON_LED) or creates secondary bremsstrahlung
//! photons from electron deflections with charged particles (electron_treatment
//! = ELECTRON_TTB). Two annihilation photons of energy MASS_ELECTRON_EV (0.511
//! MeV) are created and travel in opposite directions.
void sample_positron_reaction(Particle* p);
//! Sample a nuclide based on their total cross sections and densities within
//! the current material
//!
//! \param[in] p Particle
//! \return Index in the data::nuclides vector
int sample_nuclide(const Particle* p);
//! Determine the average total, prompt, and delayed neutrons produced from
//! fission and creates appropriate bank sites.
void create_fission_sites(Particle* p, int i_nuclide, const Reaction* rx,
std::vector<Particle::Bank>& bank);
int sample_element(Particle* p);
Reaction* sample_fission(int i_nuclide, const Particle* p);
void sample_photon_product(int i_nuclide, const Particle* p, int* i_rx, int* i_product);
void absorption(Particle* p, int i_nuclide);
void scatter(Particle*, int i_nuclide);
//! Treats the elastic scattering of a neutron with a target.
void elastic_scatter(int i_nuclide, const Reaction& rx, double kT,
Particle* p);
void sab_scatter(int i_nuclide, int i_sab, Particle* p);
//! samples the target velocity. The constant cross section free gas model is
//! the default method. Methods for correctly accounting for the energy
//! dependence of cross sections in treating resonance elastic scattering such
//! as the DBRC and a new, accelerated scheme are also implemented here.
Direction sample_target_velocity(const Nuclide* nuc, double E, Direction u,
Direction v_neut, double xs_eff, double kT);
//! samples a target velocity based on the free gas scattering formulation, used
//! by most Monte Carlo codes, in which cross section is assumed to be constant
//! in energy. Excellent documentation for this method can be found in
//! FRA-TM-123.
Direction sample_cxs_target_velocity(double awr, double E, Direction u, double kT);
void sample_fission_neutron(int i_nuclide, const Reaction* rx, double E_in, Particle::Bank* site);
//! handles all reactions with a single secondary neutron (other than fission),
//! i.e. level scattering, (n,np), (n,na), etc.
void inelastic_scatter(const Nuclide* nuc, const Reaction* rx, Particle* p);
void sample_secondary_photons(Particle* p, int i_nuclide);
} // namespace openmc
#endif // OPENMC_PHYSICS_H

View file

@ -0,0 +1,16 @@
//! \file physics_common.h
//! A collection of physics methods common to MG, CE, photon, etc.
#ifndef OPENMC_PHYSICS_COMMON_H
#define OPENMC_PHYSICS_COMMON_H
#include "openmc/particle.h"
namespace openmc {
//! \brief Performs the russian roulette operation for a particle
extern "C" void
russian_roulette(Particle* p);
} // namespace openmc
#endif // OPENMC_PHYSICS_COMMON_H

View file

@ -0,0 +1,46 @@
//! \file physics_mg.h
//! Methods needed to perform the collision physics for multi-group mode
#ifndef OPENMC_PHYSICS_MG_H
#define OPENMC_PHYSICS_MG_H
#include "openmc/capi.h"
#include "openmc/particle.h"
#include "openmc/nuclide.h"
#include <vector>
namespace openmc {
//! \brief samples particle behavior after a collision event.
//! \param p Particle to operate on
void
collision_mg(Particle* p);
//! \brief samples a reaction type.
//!
//! Note that there is special logic when suvival biasing is turned on since
//! fission and disappearance are treated implicitly.
//! \param p Particle to operate on
void
sample_reaction(Particle* p);
//! \brief Samples the scattering event
//! \param p Particle to operate on
void
scatter(Particle* p);
//! \brief Determines the average total, prompt and delayed neutrons produced
//! from fission and creates the appropriate bank sites.
//! \param p Particle to operate on
//! \param bank The particle bank to populate
void
create_fission_sites(Particle* p, std::vector<Particle::Bank>& bank);
//! \brief Handles an absorption event
//! \param p Particle to operate on
void
absorption(Particle* p);
} // namespace openmc
#endif // OPENMC_PHYSICS_MG_H

292
include/openmc/plot.h Normal file
View file

@ -0,0 +1,292 @@
#ifndef OPENMC_PLOT_H
#define OPENMC_PLOT_H
#include <unordered_map>
#include <sstream>
#include "pugixml.hpp"
#include "xtensor/xarray.hpp"
#include "hdf5.h"
#include "openmc/position.h"
#include "openmc/constants.h"
#include "openmc/cell.h"
#include "openmc/geometry.h"
#include "openmc/particle.h"
#include "openmc/xml_interface.h"
namespace openmc {
//===============================================================================
// Global variables
//===============================================================================
class Plot;
namespace model {
extern std::vector<Plot> plots; //!< Plot instance container
extern std::unordered_map<int, int> plot_map; //!< map of plot ids to index
} // namespace model
//===============================================================================
// RGBColor holds color information for plotted objects
//===============================================================================
struct RGBColor {
//Constructors
RGBColor() : red(0), green(0), blue(0) { };
RGBColor(const int v[3]) : red(v[0]), green(v[1]), blue(v[2]) { };
RGBColor(int r, int g, int b) : red(r), green(g), blue(b) { };
RGBColor(const std::vector<int> &v) {
if (v.size() != 3) {
throw std::out_of_range("Incorrect vector size for RGBColor.");
}
red = v[0];
green = v[1];
blue = v[2];
}
bool operator ==(const RGBColor& other) {
return red == other.red && green == other.green && blue == other.blue;
}
// Members
uint8_t red, green, blue;
};
// some default colors
const RGBColor WHITE {255, 255, 255};
const RGBColor RED {255, 0, 0};
typedef xt::xtensor<RGBColor, 2> ImageData;
struct IdData {
// Constructor
IdData(size_t h_res, size_t v_res);
// Methods
void set_value(size_t y, size_t x, const Particle& p, int level);
void set_overlap(size_t y, size_t x);
// Members
xt::xtensor<int32_t, 3> data_; //!< 2D array of cell & material ids
};
struct PropertyData {
// Constructor
PropertyData(size_t h_res, size_t v_res);
// Methods
void set_value(size_t y, size_t x, const Particle& p, int level);
void set_overlap(size_t y, size_t x);
// Members
xt::xtensor<double, 3> data_; //!< 2D array of temperature & density data
};
enum class PlotType {
slice = 1,
voxel = 2
};
enum class PlotBasis {
xy = 1,
xz = 2,
yz = 3
};
enum class PlotColorBy {
cells = 0,
mats = 1
};
//===============================================================================
// Plot class
//===============================================================================
class PlotBase {
public:
template<class T> T get_map() const;
// Members
public:
Position origin_; //!< Plot origin in geometry
Position width_; //!< Plot width in geometry
PlotBasis basis_; //!< Plot basis (XY/XZ/YZ)
std::array<size_t, 3> pixels_; //!< Plot size in pixels
bool color_overlaps_; //!< Show overlapping cells?
int level_; //!< Plot universe level
};
template<class T>
T PlotBase::get_map() const {
size_t width = pixels_[0];
size_t height = pixels_[1];
// get pixel size
double in_pixel = (width_[0])/static_cast<double>(width);
double out_pixel = (width_[1])/static_cast<double>(height);
// size data array
T data(width, height);
// setup basis indices and initial position centered on pixel
int in_i, out_i;
Position xyz = origin_;
switch(basis_) {
case PlotBasis::xy :
in_i = 0;
out_i = 1;
break;
case PlotBasis::xz :
in_i = 0;
out_i = 2;
break;
case PlotBasis::yz :
in_i = 1;
out_i = 2;
break;
#ifdef __GNUC__
default:
__builtin_unreachable();
#endif
}
// set initial position
xyz[in_i] = origin_[in_i] - width_[0] / 2. + in_pixel / 2.;
xyz[out_i] = origin_[out_i] + width_[1] / 2. - out_pixel / 2.;
// arbitrary direction
Direction dir = {0.7071, 0.7071, 0.0};
#pragma omp parallel
{
Particle p;
p.r() = xyz;
p.u() = dir;
p.coord_[0].universe = model::root_universe;
int level = level_;
int j{};
#pragma omp for
for (int y = 0; y < height; y++) {
p.r()[out_i] = xyz[out_i] - out_pixel * y;
for (int x = 0; x < width; x++) {
p.r()[in_i] = xyz[in_i] + in_pixel * x;
p.n_coord_ = 1;
// local variables
bool found_cell = find_cell(&p, 0);
j = p.n_coord_ - 1;
if (level >=0) {j = level + 1;}
if (found_cell) {
data.set_value(y, x, p, j);
}
if (color_overlaps_ && check_cell_overlap(&p, false)) {
data.set_overlap(y, x);
}
} // inner for
} // outer for
} // omp parallel
return data;
}
class Plot : public PlotBase {
public:
// Constructor
Plot(pugi::xml_node plot);
// Methods
private:
void set_id(pugi::xml_node plot_node);
void set_type(pugi::xml_node plot_node);
void set_output_path(pugi::xml_node plot_node);
void set_bg_color(pugi::xml_node plot_node);
void set_basis(pugi::xml_node plot_node);
void set_origin(pugi::xml_node plot_node);
void set_width(pugi::xml_node plot_node);
void set_universe(pugi::xml_node plot_node);
void set_default_colors(pugi::xml_node plot_node);
void set_user_colors(pugi::xml_node plot_node);
void set_meshlines(pugi::xml_node plot_node);
void set_mask(pugi::xml_node plot_node);
void set_overlap_color(pugi::xml_node plot_node);
// Members
public:
int id_; //!< Plot ID
PlotType type_; //!< Plot type (Slice/Voxel)
PlotColorBy color_by_; //!< Plot coloring (cell/material)
int meshlines_width_; //!< Width of lines added to the plot
int index_meshlines_mesh_ {-1}; //!< Index of the mesh to draw on the plot
RGBColor meshlines_color_; //!< Color of meshlines on the plot
RGBColor not_found_ {WHITE}; //!< Plot background color
RGBColor overlap_color_ {RED}; //!< Plot overlap color
std::vector<RGBColor> colors_; //!< Plot colors
std::string path_plot_; //!< Plot output filename
};
//===============================================================================
// Non-member functions
//===============================================================================
//! Add mesh lines to image data of a plot object
//! \param[in] plot object
//! \param[out] image data associated with the plot object
void draw_mesh_lines(Plot pl, ImageData& data);
//! Write a ppm image to file using a plot object's image data
//! \param[in] plot object
//! \param[out] image data associated with the plot object
void output_ppm(Plot pl, const ImageData& data);
//! Initialize a voxel file
//! \param[in] id of an open hdf5 file
//! \param[in] dimensions of the voxel file (dx, dy, dz)
//! \param[out] dataspace pointer to voxel data
//! \param[out] dataset pointer to voxesl data
//! \param[out] pointer to memory space of voxel data
void voxel_init(hid_t file_id, const hsize_t* dims, hid_t* dspace,
hid_t* dset, hid_t* memspace);
//! Write a section of the voxel data to hdf5
//! \param[in] voxel slice
//! \param[out] dataspace pointer to voxel data
//! \param[out] dataset pointer to voxesl data
//! \param[out] pointer to data to write
void voxel_write_slice(int x, hid_t dspace, hid_t dset,
hid_t memspace, void* buf);
//! Close voxel file entities
//! \param[in] data space to close
//! \param[in] dataset to close
//! \param[in] memory space to close
void voxel_finalize(hid_t dspace, hid_t dset, hid_t memspace);
//===============================================================================
// External functions
//===============================================================================
//! Read plot specifications from a plots.xml file
void read_plots_xml();
//! Create a ppm image for a plot object
//! \param[in] plot object
void create_ppm(Plot pl);
//! Create an hdf5 voxel file for a plot object
//! \param[in] plot object
void create_voxel(Plot pl);
//! Create a randomly generated RGB color
//! \return RGBColor with random value
RGBColor random_color();
} // namespace openmc
#endif // OPENMC_PLOT_H

108
include/openmc/position.h Normal file
View file

@ -0,0 +1,108 @@
#ifndef OPENMC_POSITION_H
#define OPENMC_POSITION_H
#include <array>
#include <cmath> // for sqrt
#include <iostream>
#include <stdexcept> // for out_of_range
#include <vector>
namespace openmc {
//==============================================================================
//! Type representing a position in Cartesian coordinates
//==============================================================================
struct Position {
// Constructors
Position() = default;
Position(double x_, double y_, double z_) : x{x_}, y{y_}, z{z_} { };
Position(const double xyz[]) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} { };
Position(const std::vector<double>& xyz) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} { };
Position(const std::array<double, 3>& xyz) : x{xyz[0]}, y{xyz[1]}, z{xyz[2]} { };
// Unary operators
Position& operator+=(Position);
Position& operator+=(double);
Position& operator-=(Position);
Position& operator-=(double);
Position& operator*=(Position);
Position& operator*=(double);
Position& operator/=(Position);
Position& operator/=(double);
Position operator-() const;
const double& operator[](int i) const {
switch (i) {
case 0: return x;
case 1: return y;
case 2: return z;
default:
throw std::out_of_range{"Index in Position must be between 0 and 2."};
}
}
double& operator[](int i) {
switch (i) {
case 0: return x;
case 1: return y;
case 2: return z;
default:
throw std::out_of_range{"Index in Position must be between 0 and 2."};
}
}
// Other member functions
//! Dot product of two vectors
//! \param[in] other Vector to take dot product with
//! \result Resulting dot product
inline double dot(Position other) const {
return x*other.x + y*other.y + z*other.z;
}
inline double norm() const {
return std::sqrt(x*x + y*y + z*z);
}
//! Rotate the position based on a rotation matrix
Position rotate(const std::vector<double>& rotation) const;
// Data members
double x = 0.;
double y = 0.;
double z = 0.;
};
// Binary operators
inline Position operator+(Position a, Position b) { return a += b; }
inline Position operator+(Position a, double b) { return a += b; }
inline Position operator+(double a, Position b) { return b += a; }
inline Position operator-(Position a, Position b) { return a -= b; }
inline Position operator-(Position a, double b) { return a -= b; }
inline Position operator-(double a, Position b) { return b -= a; }
inline Position operator*(Position a, Position b) { return a *= b; }
inline Position operator*(Position a, double b) { return a *= b; }
inline Position operator*(double a, Position b) { return b *= a; }
inline Position operator/(Position a, Position b) { return a /= b; }
inline Position operator/(Position a, double b) { return a /= b; }
inline Position operator/(double a, Position b) { return b /= a; }
inline bool operator==(Position a, Position b)
{return a.x == b.x && a.y == b.y && a.z == b.z;}
inline bool operator!=(Position a, Position b)
{return a.x != b.x || a.y != b.y || a.z != b.z;}
std::ostream& operator<<(std::ostream& os, Position a);
//==============================================================================
//! Type representing a vector direction in Cartesian coordinates
//==============================================================================
using Direction = Position;
} // namespace openmc
#endif // OPENMC_POSITION_H

View file

@ -0,0 +1,22 @@
#ifndef OPENMC_PROGRESSBAR_H
#define OPENMC_PROGRESSBAR_H
#include <string>
class ProgressBar {
public:
// Constructor
ProgressBar();
void set_value(double val);
private:
std::string bar;
char bar_old[72] = "???% | |";
};
#endif // OPENMC_PROGRESSBAR_H

View file

@ -0,0 +1,97 @@
#ifndef OPENMC_RANDOM_LCG_H
#define OPENMC_RANDOM_LCG_H
#include <cstdint>
namespace openmc {
//==============================================================================
// Module constants.
//==============================================================================
extern "C" const int N_STREAMS;
extern "C" const int STREAM_TRACKING;
extern "C" const int STREAM_TALLIES;
extern "C" const int STREAM_SOURCE;
extern "C" const int STREAM_URR_PTABLE;
extern "C" const int STREAM_VOLUME;
extern "C" const int STREAM_PHOTON;
constexpr int64_t DEFAULT_SEED = 1;
//==============================================================================
//! Generate a pseudo-random number using a linear congruential generator.
//! @return A random number between 0 and 1
//==============================================================================
extern "C" double prn();
//==============================================================================
//! Generate a random number which is 'n' times ahead from the current seed.
//!
//! The result of this function will be the same as the result from calling
//! `prn()` 'n' times.
//! @param n The number of RNG seeds to skip ahead by
//! @return A random number between 0 and 1
//==============================================================================
extern "C" double future_prn(int64_t n);
//==============================================================================
//! Set the RNG seed to a unique value based on the ID of the particle.
//! @param id The particle ID
//==============================================================================
extern "C" void set_particle_seed(int64_t id);
//==============================================================================
//! Advance the random number seed 'n' times from the current seed.
//! @param n The number of RNG seeds to skip ahead by
//==============================================================================
extern "C" void advance_prn_seed(int64_t n);
//==============================================================================
//! Advance a random number seed 'n' times.
//!
//! This is usually used to skip a fixed number of random numbers (the stride)
//! so that a given particle always has the same starting seed regardless of
//! how many processors are used.
//! @param n The number of RNG seeds to skip ahead by
//! @param seed The starting to seed to advance from
//==============================================================================
uint64_t future_seed(uint64_t n, uint64_t seed);
//==============================================================================
//! Switch the RNG to a different stream of random numbers.
//!
//! If random numbers are needed in routines not used directly for tracking
//! (e.g. physics), this allows the numbers to be generated without affecting
//! reproducibility of the physics.
//! @param n The RNG stream to switch to. Use the constants such as
//! `STREAM_TRACKING` and `STREAM_TALLIES` for this argument.
//==============================================================================
extern "C" void prn_set_stream(int n);
//==============================================================================
// API FUNCTIONS
//==============================================================================
//==============================================================================
//! Get OpenMC's master seed.
//==============================================================================
extern "C" int64_t openmc_get_seed();
//==============================================================================
//! Set OpenMC's master seed.
//! @param new_seed The master seed. All other seeds will be derived from this
//! one.
//==============================================================================
extern "C" void openmc_set_seed(int64_t new_seed);
} // namespace openmc
#endif // OPENMC_RANDOM_LCG_H

51
include/openmc/reaction.h Normal file
View file

@ -0,0 +1,51 @@
//! \file reaction.h
//! Data for an incident neutron reaction
#ifndef OPENMC_REACTION_H
#define OPENMC_REACTION_H
#include <string>
#include <vector>
#include "hdf5.h"
#include "openmc/reaction_product.h"
namespace openmc {
//==============================================================================
//! Data for a single reaction including cross sections (possibly at multiple
//! temperatures) and reaction products (with secondary angle-energy
//! distributions)
//==============================================================================
class Reaction {
public:
//! Construct reaction from HDF5 data
//! \param[in] group HDF5 group containing reaction data
//! \param[in] temperatures Desired temperatures for cross sections
explicit Reaction(hid_t group, const std::vector<int>& temperatures);
//! Cross section at a single temperature
struct TemperatureXS {
int threshold;
std::vector<double> value;
};
int mt_; //!< ENDF MT value
double q_value_; //!< Reaction Q value in [eV]
bool scatter_in_cm_; //!< scattering system in center-of-mass?
bool redundant_; //!< redundant reaction?
std::vector<TemperatureXS> xs_; //!< Cross section at each temperature
std::vector<ReactionProduct> products_; //!< Reaction products
};
//==============================================================================
// Non-member functions
//==============================================================================
std::string reaction_name(int mt);
} // namespace openmc
#endif // OPENMC_REACTION_H

View file

@ -0,0 +1,57 @@
//! \file reaction_product.h
//! Data for a reaction product
#ifndef OPENMC_REACTION_PRODUCT_H
#define OPENMC_REACTION_PRODUCT_H
#include <memory> // for unique_ptr
#include <vector> // for vector
#include "hdf5.h"
#include "openmc/angle_energy.h"
#include "openmc/endf.h"
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
//! Data for a reaction product including its yield and angle-energy
//! distributions, each of which has a given probability of occurring for a
//! given incoming energy. In general, most products only have one angle-energy
//! distribution, but for some cases (e.g., (n,2n) in certain nuclides) multiple
//! distinct distributions exist.
//==============================================================================
class ReactionProduct {
public:
//! Emission mode for product
enum class EmissionMode {
prompt, // Prompt emission of secondary particle
delayed, // Yield represents total emission (prompt + delayed)
total // Delayed emission of secondary particle
};
using Secondary = std::unique_ptr<AngleEnergy>;
//! Construct reaction product from HDF5 data
//! \param[in] group HDF5 group containing data
explicit ReactionProduct(hid_t group);
//! Sample an outgoing angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const;
Particle::Type particle_; //!< Particle type
EmissionMode emission_mode_; //!< Emission mode
double decay_rate_; //!< Decay rate (for delayed neutron precursors) in [1/s]
std::unique_ptr<Function1D> yield_; //!< Yield as a function of energy
std::vector<Tabulated1D> applicability_; //!< Applicability of distribution
std::vector<Secondary> distribution_; //!< Secondary angle-energy distribution
};
} // namespace opemc
#endif // OPENMC_REACTION_PRODUCT_H

265
include/openmc/scattdata.h Normal file
View file

@ -0,0 +1,265 @@
//! \file scattdata.h
//! A collection of multi-group scattering data classes
#ifndef OPENMC_SCATTDATA_H
#define OPENMC_SCATTDATA_H
#include <vector>
#include "xtensor/xtensor.hpp"
#include "openmc/constants.h"
namespace openmc {
// forward declarations so we can name our friend functions
class ScattDataLegendre;
class ScattDataTabular;
//==============================================================================
// SCATTDATA contains all the data needed to describe the scattering energy and
// angular distribution data
//==============================================================================
class ScattData {
public:
virtual ~ScattData() = default;
protected:
//! \brief Initializes the attributes of the base class.
void
base_init(int order, const xt::xtensor<int, 1>& in_gmin,
const xt::xtensor<int, 1>& in_gmax, const double_2dvec& in_energy,
const double_2dvec& in_mult);
//! \brief Combines microscopic ScattDatas into a macroscopic one.
void
base_combine(size_t max_order, const std::vector<ScattData*>& those_scatts,
const std::vector<double>& scalars, xt::xtensor<int, 1>& in_gmin,
xt::xtensor<int, 1>& in_gmax, double_2dvec& sparse_mult,
double_3dvec& sparse_scatter);
public:
double_2dvec energy; // Normalized p0 matrix for sampling Eout
double_2dvec mult; // nu-scatter multiplication (nu-scatt/scatt)
double_3dvec dist; // Angular distribution
xt::xtensor<double, 1> gmin; // minimum outgoing group
xt::xtensor<double, 1> gmax; // maximum outgoing group
xt::xtensor<double, 1> scattxs; // Isotropic Sigma_{s,g_{in}}
//! \brief Calculates the value of normalized f(mu).
//!
//! The value of f(mu) is normalized as in the integral of f(mu)dmu across
//! [-1,1] is 1.
//!
//! @param gin Incoming energy group of interest.
//! @param gout Outgoing energy group of interest.
//! @param mu Cosine of the change-in-angle of interest.
//! @return The value of f(mu).
virtual double
calc_f(int gin, int gout, double mu) = 0;
//! \brief Samples the outgoing energy and angle from the ScattData info.
//!
//! @param gin Incoming energy group.
//! @param gout Sampled outgoing energy group.
//! @param mu Sampled cosine of the change-in-angle.
//! @param wgt Weight of the particle to be adjusted.
virtual void
sample(int gin, int& gout, double& mu, double& wgt) = 0;
//! \brief Initializes the ScattData object from a given scatter and
//! multiplicity matrix.
//!
//! @param in_gmin List of minimum outgoing groups for every incoming group
//! @param in_gmax List of maximum outgoing groups for every incoming group
//! @param in_mult Input sparse multiplicity matrix
//! @param coeffs Input sparse scattering matrix
virtual void
init(const xt::xtensor<int, 1>& in_gmin, const xt::xtensor<int, 1>& in_gmax,
const double_2dvec& in_mult, const double_3dvec& coeffs) = 0;
//! \brief Combines the microscopic data.
//!
//! @param those_scatts Microscopic objects to combine.
//! @param scalars Scalars to multiply the microscopic data by.
virtual void
combine(const std::vector<ScattData*>& those_scatts,
const std::vector<double>& scalars) = 0;
//! \brief Getter for the dimensionality of the scattering order.
//!
//! If Legendre this is the "n" in "Pn"; for Tabular, this is the number
//! of points, and for Histogram this is the number of bins.
//!
//! @return The order.
virtual size_t
get_order() = 0;
//! \brief Builds a dense scattering matrix from the constituent parts
//!
//! @param max_order If Legendre this is the maximum value of "n" in "Pn"
//! requested; ignored otherwise.
//! @return The dense scattering matrix.
virtual xt::xtensor<double, 3>
get_matrix(size_t max_order) = 0;
//! \brief Samples the outgoing energy from the ScattData info.
//!
//! @param gin Incoming energy group.
//! @param gout Sampled outgoing energy group.
//! @param i_gout Sampled outgoing energy group index.
void
sample_energy(int gin, int& gout, int& i_gout);
//! \brief Provides a cross section value given certain parameters
//!
//! @param xstype Type of cross section requested, according to the
//! enumerated constants.
//! @param gin Incoming energy group.
//! @param gout Outgoing energy group; use nullptr if irrelevant, or if a
//! sum is requested.
//! @param mu Cosine of the change-in-angle, for scattering quantities;
//! use nullptr if irrelevant.
//! @return Requested cross section value.
double
get_xs(int xstype, int gin, const int* gout, const double* mu);
};
//==============================================================================
// ScattDataLegendre represents the angular distributions as Legendre kernels
//==============================================================================
class ScattDataLegendre: public ScattData {
protected:
// Maximal value for rejection sampling from a rectangle
double_2dvec max_val;
// Friend convert_legendre_to_tabular so it has access to protected
// parameters
friend void
convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab);
public:
void
init(const xt::xtensor<int, 1>& in_gmin, const xt::xtensor<int, 1>& in_gmax,
const double_2dvec& in_mult, const double_3dvec& coeffs);
void
combine(const std::vector<ScattData*>& those_scatts,
const std::vector<double>& scalars);
//! \brief Find the maximal value of the angular distribution to use as a
// bounding box with rejection sampling.
void
update_max_val();
double
calc_f(int gin, int gout, double mu);
void
sample(int gin, int& gout, double& mu, double& wgt);
size_t
get_order() {return dist[0][0].size() - 1;};
xt::xtensor<double, 3>
get_matrix(size_t max_order);
};
//==============================================================================
// ScattDataHistogram represents the angular distributions as a histogram, as it
// would be if it came from a "mu" tally in OpenMC
//==============================================================================
class ScattDataHistogram: public ScattData {
protected:
xt::xtensor<double, 1> mu; // Angle distribution mu bin boundaries
double dmu; // Quick storage of the mu spacing
double_3dvec fmu; // The angular distribution histogram
public:
void
init(const xt::xtensor<int, 1>& in_gmin, const xt::xtensor<int, 1>& in_gmax,
const double_2dvec& in_mult, const double_3dvec& coeffs);
void
combine(const std::vector<ScattData*>& those_scatts,
const std::vector<double>& scalars);
double
calc_f(int gin, int gout, double mu);
void
sample(int gin, int& gout, double& mu, double& wgt);
size_t
get_order() {return dist[0][0].size();};
xt::xtensor<double, 3>
get_matrix(size_t max_order);
};
//==============================================================================
// ScattDataTabular represents the angular distributions as a table of mu and
// f(mu)
//==============================================================================
class ScattDataTabular: public ScattData {
protected:
xt::xtensor<double, 1> mu; // Angle distribution mu grid points
double dmu; // Quick storage of the mu spacing
double_3dvec fmu; // The angular distribution function
// Friend convert_legendre_to_tabular so it has access to protected
// parameters
friend void
convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab);
public:
void
init(const xt::xtensor<int, 1>& in_gmin, const xt::xtensor<int, 1>& in_gmax,
const double_2dvec& in_mult, const double_3dvec& coeffs);
void
combine(const std::vector<ScattData*>& those_scatts,
const std::vector<double>& scalars);
double
calc_f(int gin, int gout, double mu);
void
sample(int gin, int& gout, double& mu, double& wgt);
size_t
get_order() {return dist[0][0].size();};
xt::xtensor<double, 3>
get_matrix(size_t max_order);
};
//==============================================================================
// Function to convert Legendre functions to tabular
//==============================================================================
//! \brief Converts a ScattDatalegendre to a ScattDataHistogram
//!
//! @param leg The initial ScattDataLegendre object.
//! @param leg The resultant ScattDataTabular object.
//! @param n_mu The number of mu points to use when building the
//! ScattDataTabular object.
void
convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab,
int n_mu);
} // namespace openmc
#endif // OPENMC_SCATTDATA_H

32
include/openmc/search.h Normal file
View file

@ -0,0 +1,32 @@
//! \file search.h
//! Search algorithms
#ifndef OPENMC_SEARCH_H
#define OPENMC_SEARCH_H
#include <algorithm> // for lower_bound, upper_bound
namespace openmc {
//! Perform binary search
template<class It, class T>
typename std::iterator_traits<It>::difference_type
lower_bound_index(It first, It last, const T& value)
{
if (*first == value) return 0;
It index = std::lower_bound(first, last, value) - 1;
return (index == last) ? -1 : index - first;
}
template<class It, class T>
typename std::iterator_traits<It>::difference_type
upper_bound_index(It first, It last, const T& value)
{
It index = std::upper_bound(first, last, value) - 1;
return (index == last) ? -1 : index - first;
}
} // namespace openmc
#endif // OPENMC_SEARCH_H

View file

@ -0,0 +1,61 @@
//! \file secondary_correlated.h
//! Correlated angle-energy distribution
#ifndef OPENMC_SECONDARY_CORRELATED_H
#define OPENMC_SECONDARY_CORRELATED_H
#include <vector>
#include "hdf5.h"
#include "xtensor/xtensor.hpp"
#include "openmc/angle_energy.h"
#include "openmc/endf.h"
#include "openmc/distribution.h"
namespace openmc {
//==============================================================================
//! Correlated angle-energy distribution corresponding to ACE law 61 and ENDF
//! File 6, LAW=1, LANG!=2.
//==============================================================================
class CorrelatedAngleEnergy : public AngleEnergy {
public:
//! Outgoing energy/angle at a single incoming energy
struct CorrTable {
int n_discrete; //!< Number of discrete lines
Interpolation interpolation; //!< Interpolation law
xt::xtensor<double, 1> e_out; //!< Outgoing energies [eV]
xt::xtensor<double, 1> p; //!< Probability density
xt::xtensor<double, 1> c; //!< Cumulative distribution
std::vector<UPtrDist> angle; //!< Angle distribution
};
explicit CorrelatedAngleEnergy(hid_t group);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
// energy property
std::vector<double>& energy() { return energy_; }
const std::vector<double>& energy() const { return energy_; }
// distribution property
std::vector<CorrTable>& distribution() { return distribution_; }
const std::vector<CorrTable>& distribution() const { return distribution_; }
private:
int n_region_; //!< Number of interpolation regions
std::vector<int> breakpoints_; //!< Breakpoints between regions
std::vector<Interpolation> interpolation_; //!< Interpolation laws
std::vector<double> energy_; //!< Energies [eV] at which distributions
//!< are tabulated
std::vector<CorrTable> distribution_; //!< Distribution at each energy
};
} // namespace openmc
#endif // OPENMC_SECONDARY_CORRELATED_H

View file

@ -0,0 +1,55 @@
//! \file secondary_kalbach.h
//! Kalbach-Mann angle-energy distribution
#ifndef OPENMC_SECONDARY_KALBACH_H
#define OPENMC_SECONDARY_KALBACH_H
#include <vector>
#include "hdf5.h"
#include "xtensor/xtensor.hpp"
#include "openmc/angle_energy.h"
#include "openmc/constants.h"
#include "openmc/endf.h"
namespace openmc {
//==============================================================================
//! Correlated angle-energy distribution with the angular distribution
//! represented using Kalbach-Mann systematics. This corresponds to ACE law 44
//! and ENDF File 6, LAW=1, LANG=2.
//==============================================================================
class KalbachMann : public AngleEnergy {
public:
explicit KalbachMann(hid_t group);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
//! Outgoing energy/angle at a single incoming energy
struct KMTable {
int n_discrete; //!< Number of discrete lines
Interpolation interpolation; //!< Interpolation law
xt::xtensor<double, 1> e_out; //!< Outgoing energies [eV]
xt::xtensor<double, 1> p; //!< Probability density
xt::xtensor<double, 1> c; //!< Cumulative distribution
xt::xtensor<double, 1> r; //!< Pre-compound fraction
xt::xtensor<double, 1> a; //!< Parameterized function
};
int n_region_; //!< Number of interpolation regions
std::vector<int> breakpoints_; //!< Breakpoints between regions
std::vector<Interpolation> interpolation_; //!< Interpolation laws
std::vector<double> energy_; //!< Energies [eV] at which distributions
//!< are tabulated
std::vector<KMTable> distribution_; //!< Distribution at each energy
};
} // namespace openmc
#endif // OPENMC_SECONDARY_KALBACH_H

View file

@ -0,0 +1,37 @@
//! \file secondary_nbody.h
//! N-body phase space distribution
#ifndef OPENMC_SECONDARY_NBODY_H
#define OPENMC_SECONDARY_NBODY_H
#include "hdf5.h"
#include "openmc/angle_energy.h"
namespace openmc {
//==============================================================================
//! Angle-energy distribution for particles emitted from neutron and
//! charged-particle reactions. This corresponds to ACE law 66 and ENDF File 6,
//! LAW=6.
//==============================================================================
class NBodyPhaseSpace : public AngleEnergy {
public:
explicit NBodyPhaseSpace(hid_t group);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
int n_bodies_; //!< Number of particles distributed
double mass_ratio_; //!< Total mass of particles [neutron mass]
double A_; //!< Atomic weight ratio
double Q_; //!< Reaction Q-value [eV]
};
} // namespace openmc
#endif // OPENMC_SECONDARY_NBODY_H

View file

@ -0,0 +1,139 @@
//! \file secondary_thermal.h
//! Angle-energy distributions for thermal scattering
#ifndef OPENMC_SECONDARY_THERMAL_H
#define OPENMC_SECONDARY_THERMAL_H
#include "openmc/angle_energy.h"
#include "openmc/endf.h"
#include "openmc/secondary_correlated.h"
#include <hdf5.h>
#include "xtensor/xtensor.hpp"
#include <vector>
namespace openmc {
//==============================================================================
//! Coherent elastic scattering angle-energy distribution
//==============================================================================
class CoherentElasticAE : public AngleEnergy {
public:
//! Construct from a coherent elastic scattering cross section
//
//! \param[in] xs Coherent elastic scattering cross section
explicit CoherentElasticAE(const CoherentElasticXS& xs);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
const CoherentElasticXS& xs_; //!< Coherent elastic scattering cross section
};
//==============================================================================
//! Incoherent elastic scattering angle-energy distribution
//==============================================================================
class IncoherentElasticAE : public AngleEnergy {
public:
//! Construct from HDF5 file
//
//! \param[in] group HDF5 group
explicit IncoherentElasticAE(hid_t group);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
double debye_waller_;
};
//==============================================================================
//! Incoherent elastic scattering angle-energy distribution (discrete)
//==============================================================================
class IncoherentElasticAEDiscrete : public AngleEnergy {
public:
//! Construct from HDF5 file
//
//! \param[in] group HDF5 group
//! \param[in] energy Energies at which cosines are tabulated
explicit IncoherentElasticAEDiscrete(hid_t group, const std::vector<double>& energy);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
const std::vector<double>& energy_; //!< Energies at which cosines are tabulated
xt::xtensor<double, 2> mu_out_; //!< Cosines for each incident energy
};
//==============================================================================
//! Incoherent inelastic scattering angle-energy distribution (discrete)
//==============================================================================
class IncoherentInelasticAEDiscrete : public AngleEnergy {
public:
//! Construct from HDF5 file
//
//! \param[in] group HDF5 group
//! \param[in] energy Incident energies at which distributions are tabulated
explicit IncoherentInelasticAEDiscrete(hid_t group, const std::vector<double>& energy);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
const std::vector<double>& energy_; //!< Incident energies
xt::xtensor<double, 2> energy_out_; //!< Outgoing energies for each incident energy
xt::xtensor<double, 3> mu_out_; //!< Outgoing cosines for each incident/outgoing energy
bool skewed_; //!< Whether outgoing energy distribution is skewed
};
//==============================================================================
//! Incoherent inelastic scattering angle-energy distribution
//==============================================================================
class IncoherentInelasticAE : public AngleEnergy {
public:
//! Construct from HDF5 file
//
//! \param[in] group HDF5 group
explicit IncoherentInelasticAE(hid_t group);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
private:
//! Secondary energy/angle distribution
struct DistEnergySab {
std::size_t n_e_out; //!< Number of outgoing energies
xt::xtensor<double, 1> e_out; //!< Outgoing energies
xt::xtensor<double, 1> e_out_pdf; //!< Probability density function
xt::xtensor<double, 1> e_out_cdf; //!< Cumulative distribution function
xt::xtensor<double, 2> mu; //!< Equiprobable angles at each outgoing energy
};
std::vector<double> energy_; //!< Incident energies
std::vector<DistEnergySab> distribution_; //!< Secondary angle-energy at
//!< each incident energy
};
} // namespace openmc
#endif // OPENMC_SECONDARY_THERMAL_H

View file

@ -0,0 +1,45 @@
//! \file secondary_uncorrelated.h
//! Uncorrelated angle-energy distribution
#ifndef OPENMC_SECONDARY_UNCORRELATED_H
#define OPENMC_SECONDARY_UNCORRELATED_H
#include <memory>
#include <vector>
#include "hdf5.h"
#include "openmc/angle_energy.h"
#include "openmc/distribution_angle.h"
#include "openmc/distribution_energy.h"
namespace openmc {
//==============================================================================
//! Uncorrelated angle-energy distribution. This corresponds to when an energy
//! distribution is given in ENDF File 5/6 and an angular distribution is given
//! in ENDF File 4.
//==============================================================================
class UncorrelatedAngleEnergy : public AngleEnergy {
public:
explicit UncorrelatedAngleEnergy(hid_t group);
//! Sample distribution for an angle and energy
//! \param[in] E_in Incoming energy in [eV]
//! \param[out] E_out Outgoing energy in [eV]
//! \param[out] mu Outgoing cosine with respect to current direction
void sample(double E_in, double& E_out, double& mu) const override;
// Accessors
AngleDistribution& angle() { return angle_; }
bool& fission() { return fission_; }
private:
AngleDistribution angle_; //!< Angle distribution
std::unique_ptr<EnergyDistribution> energy_; //!< Energy distribution
bool fission_ {false}; //!< Whether distribution is use for fission
};
} // namespace openmc
#endif // OPENMC_SECONDARY_UNCORRELATED_H

107
include/openmc/settings.h Normal file
View file

@ -0,0 +1,107 @@
#ifndef OPENMC_SETTINGS_H
#define OPENMC_SETTINGS_H
//! \file settings.h
//! \brief Settings for OpenMC
#include <array>
#include <cstdint>
#include <string>
#include <unordered_set>
#include <vector>
#include "pugixml.hpp"
#include "openmc/constants.h"
namespace openmc {
//==============================================================================
// Global variable declarations
//==============================================================================
namespace settings {
// Boolean flags
extern bool assume_separate; //!< assume tallies are spatially separate?
extern bool check_overlaps; //!< check overlaps in geometry?
extern bool confidence_intervals; //!< use confidence intervals for results?
extern bool create_fission_neutrons; //!< create fission neutrons (fixed source)?
extern "C" bool cmfd_run; //!< is a CMFD run?
extern "C" bool dagmc; //!< indicator of DAGMC geometry
extern "C" bool entropy_on; //!< calculate Shannon entropy?
extern bool legendre_to_tabular; //!< convert Legendre distributions to tabular?
extern bool output_summary; //!< write summary.h5?
extern bool output_tallies; //!< write tallies.out?
extern bool particle_restart_run; //!< particle restart run?
extern "C" bool photon_transport; //!< photon transport turned on?
extern "C" bool reduce_tallies; //!< reduce tallies at end of batch?
extern bool res_scat_on; //!< use resonance upscattering method?
extern "C" bool restart_run; //!< restart run?
extern "C" bool run_CE; //!< run with continuous-energy data?
extern bool source_latest; //!< write latest source at each batch?
extern bool source_separate; //!< write source to separate file?
extern bool source_write; //!< write source in HDF5 files?
extern bool survival_biasing; //!< use survival biasing?
extern bool temperature_multipole; //!< use multipole data?
extern "C" bool trigger_on; //!< tally triggers enabled?
extern bool trigger_predict; //!< predict batches for triggers?
extern bool ufs_on; //!< uniform fission site method on?
extern bool urr_ptables_on; //!< use unresolved resonance prob. tables?
extern bool write_all_tracks; //!< write track files for every particle?
extern bool write_initial_source; //!< write out initial source file?
// Paths to various files
extern std::string path_cross_sections; //!< path to cross_sections.xml
extern std::string path_input; //!< directory where main .xml files resides
extern std::string path_output; //!< directory where output files are written
extern std::string path_particle_restart; //!< path to a particle restart file
extern std::string path_source;
extern std::string path_sourcepoint; //!< path to a source file
extern "C" std::string path_statepoint; //!< path to a statepoint file
extern "C" int32_t n_batches; //!< number of (inactive+active) batches
extern "C" int32_t n_inactive; //!< number of inactive batches
extern "C" int32_t gen_per_batch; //!< number of generations per batch
extern "C" int64_t n_particles; //!< number of particles per generation
extern int electron_treatment; //!< how to treat secondary electrons
extern std::array<double, 4> energy_cutoff; //!< Energy cutoff in [eV] for each particle type
extern int legendre_to_tabular_points; //!< number of points to convert Legendres
extern int max_order; //!< Maximum Legendre order for multigroup data
extern int n_log_bins; //!< number of bins for logarithmic energy grid
extern int n_max_batches; //!< Maximum number of batches
extern ResScatMethod res_scat_method; //!< resonance upscattering method
extern double res_scat_energy_min; //!< Min energy in [eV] for res. upscattering
extern double res_scat_energy_max; //!< Max energy in [eV] for res. upscattering
extern std::vector<std::string> res_scat_nuclides; //!< Nuclides using res. upscattering treatment
extern "C" int run_mode; //!< Run mode (eigenvalue, fixed src, etc.)
extern std::unordered_set<int> sourcepoint_batch; //!< Batches when source should be written
extern std::unordered_set<int> statepoint_batch; //!< Batches when state should be written
extern int temperature_method; //!< method for choosing temperatures
extern double temperature_tolerance; //!< Tolerance in [K] on choosing temperatures
extern double temperature_default; //!< Default T in [K]
extern std::array<double, 2> temperature_range; //!< Min/max T in [K] over which to load xs
extern int trace_batch; //!< Batch to trace particle on
extern int trace_gen; //!< Generation to trace particle on
extern int64_t trace_particle; //!< Particle ID to enable trace on
extern std::vector<std::array<int, 3>> track_identifiers; //!< Particle numbers for writing tracks
extern int trigger_batch_interval; //!< Batch interval for triggers
extern "C" int verbosity; //!< How verbose to make output
extern double weight_cutoff; //!< Weight cutoff for Russian roulette
extern double weight_survive; //!< Survival weight after Russian roulette
} // namespace settings
//==============================================================================
// Functions
//==============================================================================
//! Read settings from XML file
//! \param[in] root XML node for <settings>
void read_settings_xml();
void free_memory_settings();
} // namespace openmc
#endif // OPENMC_SETTINGS_H

View file

@ -0,0 +1,95 @@
//! \file simulation.h
//! \brief Variables/functions related to a running simulation
#ifndef OPENMC_SIMULATION_H
#define OPENMC_SIMULATION_H
#include "openmc/mesh.h"
#include "openmc/particle.h"
#include <cstdint>
#include <vector>
namespace openmc {
constexpr int STATUS_EXIT_NORMAL {0};
constexpr int STATUS_EXIT_MAX_BATCH {1};
constexpr int STATUS_EXIT_ON_TRIGGER {2};
//==============================================================================
// Global variable declarations
//==============================================================================
namespace simulation {
extern "C" int current_batch; //!< current batch
extern "C" int current_gen; //!< current fission generation
extern "C" int64_t current_work; //!< index in source back of current particle
extern "C" bool initialized; //!< has simulation been initialized?
extern "C" double keff; //!< average k over batches
extern "C" double keff_std; //!< standard deviation of average k
extern "C" double k_col_abs; //!< sum over batches of k_collision * k_absorption
extern "C" double k_col_tra; //!< sum over batches of k_collision * k_tracklength
extern "C" double k_abs_tra; //!< sum over batches of k_absorption * k_tracklength
extern double log_spacing; //!< lethargy spacing for energy grid searches
extern "C" int n_lost_particles; //!< cumulative number of lost particles
extern "C" bool need_depletion_rx; //!< need to calculate depletion rx?
extern "C" int restart_batch; //!< batch at which a restart job resumed
extern "C" bool satisfy_triggers; //!< have tally triggers been satisfied?
extern "C" int total_gen; //!< total number of generations simulated
extern double total_weight; //!< Total source weight in a batch
extern int64_t work_per_rank; //!< number of particles per MPI rank
extern const RegularMesh* entropy_mesh;
extern const RegularMesh* ufs_mesh;
extern std::vector<double> k_generation;
extern std::vector<int64_t> work_index;
// Threadprivate variables
extern "C" bool trace; //!< flag to show debug information
#pragma omp threadprivate(current_work, trace)
} // namespace simulation
//==============================================================================
// Functions
//==============================================================================
//! Allocate space for source and fission banks
void allocate_banks();
//! Determine number of particles to transport per process
void calculate_work();
//! Initialize a batch
void initialize_batch();
//! Initialize a fission generation
void initialize_generation();
void initialize_history(Particle* p, int64_t index_source);
//! Finalize a batch
//!
//! Handles synchronization and accumulation of tallies, calculation of Shannon
//! entropy, getting single-batch estimate of keff, and turning on tallies when
//! appropriate
void finalize_batch();
//! Finalize a fission generation
void finalize_generation();
//! Determine overall generation number
extern "C" int overall_generation();
#ifdef OPENMC_MPI
void broadcast_results();
#endif
void free_memory_simulation();
} // namespace openmc
#endif // OPENMC_SIMULATION_H

73
include/openmc/source.h Normal file
View file

@ -0,0 +1,73 @@
//! \file source.h
//! \brief External source distributions
#ifndef OPENMC_SOURCE_H
#define OPENMC_SOURCE_H
#include <memory>
#include <vector>
#include "pugixml.hpp"
#include "openmc/distribution_multi.h"
#include "openmc/distribution_spatial.h"
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
class SourceDistribution;
namespace model {
extern std::vector<SourceDistribution> external_sources;
} // namespace model
//==============================================================================
//! External source distribution
//==============================================================================
class SourceDistribution {
public:
// Constructors
SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy);
explicit SourceDistribution(pugi::xml_node node);
//! Sample from the external source distribution
//! \return Sampled site
Particle::Bank sample() const;
// Properties
double strength() const { return strength_; }
private:
Particle::Type particle_ {Particle::Type::neutron}; //!< Type of particle emitted
double strength_ {1.0}; //!< Source strength
UPtrSpace space_; //!< Spatial distribution
UPtrAngle angle_; //!< Angular distribution
UPtrDist energy_; //!< Energy distribution
};
//==============================================================================
// Functions
//==============================================================================
//! Initialize source bank from file/distribution
extern "C" void initialize_source();
//! Sample a site from all external source distributions in proportion to their
//! source strength
//! \return Sampled source site
Particle::Bank sample_external_source();
//! Fill source bank at end of generation for fixed source simulations
void fill_source_bank_fixedsource();
void free_memory_source();
} // namespace openmc
#endif // OPENMC_SOURCE_H

View file

@ -0,0 +1,20 @@
#ifndef OPENMC_STATE_POINT_H
#define OPENMC_STATE_POINT_H
#include <cstdint>
#include "hdf5.h"
#include "openmc/capi.h"
namespace openmc {
void load_state_point();
void write_source_point(const char* filename);
void write_source_bank(hid_t group_id);
void read_source_bank(hid_t group_id);
void write_tally_results_nr(hid_t file_id);
void restart_set_keff();
} // namespace openmc
#endif // OPENMC_STATE_POINT_H

View file

@ -0,0 +1,26 @@
#ifndef OPENMC_STRING_UTILS_H
#define OPENMC_STRING_UTILS_H
#include <string>
#include <vector>
namespace openmc {
std::string& strtrim(std::string& s);
char* strtrim(char* c_str);
std::string to_element(const std::string& name);
void to_lower(std::string& str);
int word_count(std::string const& str);
std::vector<std::string> split(const std::string& in);
bool ends_with(const std::string& value, const std::string& ending);
bool starts_with(const std::string& value, const std::string& beginning);
} // namespace openmc
#endif // OPENMC_STRING_UTILS_H

16
include/openmc/summary.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef OPENMC_SUMMARY_H
#define OPENMC_SUMMARY_H
#include <hdf5.h>
namespace openmc {
void write_summary();
void write_header(hid_t file);
void write_nuclides(hid_t file);
void write_geometry(hid_t file);
void write_materials(hid_t file);
}
#endif // OPENMC_SUMMARY_H

457
include/openmc/surface.h Normal file
View file

@ -0,0 +1,457 @@
#ifndef OPENMC_SURFACE_H
#define OPENMC_SURFACE_H
#include <memory> // for unique_ptr
#include <limits> // For numeric_limits
#include <string>
#include <unordered_map>
#include <vector>
#include "hdf5.h"
#include "pugixml.hpp"
#include "openmc/constants.h"
#include "openmc/position.h"
#include "dagmc.h"
namespace openmc {
//==============================================================================
// Module constant declarations (defined in .cpp)
//==============================================================================
// TODO: Convert to enum
extern "C" const int BC_TRANSMIT;
extern "C" const int BC_VACUUM;
extern "C" const int BC_REFLECT;
extern "C" const int BC_PERIODIC;
extern "C" const int BC_WHITE;
//==============================================================================
// Global variables
//==============================================================================
class Surface;
namespace model {
extern std::vector<std::unique_ptr<Surface>> surfaces;
extern std::unordered_map<int, int> surface_map;
} // namespace model
//==============================================================================
//! Coordinates for an axis-aligned cube that bounds a geometric object.
//==============================================================================
struct BoundingBox
{
double xmin = -INFTY;
double xmax = INFTY;
double ymin = -INFTY;
double ymax = INFTY;
double zmin = -INFTY;
double zmax = INFTY;
inline BoundingBox operator &(const BoundingBox& other) {
BoundingBox result = *this;
return result &= other;
}
inline BoundingBox operator |(const BoundingBox& other) {
BoundingBox result = *this;
return result |= other;
}
// intersect operator
inline BoundingBox& operator &=(const BoundingBox& other) {
xmin = std::max(xmin, other.xmin);
xmax = std::min(xmax, other.xmax);
ymin = std::max(ymin, other.ymin);
ymax = std::min(ymax, other.ymax);
zmin = std::max(zmin, other.zmin);
zmax = std::min(zmax, other.zmax);
return *this;
}
// union operator
inline BoundingBox& operator |=(const BoundingBox& other) {
xmin = std::min(xmin, other.xmin);
xmax = std::max(xmax, other.xmax);
ymin = std::min(ymin, other.ymin);
ymax = std::max(ymax, other.ymax);
zmin = std::min(zmin, other.zmin);
zmax = std::max(zmax, other.zmax);
return *this;
}
};
//==============================================================================
//! A geometry primitive used to define regions of 3D space.
//==============================================================================
class Surface
{
public:
int id_; //!< Unique ID
int bc_; //!< Boundary condition
std::string name_; //!< User-defined name
explicit Surface(pugi::xml_node surf_node);
Surface();
virtual ~Surface() {}
//! Determine which side of a surface a point lies on.
//! \param r The 3D Cartesian coordinate of a point.
//! \param u A direction used to "break ties" and pick a sense when the
//! point is very close to the surface.
//! \return true if the point is on the "positive" side of the surface and
//! false otherwise.
bool sense(Position r, Direction u) const;
//! Determine the direction of a ray reflected from the surface.
//! \param[in] r The point at which the ray is incident.
//! \param[in] u Incident direction of the ray
//! \return Outgoing direction of the ray
virtual Direction reflect(Position r, Direction u) const;
virtual Direction diffuse_reflect(Position r, Direction u) const;
//! Evaluate the equation describing the surface.
//!
//! Surfaces can be described by some function f(x, y, z) = 0. This member
//! function evaluates that mathematical function.
//! \param r A 3D Cartesian coordinate.
virtual double evaluate(Position r) const = 0;
//! Compute the distance between a point and the surface along a ray.
//! \param r A 3D Cartesian coordinate.
//! \param u The direction of the ray.
//! \param coincident A hint to the code that the given point should lie
//! exactly on the surface.
virtual double distance(Position r, Direction u, bool coincident) const = 0;
//! Compute the local outward normal direction of the surface.
//! \param r A 3D Cartesian coordinate.
//! \return Normal direction
virtual Direction normal(Position r) const = 0;
//! Write all information needed to reconstruct the surface to an HDF5 group.
//! \param group_id An HDF5 group id.
//TODO: this probably needs to include i_periodic for PeriodicSurface
virtual void to_hdf5(hid_t group_id) const = 0;
//! Get the BoundingBox for this surface.
virtual BoundingBox bounding_box(bool pos_side) const { return {}; }
};
class CSGSurface : public Surface
{
public:
explicit CSGSurface(pugi::xml_node surf_node);
CSGSurface();
void to_hdf5(hid_t group_id) const;
protected:
virtual void to_hdf5_inner(hid_t group_id) const = 0;
};
//==============================================================================
//! A `Surface` representing a DAGMC-based surface in DAGMC.
//==============================================================================
#ifdef DAGMC
class DAGSurface : public Surface
{
public:
DAGSurface();
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
Direction reflect(Position r, Direction u) const;
void to_hdf5(hid_t group_id) const;
moab::DagMC* dagmc_ptr_; //!< Pointer to DagMC instance
int32_t dag_index_; //!< DagMC index of surface
};
#endif
//==============================================================================
//! A `Surface` that supports periodic boundary conditions.
//!
//! Translational periodicity is supported for the `XPlane`, `YPlane`, `ZPlane`,
//! and `Plane` types. Rotational periodicity is supported for
//! `XPlane`-`YPlane` pairs.
//==============================================================================
class PeriodicSurface : public CSGSurface
{
public:
int i_periodic_{C_NONE}; //!< Index of corresponding periodic surface
explicit PeriodicSurface(pugi::xml_node surf_node);
//! Translate a particle onto this surface from a periodic partner surface.
//! \param other A pointer to the partner surface in this periodic BC.
//! \param r A point on the partner surface that will be translated onto
//! this surface.
//! \param u A direction that will be rotated for systems with rotational
//! periodicity.
//! \return true if this surface and its partner make a rotationally-periodic
//! boundary condition.
virtual bool periodic_translate(const PeriodicSurface* other, Position& r,
Direction& u) const = 0;
};
//==============================================================================
//! A plane perpendicular to the x-axis.
//
//! The plane is described by the equation \f$x - x_0 = 0\f$
//==============================================================================
class SurfaceXPlane : public PeriodicSurface
{
public:
explicit SurfaceXPlane(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
bool periodic_translate(const PeriodicSurface* other, Position& r,
Direction& u) const;
BoundingBox bounding_box(bool pos_side) const;
double x0_;
};
//==============================================================================
//! A plane perpendicular to the y-axis.
//
//! The plane is described by the equation \f$y - y_0 = 0\f$
//==============================================================================
class SurfaceYPlane : public PeriodicSurface
{
public:
explicit SurfaceYPlane(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
bool periodic_translate(const PeriodicSurface* other, Position& r,
Direction& u) const;
BoundingBox bounding_box(bool pos_side) const;
double y0_;
};
//==============================================================================
//! A plane perpendicular to the z-axis.
//
//! The plane is described by the equation \f$z - z_0 = 0\f$
//==============================================================================
class SurfaceZPlane : public PeriodicSurface
{
public:
explicit SurfaceZPlane(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
bool periodic_translate(const PeriodicSurface* other, Position& r,
Direction& u) const;
BoundingBox bounding_box(bool pos_side) const;
double z0_;
};
//==============================================================================
//! A general plane.
//
//! The plane is described by the equation \f$A x + B y + C z - D = 0\f$
//==============================================================================
class SurfacePlane : public PeriodicSurface
{
public:
explicit SurfacePlane(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
bool periodic_translate(const PeriodicSurface* other, Position& r,
Direction& u) const;
double A_, B_, C_, D_;
};
//==============================================================================
//! A cylinder aligned along the x-axis.
//
//! The cylinder is described by the equation
//! \f$(y - y_0)^2 + (z - z_0)^2 - R^2 = 0\f$
//==============================================================================
class SurfaceXCylinder : public CSGSurface
{
public:
explicit SurfaceXCylinder(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
BoundingBox bounding_box(bool pos_side) const;
double y0_, z0_, radius_;
};
//==============================================================================
//! A cylinder aligned along the y-axis.
//
//! The cylinder is described by the equation
//! \f$(x - x_0)^2 + (z - z_0)^2 - R^2 = 0\f$
//==============================================================================
class SurfaceYCylinder : public CSGSurface
{
public:
explicit SurfaceYCylinder(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
BoundingBox bounding_box(bool pos_side) const;
double x0_, z0_, radius_;
};
//==============================================================================
//! A cylinder aligned along the z-axis.
//
//! The cylinder is described by the equation
//! \f$(x - x_0)^2 + (y - y_0)^2 - R^2 = 0\f$
//==============================================================================
class SurfaceZCylinder : public CSGSurface
{
public:
explicit SurfaceZCylinder(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
BoundingBox bounding_box(bool pos_side) const;
double x0_, y0_, radius_;
};
//==============================================================================
//! A sphere.
//
//! The cylinder is described by the equation
//! \f$(x - x_0)^2 + (y - y_0)^2 + (z - z_0)^2 - R^2 = 0\f$
//==============================================================================
class SurfaceSphere : public CSGSurface
{
public:
explicit SurfaceSphere(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
BoundingBox bounding_box(bool pos_side) const;
double x0_, y0_, z0_, radius_;
};
//==============================================================================
//! A cone aligned along the x-axis.
//
//! The cylinder is described by the equation
//! \f$(y - y_0)^2 + (z - z_0)^2 - R^2 (x - x_0)^2 = 0\f$
//==============================================================================
class SurfaceXCone : public CSGSurface
{
public:
explicit SurfaceXCone(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
double x0_, y0_, z0_, radius_sq_;
};
//==============================================================================
//! A cone aligned along the y-axis.
//
//! The cylinder is described by the equation
//! \f$(x - x_0)^2 + (z - z_0)^2 - R^2 (y - y_0)^2 = 0\f$
//==============================================================================
class SurfaceYCone : public CSGSurface
{
public:
explicit SurfaceYCone(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
double x0_, y0_, z0_, radius_sq_;
};
//==============================================================================
//! A cone aligned along the z-axis.
//
//! The cylinder is described by the equation
//! \f$(x - x_0)^2 + (y - y_0)^2 - R^2 (z - z_0)^2 = 0\f$
//==============================================================================
class SurfaceZCone : public CSGSurface
{
public:
explicit SurfaceZCone(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
double x0_, y0_, z0_, radius_sq_;
};
//==============================================================================
//! A general surface described by a quadratic equation.
//
//! \f$A x^2 + B y^2 + C z^2 + D x y + E y z + F x z + G x + H y + J z + K = 0\f$
//==============================================================================
class SurfaceQuadric : public CSGSurface
{
public:
explicit SurfaceQuadric(pugi::xml_node surf_node);
double evaluate(Position r) const;
double distance(Position r, Direction u, bool coincident) const;
Direction normal(Position r) const;
void to_hdf5_inner(hid_t group_id) const;
// Ax^2 + By^2 + Cz^2 + Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0
double A_, B_, C_, D_, E_, F_, G_, H_, J_, K_;
};
//==============================================================================
// Non-member functions
//==============================================================================
void read_surfaces(pugi::xml_node node);
void free_memory_surfaces();
} // namespace openmc
#endif // OPENMC_SURFACE_H

View file

@ -0,0 +1,86 @@
#ifndef OPENMC_TALLIES_DERIVATIVE_H
#define OPENMC_TALLIES_DERIVATIVE_H
#include "openmc/particle.h"
#include <unordered_map>
#include <vector>
#include "pugixml.hpp"
//==============================================================================
//! Describes a first-order derivative that can be applied to tallies.
//==============================================================================
namespace openmc {
struct TallyDerivative {
int id; //!< User-defined identifier
int variable; //!< Independent variable (like temperature)
int diff_material; //!< Material this derivative is applied to
int diff_nuclide; //!< Nuclide this material is applied to
double flux_deriv; //!< Derivative of the current particle's weight
TallyDerivative() {}
explicit TallyDerivative(pugi::xml_node node);
};
//==============================================================================
// Non-method functions
//==============================================================================
//! Read tally derivatives from a tallies.xml file
void read_tally_derivatives(pugi::xml_node node);
//! Scale the given score by its logarithmic derivative
void
apply_derivative_to_score(const Particle* p, int i_tally, int i_nuclide,
double atom_density, int score_bin, double& score);
//! Adjust diff tally flux derivatives for a particle scattering event.
//
//! Note that this subroutine will be called after absorption events in
//! addition to scattering events, but any flux derivatives scored after an
//! absorption will never be tallied. The paricle will be killed before any
//! further tallies are scored.
//
//! \param p The particle being tracked
void score_collision_derivative(const Particle* p);
//! Adjust diff tally flux derivatives for a particle tracking event.
//
//! \param p The particle being tracked
//! \param distance The distance in [cm] traveled by the particle
void score_track_derivative(const Particle* p, double distance);
//! Set the flux derivatives on differential tallies to zero.
void zero_flux_derivs();
} // namespace openmc
//==============================================================================
// Global variables
//==============================================================================
// Explicit vector template specialization declaration of threadprivate variable
// outside of the openmc namespace for the picky Intel compiler.
extern template class std::vector<openmc::TallyDerivative>;
namespace openmc {
namespace model {
extern std::vector<TallyDerivative> tally_derivs;
#pragma omp threadprivate(tally_derivs)
extern std::unordered_map<int, int> tally_deriv_map;
} // namespace model
// Independent variables
//TODO: convert to enum
constexpr int DIFF_DENSITY {1};
constexpr int DIFF_NUCLIDE_DENSITY {2};
constexpr int DIFF_TEMPERATURE {3};
} // namespace openmc
#endif // OPENMC_TALLIES_DERIVATIVE_H

View file

@ -0,0 +1,150 @@
#ifndef OPENMC_TALLIES_FILTER_H
#define OPENMC_TALLIES_FILTER_H
#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <gsl/gsl>
#include "openmc/hdf5_interface.h"
#include "openmc/particle.h"
#include "pugixml.hpp"
namespace openmc {
//==============================================================================
//! Stores bins and weights for filtered tally events.
//==============================================================================
class FilterMatch
{
public:
std::vector<int> bins_;
std::vector<double> weights_;
int i_bin_;
bool bins_present_ {false};
};
} // namespace openmc
// Without an explicit instantiation of vector<FilterMatch>, the Intel compiler
// will complain about the threadprivate directive on filter_matches. Note that
// this has to happen *outside* of the openmc namespace
extern template class std::vector<openmc::FilterMatch>;
namespace openmc {
//==============================================================================
//! Modifies tally score events.
//==============================================================================
class Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors, factory functions
Filter();
virtual ~Filter();
//! Create a new tally filter
//
//! \param[in] type Type of the filter
//! \param[in] id Unique ID for the filter. If none is passed, an ID is
//! automatically assigned
//! \return Pointer to the new filter object
static Filter* create(const std::string& type, int32_t id = -1);
//! Create a new tally filter from an XML node
//
//! \param[in] node XML node
//! \return Pointer to the new filter object
static Filter* create(pugi::xml_node node);
//! Uses an XML input to fill the filter's data fields.
virtual void from_xml(pugi::xml_node node) = 0;
//----------------------------------------------------------------------------
// Methods
virtual std::string type() const = 0;
//! Matches a tally event to a set of filter bins and weights.
//!
//! \param[out] match will contain the matching bins and corresponding
//! weights; note that there may be zero matching bins
virtual void
get_all_bins(const Particle* p, int estimator, FilterMatch& match) const = 0;
//! Writes data describing this filter to an HDF5 statepoint group.
virtual void
to_statepoint(hid_t filter_group) const
{
write_dataset(filter_group, "type", type());
write_dataset(filter_group, "n_bins", n_bins_);
}
//! Return a string describing a filter bin for the tallies.out file.
//
//! For example, an `EnergyFilter` might return the string
//! "Incoming Energy [0.625E-6, 20.0)".
virtual std::string text_label(int bin) const = 0;
//----------------------------------------------------------------------------
// Accessors
//! Get unique ID of filter
//! \return Unique ID
int32_t id() const { return id_; }
//! Assign a unique ID to the filter
//! \param[in] Unique ID to assign. A value of -1 indicates that an ID should
//! be automatically assigned
void set_id(int32_t id);
//! Get number of bins
//! \return Number of bins
int n_bins() const { return n_bins_; }
gsl::index index() const { return index_; }
//----------------------------------------------------------------------------
// Data members
protected:
int n_bins_;
private:
int32_t id_ {-1};
gsl::index index_;
};
//==============================================================================
// Global variables
//==============================================================================
namespace simulation {
extern std::vector<FilterMatch> filter_matches;
#pragma omp threadprivate(filter_matches)
} // namespace simulation
namespace model {
extern "C" int32_t n_filters;
extern std::vector<std::unique_ptr<Filter>> tally_filters;
extern std::unordered_map<int, int> filter_map;
}
//==============================================================================
// Non-member functions
//==============================================================================
//! Make sure index corresponds to a valid filter
int verify_filter(int32_t index);
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_H

View file

@ -0,0 +1,52 @@
#ifndef OPENMC_TALLIES_FILTER_AZIMUTHAL_H
#define OPENMC_TALLIES_FILTER_AZIMUTHAL_H
#include <string>
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Bins the incident neutron azimuthal angle (relative to the global xy-plane).
//==============================================================================
class AzimuthalFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~AzimuthalFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "azimuthal";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_bins(gsl::span<double> bins);
private:
//----------------------------------------------------------------------------
// Data members
std::vector<double> bins_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_AZIMUTHAL_H

View file

@ -0,0 +1,59 @@
#ifndef OPENMC_TALLIES_FILTER_CELL_H
#define OPENMC_TALLIES_FILTER_CELL_H
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Specifies which geometric cells tally events reside in.
//==============================================================================
class CellFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~CellFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "cell";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
const std::vector<int32_t>& cells() const { return cells_; }
void set_cells(gsl::span<int32_t> cells);
protected:
//----------------------------------------------------------------------------
// Data members
//! The indices of the cells binned by this filter.
std::vector<int32_t> cells_;
//! A map from cell indices to filter bin indices.
std::unordered_map<int32_t, int> map_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_CELL_H

View file

@ -0,0 +1,29 @@
#ifndef OPENMC_TALLIES_FILTER_CELLBORN_H
#define OPENMC_TALLIES_FILTER_CELLBORN_H
#include <string>
#include "openmc/tallies/filter_cell.h"
namespace openmc {
//==============================================================================
//! Specifies which cell the particle was born in.
//==============================================================================
class CellbornFilter : public CellFilter
{
public:
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "cellborn";}
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
std::string text_label(int bin) const override;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_CELLBORN_H

View file

@ -0,0 +1,29 @@
#ifndef OPENMC_TALLIES_FILTER_CELLFROM_H
#define OPENMC_TALLIES_FILTER_CELLFROM_H
#include <string>
#include "openmc/tallies/filter_cell.h"
namespace openmc {
//==============================================================================
//! Specifies which geometric cells particles exit when crossing a surface.
//==============================================================================
class CellFromFilter : public CellFilter
{
public:
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "cellfrom";}
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
std::string text_label(int bin) const override;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_CELLFROM_H

View file

@ -0,0 +1,56 @@
#ifndef OPENMC_TALLIES_FILTER_DELAYEDGROUP_H
#define OPENMC_TALLIES_FILTER_DELAYEDGROUP_H
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Bins outgoing fission neutrons in their delayed groups.
//!
//! The get_all_bins functionality is not actually used. The bins are manually
//! iterated over in the scoring subroutines.
//==============================================================================
class DelayedGroupFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~DelayedGroupFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "delayedgroup";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
const std::vector<int>& groups() const { return groups_; }
void set_groups(gsl::span<int> groups);
private:
//----------------------------------------------------------------------------
// Data members
std::vector<int> groups_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_DELAYEDGROUP_H

View file

@ -0,0 +1,51 @@
#ifndef OPENMC_TALLIES_FILTER_DISTRIBCELL_H
#define OPENMC_TALLIES_FILTER_DISTRIBCELL_H
#include <string>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Specifies which distributed geometric cells tally events reside in.
//==============================================================================
class DistribcellFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~DistribcellFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "distribcell";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
int32_t cell() const { return cell_; }
void set_cell(int32_t cell);
private:
//----------------------------------------------------------------------------
// Data members
int32_t cell_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_DISTRIBCELL_H

View file

@ -0,0 +1,78 @@
#ifndef OPENMC_TALLIES_FILTER_ENERGY_H
#define OPENMC_TALLIES_FILTER_ENERGY_H
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Bins the incident neutron energy.
//==============================================================================
class EnergyFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~EnergyFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "energy";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
const std::vector<double>& bins() const { return bins_; }
void set_bins(gsl::span<const double> bins);
bool matches_transport_groups() const { return matches_transport_groups_; }
protected:
//----------------------------------------------------------------------------
// Data members
std::vector<double> bins_;
//! True if transport group number can be used directly to get bin number
bool matches_transport_groups_ {false};
};
//==============================================================================
//! Bins the outgoing neutron energy.
//!
//! Only scattering events use the get_all_bins functionality. Nu-fission
//! tallies manually iterate over the filter bins.
//==============================================================================
class EnergyoutFilter : public EnergyFilter
{
public:
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "energyout";}
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
std::string text_label(int bin) const override;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_ENERGY_H

View file

@ -0,0 +1,62 @@
#ifndef OPENMC_TALLIES_FILTER_ENERGYFUNC_H
#define OPENMC_TALLIES_FILTER_ENERGYFUNC_H
#include <vector>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Multiplies tally scores by an arbitrary function of incident energy
//! described by a piecewise linear-linear interpolation.
//==============================================================================
class EnergyFunctionFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
EnergyFunctionFilter()
: Filter {}
{
n_bins_ = 1;
}
~EnergyFunctionFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "energyfunction";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
const std::vector<double>& energy() const { return energy_; }
const std::vector<double>& y() const { return y_; }
void set_data(gsl::span<const double> energy, gsl::span<const double> y);
private:
//----------------------------------------------------------------------------
// Data members
//! Incident neutron energy interpolation grid.
std::vector<double> energy_;
//! Interpolant values.
std::vector<double> y_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_ENERGYFUNC_H

View file

@ -0,0 +1,51 @@
#ifndef OPENMC_TALLIES_FILTER_LEGENDRE_H
#define OPENMC_TALLIES_FILTER_LEGENDRE_H
#include <string>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Gives Legendre moments of the change in scattering angle
//==============================================================================
class LegendreFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~LegendreFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "legendre";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
int order() const { return order_; }
void set_order(int order);
private:
//----------------------------------------------------------------------------
// Data members
int order_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_LEGENDRE_H

View file

@ -0,0 +1,61 @@
#ifndef OPENMC_TALLIES_FILTER_MATERIAL_H
#define OPENMC_TALLIES_FILTER_MATERIAL_H
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Specifies which material tally events reside in.
//==============================================================================
class MaterialFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~MaterialFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "material";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
std::vector<int32_t>& materials() { return materials_; }
const std::vector<int32_t>& materials() const { return materials_; }
void set_materials(gsl::span<const int32_t> materials);
private:
//----------------------------------------------------------------------------
// Data members
//! The indices of the materials binned by this filter.
std::vector<int32_t> materials_;
//! A map from material indices to filter bin indices.
std::unordered_map<int32_t, int> map_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_MATERIAL_H

View file

@ -0,0 +1,53 @@
#ifndef OPENMC_TALLIES_FILTER_MESH_H
#define OPENMC_TALLIES_FILTER_MESH_H
#include <cstdint>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Indexes the location of particle events to a regular mesh. For tracklength
//! tallies, it will produce multiple valid bins and the bin weight will
//! correspond to the fraction of the track length that lies in that bin.
//==============================================================================
class MeshFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~MeshFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "mesh";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
virtual int32_t mesh() const {return mesh_;}
virtual void set_mesh(int32_t mesh);
protected:
//----------------------------------------------------------------------------
// Data members
int32_t mesh_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_MESH_H

View file

@ -0,0 +1,28 @@
#ifndef OPENMC_TALLIES_FILTER_MESHSURFACE_H
#define OPENMC_TALLIES_FILTER_MESHSURFACE_H
#include "openmc/tallies/filter_mesh.h"
namespace openmc {
class MeshSurfaceFilter : public MeshFilter
{
public:
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "meshsurface";}
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_mesh(int32_t mesh) override;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_MESHSURFACE_H

View file

@ -0,0 +1,52 @@
#ifndef OPENMC_TALLIES_FILTER_MU_H
#define OPENMC_TALLIES_FILTER_MU_H
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Bins the incoming-outgoing direction cosine. This is only used for scatter
//! reactions.
//==============================================================================
class MuFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~MuFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "mu";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_bins(gsl::span<double> bins);
private:
//----------------------------------------------------------------------------
// Data members
std::vector<double> bins_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_MU_H

View file

@ -0,0 +1,52 @@
#ifndef OPENMC_TALLIES_FILTER_PARTICLE_H
#define OPENMC_TALLIES_FILTER_PARTICLE_H
#include <vector>
#include "openmc/particle.h"
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Bins by type of particle (e.g. neutron, photon).
//==============================================================================
class ParticleFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~ParticleFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "particle";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
const std::vector<Particle::Type>& particles() const { return particles_; }
void set_particles(gsl::span<Particle::Type> particles);
private:
//----------------------------------------------------------------------------
// Data members
std::vector<Particle::Type> particles_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_PARTICLE_H

View file

@ -0,0 +1,52 @@
#ifndef OPENMC_TALLIES_FILTER_POLAR_H
#define OPENMC_TALLIES_FILTER_POLAR_H
#include <cmath>
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Bins the incident neutron polar angle (relative to the global z-axis).
//==============================================================================
class PolarFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~PolarFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "polar";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_bins(gsl::span<double> bins);
private:
//----------------------------------------------------------------------------
// Data members
std::vector<double> bins_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_POLAR_H

View file

@ -0,0 +1,64 @@
#ifndef OPENMC_TALLIES_FILTER_SPH_HARM_H
#define OPENMC_TALLIES_FILTER_SPH_HARM_H
#include <string>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
enum class SphericalHarmonicsCosine {
scatter, particle
};
//==============================================================================
//! Gives spherical harmonics expansion moments of a tally score
//==============================================================================
class SphericalHarmonicsFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~SphericalHarmonicsFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "sphericalharmonics";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
int order() const { return order_; }
void set_order(int order);
SphericalHarmonicsCosine cosine() const { return cosine_; }
void set_cosine(gsl::cstring_span cosine);
private:
//----------------------------------------------------------------------------
// Data members
int order_;
//! The type of angle that this filter measures when binning events.
SphericalHarmonicsCosine cosine_ {SphericalHarmonicsCosine::particle};
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_SPH_HARM_H

View file

@ -0,0 +1,70 @@
#ifndef OPENMC_TALLIES_FILTER_SPTL_LEGENDRE_H
#define OPENMC_TALLIES_FILTER_SPTL_LEGENDRE_H
#include <string>
#include "openmc/tallies/filter.h"
namespace openmc {
enum class LegendreAxis {
x, y, z
};
//==============================================================================
//! Gives Legendre moments of the particle's normalized position along an axis
//==============================================================================
class SpatialLegendreFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~SpatialLegendreFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "spatiallegendre";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
int order() const { return order_; }
void set_order(int order);
LegendreAxis axis() const { return axis_; }
void set_axis(LegendreAxis axis);
double min() const { return min_; }
double max() const { return max_; }
void set_minmax(double min, double max);
private:
//----------------------------------------------------------------------------
// Data members
int order_;
//! The Cartesian coordinate axis that the Legendre expansion is applied to.
LegendreAxis axis_;
//! The minimum coordinate along the reference axis that the expansion covers.
double min_;
//! The maximum coordinate along the reference axis that the expansion covers.
double max_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_SPTL_LEGENDRE_H

View file

@ -0,0 +1,57 @@
#ifndef OPENMC_TALLIES_FILTER_SURFACE_H
#define OPENMC_TALLIES_FILTER_SURFACE_H
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Specifies which surface particles are crossing
//==============================================================================
class SurfaceFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~SurfaceFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "surface";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_surfaces(gsl::span<int32_t> surfaces);
private:
//----------------------------------------------------------------------------
// Data members
//! The indices of the surfaces binned by this filter.
std::vector<int32_t> surfaces_;
//! A map from surface indices to filter bin indices.
std::unordered_map<int32_t, int> map_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_SURFACE_H

View file

@ -0,0 +1,57 @@
#ifndef OPENMC_TALLIES_FILTER_UNIVERSE_H
#define OPENMC_TALLIES_FILTER_UNIVERSE_H
#include <cstdint>
#include <unordered_map>
#include <vector>
#include <gsl/gsl>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Specifies which geometric universes tally events reside in.
//==============================================================================
class UniverseFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~UniverseFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "universe";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_universes(gsl::span<int32_t> universes);
private:
//----------------------------------------------------------------------------
// Data members
//! The indices of the universes binned by this filter.
std::vector<int32_t> universes_;
//! A map from universe indices to filter bin indices.
std::unordered_map<int32_t, int> map_;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_UNIVERSE_H

View file

@ -0,0 +1,91 @@
#ifndef OPENMC_TALLIES_FILTER_ZERNIKE_H
#define OPENMC_TALLIES_FILTER_ZERNIKE_H
#include <string>
#include "openmc/tallies/filter.h"
namespace openmc {
//==============================================================================
//! Gives Zernike polynomial moments of a particle's position
//==============================================================================
class ZernikeFilter : public Filter
{
public:
//----------------------------------------------------------------------------
// Constructors, destructors
~ZernikeFilter() = default;
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "zernike";}
void from_xml(pugi::xml_node node) override;
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
void to_statepoint(hid_t filter_group) const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
int order() const { return order_; }
virtual void set_order(int order);
double x() const { return x_; }
void set_x(double x) { x_ = x; }
double y() const { return y_; }
void set_y(double y) { y_ = y; }
double r() const { return r_; }
void set_r(double r) { r_ = r; }
//----------------------------------------------------------------------------
// Data members
protected:
//! Cartesian x coordinate for the origin of this expansion.
double x_;
//! Cartesian y coordinate for the origin of this expansion.
double y_;
//! Maximum radius from the origin covered by this expansion.
double r_;
int order_;
};
//==============================================================================
//! Gives even order radial Zernike polynomial moments of a particle's position
//==============================================================================
class ZernikeRadialFilter : public ZernikeFilter
{
public:
//----------------------------------------------------------------------------
// Methods
std::string type() const override {return "zernikeradial";}
void get_all_bins(const Particle* p, int estimator, FilterMatch& match)
const override;
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
void set_order(int order) override;
};
} // namespace openmc
#endif // OPENMC_TALLIES_FILTER_ZERNIKE_H

View file

@ -0,0 +1,201 @@
#ifndef OPENMC_TALLIES_TALLY_H
#define OPENMC_TALLIES_TALLY_H
#include "openmc/constants.h"
#include "openmc/tallies/filter.h"
#include "openmc/tallies/trigger.h"
#include <gsl/gsl>
#include "pugixml.hpp"
#include "xtensor/xfixed.hpp"
#include "xtensor/xtensor.hpp"
#include <memory> // for unique_ptr
#include <unordered_map>
#include <string>
#include <vector>
namespace openmc {
//==============================================================================
//! A user-specified flux-weighted (or current) measurement.
//==============================================================================
class Tally {
public:
//----------------------------------------------------------------------------
// Constructors, destructors, factory functions
explicit Tally(int32_t id);
explicit Tally(pugi::xml_node node);
~Tally();
static Tally* create(int32_t id = -1);
//----------------------------------------------------------------------------
// Accessors
void set_id(int32_t id);
void set_active(bool active) { active_ = active; }
void set_writable(bool writable) { writable_ = writable; }
void set_scores(pugi::xml_node node);
void set_scores(const std::vector<std::string>& scores);
void set_nuclides(pugi::xml_node node);
void set_nuclides(const std::vector<std::string>& nuclides);
const std::vector<int32_t>& filters() const {return filters_;}
int32_t filters(int i) const {return filters_[i];}
void set_filters(gsl::span<Filter*> filters);
int32_t strides(int i) const {return strides_[i];}
int32_t n_filter_bins() const {return n_filter_bins_;}
bool writable() const { return writable_;}
//----------------------------------------------------------------------------
// Other methods.
void init_triggers(pugi::xml_node node);
void init_results();
void reset();
void accumulate();
//----------------------------------------------------------------------------
// Major public data members.
int id_; //!< User-defined identifier
std::string name_; //!< User-defined name
int type_ {TALLY_VOLUME}; //!< e.g. volume, surface current
//! Event type that contributes to this tally
int estimator_ {ESTIMATOR_TRACKLENGTH};
//! Whether this tally is currently being updated
bool active_ {false};
//! Number of realizations
int n_realizations_ {0};
std::vector<int> scores_; //!< Filter integrands (e.g. flux, fission)
//! Index of each nuclide to be tallied. -1 indicates total material.
std::vector<int> nuclides_ {-1};
//! True if this tally has a bin for every nuclide in the problem
bool all_nuclides_ {false};
//! Results for each bin -- the first dimension of the array is for scores
//! (e.g. flux, total reaction rate, fission reaction rate, etc.) and the
//! second dimension of the array is for the combination of filters
//! (e.g. specific cell, specific energy group, etc.)
xt::xtensor<double, 3> results_;
//! True if this tally should be written to statepoint files
bool writable_ {true};
//----------------------------------------------------------------------------
// Miscellaneous public members.
// We need to have quick access to some filters. The following gives indices
// for various filters that could be in the tally or C_NONE if they are not
// present.
int energyout_filter_ {C_NONE};
int delayedgroup_filter_ {C_NONE};
bool depletion_rx_ {false}; //!< Has depletion reactions (e.g. (n,2n))
std::vector<Trigger> triggers_;
int deriv_ {C_NONE}; //!< Index of a TallyDerivative object for diff tallies.
private:
//----------------------------------------------------------------------------
// Private data.
std::vector<int32_t> filters_; //!< Filter indices in global filters array
//! Index strides assigned to each filter to support 1D indexing.
std::vector<int32_t> strides_;
int32_t n_filter_bins_ {0};
gsl::index index_;
};
//==============================================================================
// Global variable declarations
//==============================================================================
namespace model {
extern std::vector<std::unique_ptr<Tally>> tallies;
extern std::vector<int> active_tallies;
extern std::vector<int> active_analog_tallies;
extern std::vector<int> active_tracklength_tallies;
extern std::vector<int> active_collision_tallies;
extern std::vector<int> active_meshsurf_tallies;
extern std::vector<int> active_surface_tallies;
extern std::unordered_map<int, int> tally_map;
}
namespace simulation {
//! Global tallies (such as k-effective estimators)
extern xt::xtensor_fixed<double, xt::xshape<N_GLOBAL_TALLIES, 3>> global_tallies;
//! Number of realizations for global tallies
extern "C" int32_t n_realizations;
}
// It is possible to protect accumulate operations on global tallies by using an
// atomic update. However, when multiple threads accumulate to the same global
// tally, it can cause a higher cache miss rate due to invalidation. Thus, we
// use threadprivate variables to accumulate global tallies and then reduce at
// the end of a generation.
extern double global_tally_absorption;
extern double global_tally_collision;
extern double global_tally_tracklength;
extern double global_tally_leakage;
#pragma omp threadprivate(global_tally_absorption, global_tally_collision, \
global_tally_tracklength, global_tally_leakage)
//==============================================================================
// Non-member functions
//==============================================================================
//! Read tally specification from tallies.xml
void read_tallies_xml();
//! \brief Accumulate the sum of the contributions from each history within the
//! batch to a new random variable
void accumulate_tallies();
//! Determine which tallies should be active
void setup_active_tallies();
// Alias for the type returned by xt::adapt(...). N is the dimension of the
// multidimensional array
template <std::size_t N>
using adaptor_type = xt::xtensor_adaptor<xt::xbuffer_adaptor<double*&, xt::no_ownership>, N>;
#ifdef OPENMC_MPI
//! Collect all tally results onto master process
void reduce_tally_results();
#endif
void free_memory_tally();
} // namespace openmc
#endif // OPENMC_TALLIES_TALLY_H

View file

@ -0,0 +1,96 @@
#ifndef OPENMC_TALLIES_TALLY_SCORING_H
#define OPENMC_TALLIES_TALLY_SCORING_H
#include "openmc/particle.h"
#include "openmc/tallies/tally.h"
namespace openmc {
//==============================================================================
//! An iterator over all combinations of a tally's matching filter bins.
//
//! This iterator handles two distinct tasks. First, it maps the N-dimensional
//! space created by the indices of N filters onto a 1D sequence. In other
//! words, it provides a single number that uniquely identifies a combination of
//! bins for many filters. Second, it handles the task of finding each valid
//! combination of filter bins given that each filter can have 1 or 2 or many
//! bins that are valid for the current tally event.
//==============================================================================
class FilterBinIter
{
public:
//! Construct an iterator over bins that match a given particle's state.
FilterBinIter(const Tally& tally, const Particle* p);
//! Construct an iterator over all filter bin combinations.
//
//! \param end if true, the returned iterator indicates the end of a loop.
FilterBinIter(const Tally& tally, bool end);
bool operator==(const FilterBinIter& other) const
{return index_ == other.index_;}
bool operator!=(const FilterBinIter& other) const
{return !(*this == other);}
FilterBinIter& operator++();
int index_ {1};
double weight_ {1.};
private:
void compute_index_weight();
const Tally& tally_;
};
//==============================================================================
// Non-member functions
//==============================================================================
//! Score tallies using a 1 / Sigma_t estimate of the flux.
//
//! This is triggered after every collision. It is invalid for tallies that
//! require post-collison information because it can score reactions that didn't
//! actually occur, and we don't a priori know what the outcome will be for
//! reactions that we didn't sample. It is assumed the material is not void
//! since collisions do not occur in voids.
//
//! \param p The particle being tracked
void score_collision_tally(Particle* p);
//! Score tallies based on a simple count of events (for continuous energy).
//
//! Analog tallies are triggered at every collision, not every event.
//
//! \param p The particle being tracked
void score_analog_tally_ce(Particle* p);
//! Score tallies based on a simple count of events (for multigroup).
//
//! Analog tallies are triggered at every collision, not every event.
//
//! \param p The particle being tracked
void score_analog_tally_mg(const Particle* p);
//! Score tallies using a tracklength estimate of the flux.
//
//! This is triggered at every event (surface crossing, lattice crossing, or
//! collision) and thus cannot be done for tallies that require post-collision
//! information.
//
//! \param p The particle being tracked
//! \param distance The distance in [cm] traveled by the particle
void score_tracklength_tally(Particle* p, double distance);
//! Score surface or mesh-surface tallies for particle currents.
//
//! \param p The particle being tracked
//! \param tallies A vector of tallies to score to
void score_surface_tally(const Particle* p, const std::vector<int>& tallies);
} // namespace openmc
#endif // OPENMC_TALLIES_TALLY_SCORING_H

View file

@ -0,0 +1,50 @@
#ifndef OPENMC_TALLIES_TRIGGER_H
#define OPENMC_TALLIES_TRIGGER_H
#include <string>
#include "pugixml.hpp"
namespace openmc {
//==============================================================================
// Type definitions
//==============================================================================
enum class TriggerMetric {
variance, relative_error, standard_deviation, not_active
};
//! Stops the simulation early if a desired tally uncertainty is reached.
struct Trigger {
TriggerMetric metric; //!< The type of uncertainty (e.g. std dev) measured
double threshold; //!< Uncertainty value below which trigger is satisfied
int score_index; //!< Index of the relevant score in the tally's arrays
};
//! Stops the simulation early if a desired k-effective uncertainty is reached.
struct KTrigger
{
TriggerMetric metric {TriggerMetric::not_active};
double threshold {0.};
};
//==============================================================================
// Global variable declarations
//==============================================================================
//TODO: consider a different namespace
namespace settings {
extern KTrigger keff_trigger;
}
//==============================================================================
// Non-memeber functions
//==============================================================================
void check_triggers();
} // namespace openmc
#endif // OPENMC_TALLIES_TRIGGER_H

130
include/openmc/thermal.h Normal file
View file

@ -0,0 +1,130 @@
#ifndef OPENMC_THERMAL_H
#define OPENMC_THERMAL_H
#include <cstddef>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "xtensor/xtensor.hpp"
#include "openmc/angle_energy.h"
#include "openmc/endf.h"
#include "openmc/hdf5_interface.h"
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
// Constants
//==============================================================================
// Secondary energy mode for S(a,b) inelastic scattering
// TODO: Convert to enum
constexpr int SAB_SECONDARY_EQUAL {0}; // Equally-likely outgoing energy bins
constexpr int SAB_SECONDARY_SKEWED {1}; // Skewed outgoing energy bins
constexpr int SAB_SECONDARY_CONT {2}; // Continuous, linear-linear interpolation
// Elastic mode for S(a,b) elastic scattering
// TODO: Convert to enum
constexpr int SAB_ELASTIC_INCOHERENT {3}; // Incoherent elastic scattering
constexpr int SAB_ELASTIC_COHERENT {4}; // Coherent elastic scattering (Bragg edges)
//==============================================================================
// Global variables
//==============================================================================
class ThermalScattering;
namespace data {
extern std::vector<std::unique_ptr<ThermalScattering>> thermal_scatt;
extern std::unordered_map<std::string, int> thermal_scatt_map;
}
//==============================================================================
//! Secondary angle-energy data for thermal neutron scattering at a single
//! temperature
//==============================================================================
class ThermalData {
public:
ThermalData(hid_t group);
//! Calculate the cross section
//
//! \param[in] E Incident neutron energy in [eV]
//! \param[out] elastic Elastic scattering cross section in [b]
//! \param[out] inelastic Inelastic scattering cross section in [b]
void calculate_xs(double E, double* elastic, double* inelastic) const;
//! Sample an outgoing energy and angle
//
//! \param[in] micro_xs Microscopic cross sections
//! \param[in] E_in Incident neutron energy in [eV]
//! \param[out] E_out Outgoing neutron energy in [eV]
//! \param[out] mu Outgoing scattering angle cosine
void sample(const NuclideMicroXS& micro_xs, double E_in,
double* E_out, double* mu);
private:
struct Reaction {
// Default constructor
Reaction() { }
// Data members
std::unique_ptr<Function1D> xs; //!< Cross section
std::unique_ptr<AngleEnergy> distribution; //!< Secondary angle-energy distribution
};
// Inelastic scattering data
Reaction elastic_;
Reaction inelastic_;
// ThermalScattering needs access to private data members
friend class ThermalScattering;
};
//==============================================================================
//! Data for thermal neutron scattering, typically off light isotopes in
//! moderating materials such as water, graphite, BeO, etc.
//==============================================================================
class ThermalScattering {
public:
ThermalScattering(hid_t group, const std::vector<double>& temperature);
//! Determine inelastic/elastic cross section at given energy
//!
//! \param[in] E incoming energy in [eV]
//! \param[in] sqrtkT square-root of temperature multipled by Boltzmann's constant
//! \param[out] i_temp corresponding temperature index
//! \param[out] elastic Thermal elastic scattering cross section
//! \param[out] inelastic Thermal inelastic scattering cross section
void calculate_xs(double E, double sqrtkT, int* i_temp, double* elastic,
double* inelastic) const;
//! Determine whether table applies to a particular nuclide
//!
//! \param[in] name Name of the nuclide, e.g., "H1"
//! \return Whether table applies to the nuclide
bool has_nuclide(const char* name) const;
// Sample an outgoing energy and angle
void sample(const NuclideMicroXS& micro_xs, double E_in,
double* E_out, double* mu);
std::string name_; //!< name of table, e.g. "c_H_in_H2O"
double awr_; //!< weight of nucleus in neutron masses
double energy_max_; //!< maximum energy for thermal scattering in [eV]
std::vector<double> kTs_; //!< temperatures in [eV] (k*T)
std::vector<std::string> nuclides_; //!< Valid nuclides
//! cross sections and distributions at each temperature
std::vector<ThermalData> data_;
};
void free_memory_thermal();
} // namespace openmc
#endif // OPENMC_THERMAL_H

67
include/openmc/timer.h Normal file
View file

@ -0,0 +1,67 @@
#ifndef OPENMC_TIMER_H
#define OPENMC_TIMER_H
#include <chrono>
namespace openmc {
//==============================================================================
// Global variables
//==============================================================================
class Timer;
namespace simulation {
extern Timer time_active;
extern Timer time_bank;
extern Timer time_bank_sample;
extern Timer time_bank_sendrecv;
extern Timer time_finalize;
extern Timer time_inactive;
extern Timer time_initialize;
extern Timer time_read_xs;
extern Timer time_tallies;
extern Timer time_total;
extern Timer time_transport;
} // namespace simulation
//==============================================================================
//! Class for measuring time elapsed
//==============================================================================
class Timer {
public:
using clock = std::chrono::high_resolution_clock;
Timer() {};
//! Start running the timer
void start();
//! Get total elapsed time in seconds
//! \return Elapsed time in [s]
double elapsed();
//! Stop running the timer
void stop();
//! Stop the timer and reset its elapsed time
void reset();
private:
bool running_ {false}; //!< is timer running?
std::chrono::time_point<clock> start_; //!< starting point for clock
double elapsed_ {0.0}; //!< elapsed time in [s]
};
//==============================================================================
// Non-member functions
//==============================================================================
void reset_timers();
} // namespace openmc
#endif // OPENMC_TIMER_H

View file

@ -0,0 +1,18 @@
#ifndef OPENMC_TRACK_OUTPUT_H
#define OPENMC_TRACK_OUTPUT_H
#include "openmc/particle.h"
namespace openmc {
//==============================================================================
// Non-member functions
//==============================================================================
void add_particle_track();
void write_particle_track(const Particle& p);
void finalize_particle_track(const Particle& p);
} // namespace openmc
#endif // OPENMC_TRACK_OUTPUT_H

33
include/openmc/urr.h Normal file
View file

@ -0,0 +1,33 @@
//! \brief UrrData information for the unresolved resonance treatment
#ifndef OPENMC_URR_H
#define OPENMC_URR_H
#include "xtensor/xtensor.hpp"
#include "openmc/constants.h"
#include "openmc/hdf5_interface.h"
namespace openmc {
//==============================================================================
//! UrrData contains probability tables for the unresolved resonance range.
//==============================================================================
class UrrData{
public:
Interpolation interp_; //!< interpolation type
int inelastic_flag_; //!< inelastic competition flag
int absorption_flag_; //!< other absorption flag
bool multiply_smooth_; //!< multiply by smooth cross section?
int n_energy_; //!< number of energy points
xt::xtensor<double, 1> energy_; //!< incident energies
xt::xtensor<double, 3> prob_; //!< Actual probability tables
//! \brief Load the URR data from the provided HDF5 group
explicit UrrData(hid_t group_id);
};
} // namespace openmc
#endif // OPENMC_URR_H

View file

@ -0,0 +1,80 @@
#ifndef OPENMC_VOLUME_CALC_H
#define OPENMC_VOLUME_CALC_H
#include "openmc/position.h"
#include "pugixml.hpp"
#include "xtensor/xtensor.hpp"
#include <string>
#include <vector>
namespace openmc {
//==============================================================================
// Volume calculation class
//==============================================================================
class VolumeCalculation {
public:
// Aliases, types
struct Result {
std::array<double, 2> volume; //!< Mean/standard deviation of volume
std::vector<int> nuclides; //!< Index of nuclides
std::vector<double> atoms; //!< Number of atoms for each nuclide
std::vector<double> uncertainty; //!< Uncertainty on number of atoms
}; // Results for a single domain
// Constructors
VolumeCalculation(pugi::xml_node node);
// Methods
//! \brief Stochastically determine the volume of a set of domains along with the
//! average number densities of nuclides within the domain
//
//! \return Vector of results for each user-specified domain
std::vector<Result> execute() const;
//! \brief Write volume calculation results to HDF5 file
//
//! \param[in] filename Path to HDF5 file to write
//! \param[in] results Vector of results for each domain
void to_hdf5(const std::string& filename, const std::vector<Result>& results) const;
// Data members
int domain_type_; //!< Type of domain (cell, material, etc.)
int n_samples_; //!< Number of samples to use
Position lower_left_; //!< Lower-left position of bounding box
Position upper_right_; //!< Upper-right position of bounding box
std::vector<int> domain_ids_; //!< IDs of domains to find volumes of
private:
//! \brief Check whether a material has already been hit for a given domain.
//! If not, add new entries to the vectors
//
//! \param[in] i_material Index in global materials vector
//! \param[in,out] indices Vector of material indices
//! \param[in,out] hits Number of hits corresponding to each material
void check_hit(int i_material, std::vector<int>& indices,
std::vector<int>& hits) const;
};
//==============================================================================
// Global variables
//==============================================================================
namespace model {
extern std::vector<VolumeCalculation> volume_calcs;
}
//==============================================================================
// Non-member functions
//==============================================================================
void free_memory_volume();
} // namespace openmc
#endif // OPENMC_VOLUME_CALC_H

92
include/openmc/wmp.h Normal file
View file

@ -0,0 +1,92 @@
#ifndef OPENMC_WMP_H
#define OPENMC_WMP_H
#include "hdf5.h"
#include "xtensor/xtensor.hpp"
#include <array>
#include <complex>
#include <string>
#include <tuple>
namespace openmc {
//========================================================================
// Constants
//========================================================================
// Constants that determine which value to access
constexpr int MP_EA {0}; // Pole
constexpr int MP_RS {1}; // Residue scattering
constexpr int MP_RA {2}; // Residue absorption
constexpr int MP_RF {3}; // Residue fission
// Polynomial fit indices
constexpr int FIT_S {0}; // Scattering
constexpr int FIT_A {1}; // Absorption
constexpr int FIT_F {2}; // Fission
// Multipole HDF5 file version
constexpr std::array<int, 2> WMP_VERSION {1, 1};
//========================================================================
// Windowed multipole data
//========================================================================
class WindowedMultipole {
public:
// Constructors, destructors
WindowedMultipole(hid_t group);
// Methods
//! \brief Evaluate the windowed multipole equations for cross sections in the
//! resolved resonance regions
//!
//! \param E Incident neutron energy in [eV]
//! \param sqrtkT Square root of temperature times Boltzmann constant
//! \return Tuple of elastic scattering, absorption, and fission cross sections in [b]
std::tuple<double, double, double> evaluate(double E, double sqrtkT);
//! \brief Evaluates the windowed multipole equations for the derivative of
//! cross sections in the resolved resonance regions with respect to
//! temperature.
//!
//! \param E Incident neutron energy in [eV]
//! \param sqrtkT Square root of temperature times Boltzmann constant
//! \return Tuple of derivatives of elastic scattering, absorption, and
//! fission cross sections in [b/K]
std::tuple<double, double, double> evaluate_deriv(double E, double sqrtkT);
// Data members
std::string name_; //!< Name of nuclide
bool fissionable_; //!< Is the nuclide fissionable?
xt::xtensor<std::complex<double>, 2> data_; //!< Poles and residues
double sqrt_awr_; //!< Square root of atomic weight ratio
double E_min_; //!< Minimum energy in [eV]
double E_max_; //!< Maximum energy in [eV]
double spacing_; //!< Spacing in sqrt(E) space
int fit_order_; //!< Order of the fit
xt::xtensor<int, 2> windows_; //!< Indices of pole at start/end of window
xt::xtensor<double, 3> curvefit_; //!< Fitting function (reaction, coeff index, window index)
xt::xtensor<bool, 1> broaden_poly_; //!< Whether to broaden curvefit
};
//========================================================================
// Non-member functions
//========================================================================
//! Check to make sure WMP library data version matches
//!
//! \param[in] file HDF5 file object
void check_wmp_version(hid_t file);
//! \brief Checks for the existence of a multipole library in the directory and
//! loads it
//!
//! \param[in] i_nuclide Index in global nuclides array
void read_multipole_data(int i_nuclide);
} // namespace openmc
#endif // OPENMC_WMP_H

View file

@ -0,0 +1,53 @@
#ifndef OPENMC_XML_INTERFACE_H
#define OPENMC_XML_INTERFACE_H
#include <cstddef> // for size_t
#include <sstream> // for stringstream
#include <string>
#include <vector>
#include "pugixml.hpp"
#include "xtensor/xarray.hpp"
#include "xtensor/xadapt.hpp"
namespace openmc {
inline bool
check_for_node(pugi::xml_node node, const char *name)
{
return node.attribute(name) || node.child(name);
}
std::string get_node_value(pugi::xml_node node, const char* name,
bool lowercase=false, bool strip=false);
bool get_node_value_bool(pugi::xml_node node, const char* name);
template <typename T>
std::vector<T> get_node_array(pugi::xml_node node, const char* name,
bool lowercase=false)
{
// Get value of node attribute/child
std::string s {get_node_value(node, name, lowercase)};
// Read values one by one into vector
std::stringstream iss {s};
T value;
std::vector<T> values;
while (iss >> value)
values.push_back(value);
return values;
}
template <typename T>
xt::xarray<T> get_node_xarray(pugi::xml_node node, const char* name,
bool lowercase=false)
{
std::vector<T> v = get_node_array<T>(node, name, lowercase);
std::vector<std::size_t> shape = {v.size()};
return xt::adapt(v, shape);
}
} // namespace openmc
#endif // OPENMC_XML_INTERFACE_H

140
include/openmc/xsdata.h Normal file
View file

@ -0,0 +1,140 @@
//! \file xsdata.h
//! A collection of classes for containing the Multi-Group Cross Section data
#ifndef OPENMC_XSDATA_H
#define OPENMC_XSDATA_H
#include <memory>
#include <vector>
#include "xtensor/xtensor.hpp"
#include "openmc/hdf5_interface.h"
#include "openmc/scattdata.h"
namespace openmc {
//==============================================================================
// XSDATA contains the temperature-independent cross section data for an MGXS
//==============================================================================
class XsData {
private:
//! \brief Reads scattering data from the HDF5 file
void
scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang,
int scatter_format, int final_scatter_format, int order_data);
//! \brief Reads fission data from the HDF5 file
void
fission_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic);
//! \brief Reads fission data formatted as chi and nu-fission vectors from
// the HDF5 file when beta is provided.
void
fission_vector_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic);
//! \brief Reads fission data formatted as chi and nu-fission vectors from
// the HDF5 file when beta is not provided.
void
fission_vector_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang);
//! \brief Reads fission data formatted as chi and nu-fission vectors from
// the HDF5 file when no delayed data is provided.
void
fission_vector_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang);
//! \brief Reads fission data formatted as a nu-fission matrix from
// the HDF5 file when beta is provided.
void
fission_matrix_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang, bool is_isotropic);
//! \brief Reads fission data formatted as a nu-fission matrix from
// the HDF5 file when beta is not provided.
void
fission_matrix_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang);
//! \brief Reads fission data formatted as a nu-fission matrix from
// the HDF5 file when no delayed data is provided.
void
fission_matrix_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang);
public:
// The following quantities have the following dimensions:
// [angle][incoming group]
xt::xtensor<double, 2> total;
xt::xtensor<double, 2> absorption;
xt::xtensor<double, 2> nu_fission;
xt::xtensor<double, 2> prompt_nu_fission;
xt::xtensor<double, 2> kappa_fission;
xt::xtensor<double, 2> fission;
xt::xtensor<double, 2> inverse_velocity;
// decay_rate has the following dimensions:
// [angle][delayed group]
xt::xtensor<double, 2> decay_rate;
// delayed_nu_fission has the following dimensions:
// [angle][delayed group][incoming group]
xt::xtensor<double, 3> delayed_nu_fission;
// chi_prompt has the following dimensions:
// [angle][incoming group][outgoing group]
xt::xtensor<double, 3> chi_prompt;
// chi_delayed has the following dimensions:
// [angle][incoming group][outgoing group][delayed group]
xt::xtensor<double, 4> chi_delayed;
// scatter has the following dimensions: [angle]
std::vector<std::shared_ptr<ScattData>> scatter;
XsData() = default;
//! \brief Constructs the XsData object metadata.
//!
//! @param num_groups Number of energy groups.
//! @param num_delayed_groups Number of delayed groups.
//! @param fissionable Is this a fissionable data set or not.
//! @param scatter_format The scattering representation of the file.
//! @param n_pol Number of polar angles.
//! @param n_azi Number of azimuthal angles.
XsData(bool fissionable, int scatter_format, int n_pol, int n_azi);
//! \brief Loads the XsData object from the HDF5 file
//!
//! @param xs_id HDF5 group id for the cross section data.
//! @param fissionable Is this a fissionable data set or not.
//! @param scatter_format The scattering representation of the file.
//! @param final_scatter_format The scattering representation after reading;
//! this is different from scatter_format if converting a Legendre to
//! a tabular representation.
//! @param order_data The dimensionality of the scattering data in the file.
//! @param is_isotropic Is this an isotropic or angular with respect to
//! the incoming particle.
//! @param n_pol Number of polar angles.
//! @param n_azi Number of azimuthal angles.
void
from_hdf5(hid_t xsdata_grp, bool fissionable, int scatter_format,
int final_scatter_format, int order_data, bool is_isotropic, int n_pol,
int n_azi);
//! \brief Combines the microscopic data to a macroscopic object.
//!
//! @param micros Microscopic objects to combine.
//! @param scalars Scalars to multiply the microscopic data by.
void
combine(const std::vector<XsData*>& those_xs, const std::vector<double>& scalars);
//! \brief Checks to see if this and that are able to be combined
//!
//! This comparison is used when building macroscopic cross sections
//! from microscopic cross sections.
//! @param that The other XsData to compare to this one.
//! @return True if they can be combined.
bool
equiv(const XsData& that);
};
} //namespace openmc
#endif // OPENMC_XSDATA_H