mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-21 06:25:30 -04:00
Replace xtensor with internal Tensor/View classes (#3805)
Co-authored-by: John Tramm <jtramm@gmail.com>
This commit is contained in:
parent
c6ef84d1d5
commit
977ade79a1
73 changed files with 3111 additions and 908 deletions
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -1,12 +1,6 @@
|
|||
[submodule "vendor/pugixml"]
|
||||
path = vendor/pugixml
|
||||
url = https://github.com/zeux/pugixml.git
|
||||
[submodule "vendor/xtensor"]
|
||||
path = vendor/xtensor
|
||||
url = https://github.com/xtensor-stack/xtensor.git
|
||||
[submodule "vendor/xtl"]
|
||||
path = vendor/xtl
|
||||
url = https://github.com/xtensor-stack/xtl.git
|
||||
[submodule "vendor/fmt"]
|
||||
path = vendor/fmt
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
|
|
|
|||
|
|
@ -266,23 +266,6 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# xtensor header-only library
|
||||
#===============================================================================
|
||||
|
||||
if(OPENMC_FORCE_VENDORED_LIBS)
|
||||
add_subdirectory(vendor/xtl)
|
||||
set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl)
|
||||
add_subdirectory(vendor/xtensor)
|
||||
else()
|
||||
find_package_write_status(xtensor)
|
||||
if (NOT xtensor_FOUND)
|
||||
add_subdirectory(vendor/xtl)
|
||||
set(xtl_DIR ${CMAKE_CURRENT_BINARY_DIR}/vendor/xtl)
|
||||
add_subdirectory(vendor/xtensor)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Catch2 library
|
||||
#===============================================================================
|
||||
|
|
@ -498,7 +481,7 @@ endif()
|
|||
# target_link_libraries treats any arguments starting with - but not -l as
|
||||
# linker flags. Thus, we can pass both linker flags and libraries together.
|
||||
target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES}
|
||||
xtensor fmt::fmt ${CMAKE_DL_LIBS})
|
||||
fmt::fmt ${CMAKE_DL_LIBS})
|
||||
|
||||
if(TARGET pugixml::pugixml)
|
||||
target_link_libraries(libopenmc pugixml::pugixml)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ get_filename_component(_OPENMC_PREFIX "${OpenMC_CMAKE_DIR}/../../.." ABSOLUTE)
|
|||
|
||||
find_package(fmt CONFIG REQUIRED HINTS ${_OPENMC_PREFIX})
|
||||
find_package(pugixml CONFIG REQUIRED HINTS ${_OPENMC_PREFIX})
|
||||
find_package(xtl CONFIG REQUIRED HINTS ${_OPENMC_PREFIX})
|
||||
find_package(xtensor CONFIG REQUIRED HINTS ${_OPENMC_PREFIX})
|
||||
if(@OPENMC_USE_DAGMC@)
|
||||
find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ packages should be installed, for example in Homebrew via:
|
|||
|
||||
.. code-block:: sh
|
||||
|
||||
brew install llvm cmake xtensor hdf5 python libomp libpng
|
||||
brew install llvm cmake hdf5 python libomp libpng
|
||||
|
||||
The compiler provided by the above LLVM package should be used in place of the
|
||||
one provisioned by XCode, which does not support the multithreading library used
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "openmc/particle.h"
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -14,9 +14,9 @@ namespace openmc {
|
|||
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
|
||||
tensor::Tensor<double> pdf; //!< Bremsstrahlung energy PDF
|
||||
tensor::Tensor<double> cdf; //!< Bremsstrahlung energy CDF
|
||||
tensor::Tensor<double> yield; //!< Photon yield
|
||||
};
|
||||
|
||||
class Bremsstrahlung {
|
||||
|
|
@ -32,9 +32,9 @@ public:
|
|||
|
||||
namespace data {
|
||||
|
||||
extern xt::xtensor<double, 1>
|
||||
extern tensor::Tensor<double>
|
||||
ttb_e_grid; //! energy T of incident electron in [eV]
|
||||
extern xt::xtensor<double, 1>
|
||||
extern tensor::Tensor<double>
|
||||
ttb_k_grid; //! reduced energy W/T of emitted photon
|
||||
|
||||
} // namespace data
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define OPENMC_DISTRIBUTION_ENERGY_H
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/endf.h"
|
||||
|
|
@ -86,9 +86,9 @@ private:
|
|||
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
|
||||
tensor::Tensor<double> e_out; //!< Outgoing energies in [eV]
|
||||
tensor::Tensor<double> p; //!< Probability density
|
||||
tensor::Tensor<double> c; //!< Cumulative distribution
|
||||
};
|
||||
|
||||
int n_region_; //!< Number of inteprolation regions
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <cstdint> // for int64_t
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <hdf5.h>
|
||||
|
||||
#include "openmc/array.h"
|
||||
|
|
@ -24,7 +24,7 @@ namespace simulation {
|
|||
extern double keff_generation; //!< Single-generation k on each processor
|
||||
extern array<double, 2> k_sum; //!< Used to reduce sum and sum_sq
|
||||
extern vector<double> entropy; //!< Shannon entropy at each generation
|
||||
extern xt::xtensor<double, 1> source_frac; //!< Source fraction for UFS
|
||||
extern tensor::Tensor<double> source_frac; //!< Source fraction for UFS
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
|
||||
#include "hdf5.h"
|
||||
#include "hdf5_hl.h"
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -166,24 +165,19 @@ void read_attribute(hid_t obj_id, const char* name, vector<T>& vec)
|
|||
read_attr(obj_id, name, H5TypeMap<T>::type_id, vec.data());
|
||||
}
|
||||
|
||||
// Generic array version
|
||||
// Tensor version
|
||||
template<typename T>
|
||||
void read_attribute(hid_t obj_id, const char* name, xt::xarray<T>& arr)
|
||||
void read_attribute(hid_t obj_id, const char* name, tensor::Tensor<T>& tensor)
|
||||
{
|
||||
// Get shape of attribute array
|
||||
// Get shape of attribute
|
||||
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;
|
||||
vector<T> buffer(size);
|
||||
// Resize tensor and read data directly
|
||||
vector<size_t> tshape(shape.begin(), shape.end());
|
||||
tensor.resize(tshape);
|
||||
|
||||
// Read data from attribute
|
||||
read_attr(obj_id, name, H5TypeMap<T>::type_id, buffer.data());
|
||||
|
||||
// Adapt array into xarray
|
||||
arr = xt::adapt(buffer, shape);
|
||||
read_attr(obj_id, name, H5TypeMap<T>::type_id, tensor.data());
|
||||
}
|
||||
|
||||
// overload for std::string
|
||||
|
|
@ -290,63 +284,34 @@ void read_dataset(
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void read_dataset(hid_t dset, xt::xarray<T>& arr, bool indep = false)
|
||||
void read_dataset(hid_t dset, tensor::Tensor<T>& tensor, bool indep = false)
|
||||
{
|
||||
// Get shape of dataset
|
||||
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);
|
||||
// Resize tensor and read data directly
|
||||
vector<size_t> tshape(shape.begin(), shape.end());
|
||||
tensor.resize(tshape);
|
||||
|
||||
// Read data from attribute
|
||||
// Read data from dataset
|
||||
read_dataset_lowlevel(
|
||||
dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, arr.data());
|
||||
dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, tensor.data());
|
||||
}
|
||||
|
||||
template<>
|
||||
void read_dataset(
|
||||
hid_t dset, xt::xarray<std::complex<double>>& arr, bool indep);
|
||||
hid_t dset, tensor::Tensor<std::complex<double>>& tensor, bool indep);
|
||||
|
||||
template<typename T>
|
||||
void read_dataset(
|
||||
hid_t obj_id, const char* name, xt::xarray<T>& arr, bool indep = false)
|
||||
hid_t obj_id, const char* name, tensor::Tensor<T>& tensor, bool indep = false)
|
||||
{
|
||||
// Open dataset and read array
|
||||
// Open dataset and read tensor
|
||||
hid_t dset = open_dataset(obj_id, name);
|
||||
read_dataset(dset, arr, indep);
|
||||
read_dataset(dset, tensor, 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
|
||||
vector<hsize_t> hsize_t_shape = object_shape(dset);
|
||||
close_dataset(dset);
|
||||
|
||||
// cast from hsize_t to size_t
|
||||
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)
|
||||
|
|
@ -358,31 +323,22 @@ inline void read_dataset(
|
|||
r.z = x[2];
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<typename T>
|
||||
inline void read_dataset_as_shape(
|
||||
hid_t obj_id, const char* name, xt::xtensor<T, N>& arr, bool indep = false)
|
||||
hid_t obj_id, const char* name, tensor::Tensor<T>& tensor, 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;
|
||||
vector<T> buffer(size);
|
||||
|
||||
// Read data from attribute
|
||||
// Read data directly into pre-shaped tensor
|
||||
read_dataset_lowlevel(
|
||||
dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, buffer.data());
|
||||
|
||||
// Adapt into xarray
|
||||
arr = xt::adapt(buffer, arr.shape());
|
||||
dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, tensor.data());
|
||||
|
||||
close_dataset(dset);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
inline void read_nd_vector(hid_t obj_id, const char* name,
|
||||
xt::xtensor<T, N>& result, bool must_have = false)
|
||||
template<typename T>
|
||||
inline void read_nd_tensor(hid_t obj_id, const char* name,
|
||||
tensor::Tensor<T>& result, bool must_have = false)
|
||||
{
|
||||
if (object_exists(obj_id, name)) {
|
||||
read_dataset_as_shape(obj_id, name, result, true);
|
||||
|
|
@ -496,12 +452,16 @@ inline void write_dataset(
|
|||
false, buffer.data());
|
||||
}
|
||||
|
||||
// Template for xarray, xtensor, etc.
|
||||
template<typename D>
|
||||
inline void write_dataset(
|
||||
hid_t obj_id, const char* name, const xt::xcontainer<D>& arr)
|
||||
// Template for Tensor and StaticTensor2D. A SFINAE guard is used here to
|
||||
// prevent this template from matching vector/string types that have their own
|
||||
// overloads above. A generic Container parameter avoids duplicating the body
|
||||
// for both Tensor<T> and StaticTensor2D<T,R,C>.
|
||||
template<typename Container,
|
||||
typename =
|
||||
std::enable_if_t<tensor::is_tensor<std::decay_t<Container>>::value>>
|
||||
inline void write_dataset(hid_t obj_id, const char* name, const Container& arr)
|
||||
{
|
||||
using T = typename D::value_type;
|
||||
using T = typename std::decay_t<Container>::value_type;
|
||||
auto s = arr.shape();
|
||||
vector<hsize_t> dims {s.cbegin(), s.cend()};
|
||||
write_dataset_lowlevel(obj_id, dims.size(), dims.data(), name,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include "openmc/span.h"
|
||||
#include "openmc/tensor.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include <hdf5.h>
|
||||
|
||||
#include "openmc/bremsstrahlung.h"
|
||||
|
|
@ -189,7 +189,7 @@ public:
|
|||
vector<int> nuclide_; //!< Indices in nuclides vector
|
||||
vector<int> element_; //!< Indices in elements vector
|
||||
NCrystalMat ncrystal_mat_; //!< NCrystal material object
|
||||
xt::xtensor<double, 1> atom_density_; //!< Nuclide atom density in [atom/b-cm]
|
||||
tensor::Tensor<double> 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 charge_density_; //!< Total charge density in [e/b-cm]
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "openmc/tensor.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
|
||||
#include "openmc/bounding_box.h"
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -284,8 +284,8 @@ public:
|
|||
virtual Position upper_right() const = 0;
|
||||
|
||||
// Data members
|
||||
xt::xtensor<double, 1> lower_left_; //!< Lower-left coordinates of mesh
|
||||
xt::xtensor<double, 1> upper_right_; //!< Upper-right coordinates of mesh
|
||||
tensor::Tensor<double> lower_left_; //!< Lower-left coordinates of mesh
|
||||
tensor::Tensor<double> upper_right_; //!< Upper-right coordinates of mesh
|
||||
int id_ {-1}; //!< Mesh ID
|
||||
std::string name_; //!< User-specified name
|
||||
int n_dimension_ {-1}; //!< Number of dimensions
|
||||
|
|
@ -348,7 +348,7 @@ public:
|
|||
//! \param[in] Pointer to bank sites
|
||||
//! \param[in] Number of bank sites
|
||||
//! \param[out] Whether any bank sites are outside the mesh
|
||||
xt::xtensor<double, 1> count_sites(
|
||||
tensor::Tensor<double> count_sites(
|
||||
const SourceSite* bank, int64_t length, bool* outside) const;
|
||||
|
||||
//! Get bin given mesh indices
|
||||
|
|
@ -419,8 +419,8 @@ public:
|
|||
//! Get a label for the mesh bin
|
||||
std::string bin_label(int bin) const override;
|
||||
|
||||
//! Get shape as xt::xtensor
|
||||
xt::xtensor<int, 1> get_x_shape() const;
|
||||
//! Get mesh dimensions as a tensor
|
||||
tensor::Tensor<int> get_shape_tensor() const;
|
||||
|
||||
double volume(int bin) const override
|
||||
{
|
||||
|
|
@ -515,7 +515,7 @@ public:
|
|||
//! \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(
|
||||
tensor::Tensor<double> count_sites(
|
||||
const SourceSite* bank, int64_t length, bool* outside) const;
|
||||
|
||||
//! Return the volume for a given mesh index
|
||||
|
|
@ -526,7 +526,7 @@ public:
|
|||
// Data members
|
||||
double volume_frac_; //!< Volume fraction of each mesh element
|
||||
double element_volume_; //!< Volume of each mesh element
|
||||
xt::xtensor<double, 1> width_; //!< Width of each mesh element
|
||||
tensor::Tensor<double> width_; //!< Width of each mesh element
|
||||
};
|
||||
|
||||
class RectilinearMesh : public StructuredMesh {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
|
|
@ -22,7 +22,7 @@ namespace openmc {
|
|||
|
||||
class Mgxs {
|
||||
private:
|
||||
xt::xtensor<double, 1> kTs; // temperature in eV (k * T)
|
||||
tensor::Tensor<double> kTs; // temperature in eV (k * T)
|
||||
AngleDistributionType
|
||||
scatter_format; // flag for if this is legendre, histogram, or tabular
|
||||
int num_groups; // number of energy groups
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public:
|
|||
// Temperature dependent cross section data
|
||||
vector<double> kTs_; //!< temperatures in eV (k*T)
|
||||
vector<EnergyGrid> grid_; //!< Energy grid at each temperature
|
||||
vector<xt::xtensor<double, 2>> xs_; //!< Cross sections at each temperature
|
||||
vector<tensor::Tensor<double>> xs_; //!< Cross sections at each temperature
|
||||
|
||||
// Multipole data
|
||||
unique_ptr<WindowedMultipole> multipole_;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "openmc/particle.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <hdf5.h>
|
||||
|
||||
#include <string>
|
||||
|
|
@ -62,14 +62,14 @@ public:
|
|||
int64_t index_; //!< 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_;
|
||||
tensor::Tensor<double> energy_;
|
||||
tensor::Tensor<double> coherent_;
|
||||
tensor::Tensor<double> incoherent_;
|
||||
tensor::Tensor<double> photoelectric_total_;
|
||||
tensor::Tensor<double> pair_production_total_;
|
||||
tensor::Tensor<double> pair_production_electron_;
|
||||
tensor::Tensor<double> pair_production_nuclear_;
|
||||
tensor::Tensor<double> heating_;
|
||||
|
||||
// Form factors
|
||||
Tabulated1D incoherent_form_factor_;
|
||||
|
|
@ -81,27 +81,27 @@ public:
|
|||
// stored separately to improve memory access pattern when calculating the
|
||||
// total cross section
|
||||
vector<ElectronSubshell> shells_;
|
||||
xt::xtensor<double, 2> cross_sections_;
|
||||
tensor::Tensor<double> cross_sections_;
|
||||
|
||||
// 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_;
|
||||
tensor::Tensor<double> profile_pdf_;
|
||||
tensor::Tensor<double> profile_cdf_;
|
||||
tensor::Tensor<double> binding_energy_;
|
||||
tensor::Tensor<double> electron_pdf_;
|
||||
|
||||
// Map subshells from Compton profile data obtained from Biggs et al,
|
||||
// "Hartree-Fock Compton profiles for the elements" to ENDF/B atomic
|
||||
// relaxation data
|
||||
xt::xtensor<int, 1> subshell_map_;
|
||||
tensor::Tensor<int> subshell_map_;
|
||||
|
||||
// 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_;
|
||||
tensor::Tensor<int> n_electrons_;
|
||||
tensor::Tensor<double> ionization_energy_;
|
||||
tensor::Tensor<double> stopping_power_radiative_;
|
||||
|
||||
// Bremsstrahlung scaled DCS
|
||||
xt::xtensor<double, 2> dcs_;
|
||||
tensor::Tensor<double> dcs_;
|
||||
|
||||
// Whether atomic relaxation data is present
|
||||
bool has_atomic_relaxation_ {false};
|
||||
|
|
@ -137,7 +137,7 @@ void free_memory_photon();
|
|||
|
||||
namespace data {
|
||||
|
||||
extern xt::xtensor<double, 1>
|
||||
extern tensor::Tensor<double>
|
||||
compton_profile_pz; //! Compton profile momentum grid
|
||||
|
||||
//! Photon interaction data for each element
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "openmc/tensor.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "xtensor/xarray.hpp"
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "openmc/cell.h"
|
||||
|
|
@ -90,7 +90,7 @@ const RGBColor BLACK {0, 0, 0};
|
|||
* visualized.
|
||||
*/
|
||||
|
||||
typedef xt::xtensor<RGBColor, 2> ImageData;
|
||||
typedef tensor::Tensor<RGBColor> ImageData;
|
||||
class PlottableInterface {
|
||||
public:
|
||||
PlottableInterface() = default;
|
||||
|
|
@ -154,7 +154,7 @@ struct IdData {
|
|||
void set_overlap(size_t y, size_t x);
|
||||
|
||||
// Members
|
||||
xt::xtensor<int32_t, 3> data_; //!< 2D array of cell & material ids
|
||||
tensor::Tensor<int32_t> data_; //!< 2D array of cell & material ids
|
||||
};
|
||||
|
||||
struct PropertyData {
|
||||
|
|
@ -166,7 +166,7 @@ struct PropertyData {
|
|||
void set_overlap(size_t y, size_t x);
|
||||
|
||||
// Members
|
||||
xt::xtensor<double, 3> data_; //!< 2D array of temperature & density data
|
||||
tensor::Tensor<double> data_; //!< 2D array of temperature & density data
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
|
|
|||
|
|
@ -178,10 +178,10 @@ protected:
|
|||
// Volumes for each tally and bin/score combination. This intermediate data
|
||||
// structure is used when tallying quantities that must be normalized by
|
||||
// volume (i.e., flux). The vector is index by tally index, while the inner 2D
|
||||
// xtensor is indexed by bin index and score index in a similar manner to the
|
||||
// tensor is indexed by bin index and score index in a similar manner to the
|
||||
// results tensor in the Tally class, though without the third dimension, as
|
||||
// SUM and SUM_SQ do not need to be tracked.
|
||||
vector<xt::xtensor<double, 2>> tally_volumes_;
|
||||
vector<tensor::Tensor<double>> tally_volumes_;
|
||||
|
||||
}; // class FlatSourceDomain
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#ifndef OPENMC_SCATTDATA_H
|
||||
#define OPENMC_SCATTDATA_H
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/vector.h"
|
||||
|
|
@ -26,23 +26,23 @@ public:
|
|||
|
||||
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,
|
||||
void base_init(int order, const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& 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, size_t order_dim,
|
||||
const vector<ScattData*>& those_scatts, const vector<double>& scalars,
|
||||
xt::xtensor<int, 1>& in_gmin, xt::xtensor<int, 1>& in_gmax,
|
||||
tensor::Tensor<int>& in_gmin, tensor::Tensor<int>& 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<int, 1> gmin; // minimum outgoing group
|
||||
xt::xtensor<int, 1> gmax; // maximum outgoing group
|
||||
xt::xtensor<double, 1> scattxs; // Isotropic Sigma_{s,g_{in}}
|
||||
tensor::Tensor<int> gmin; // minimum outgoing group
|
||||
tensor::Tensor<int> gmax; // maximum outgoing group
|
||||
tensor::Tensor<double> scattxs; // Isotropic Sigma_{s,g_{in}}
|
||||
|
||||
//! \brief Calculates the value of normalized f(mu).
|
||||
//!
|
||||
|
|
@ -72,8 +72,8 @@ public:
|
|||
//! @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,
|
||||
virtual void init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs) = 0;
|
||||
|
||||
//! \brief Combines the microscopic data.
|
||||
|
|
@ -96,7 +96,7 @@ public:
|
|||
//! @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;
|
||||
virtual tensor::Tensor<double> get_matrix(size_t max_order) = 0;
|
||||
|
||||
//! \brief Samples the outgoing energy from the ScattData info.
|
||||
//!
|
||||
|
|
@ -135,8 +135,8 @@ protected:
|
|||
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,
|
||||
void init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs) override;
|
||||
|
||||
void combine(const vector<ScattData*>& those_scatts,
|
||||
|
|
@ -153,7 +153,7 @@ public:
|
|||
|
||||
size_t get_order() override { return dist[0][0].size() - 1; };
|
||||
|
||||
xt::xtensor<double, 3> get_matrix(size_t max_order) override;
|
||||
tensor::Tensor<double> get_matrix(size_t max_order) override;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -164,13 +164,13 @@ public:
|
|||
class ScattDataHistogram : public ScattData {
|
||||
|
||||
protected:
|
||||
xt::xtensor<double, 1> mu; // Angle distribution mu bin boundaries
|
||||
tensor::Tensor<double> 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,
|
||||
void init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs) override;
|
||||
|
||||
void combine(const vector<ScattData*>& those_scatts,
|
||||
|
|
@ -183,7 +183,7 @@ public:
|
|||
|
||||
size_t get_order() override { return dist[0][0].size(); };
|
||||
|
||||
xt::xtensor<double, 3> get_matrix(size_t max_order) override;
|
||||
tensor::Tensor<double> get_matrix(size_t max_order) override;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -194,7 +194,7 @@ public:
|
|||
class ScattDataTabular : public ScattData {
|
||||
|
||||
protected:
|
||||
xt::xtensor<double, 1> mu; // Angle distribution mu grid points
|
||||
tensor::Tensor<double> mu; // Angle distribution mu grid points
|
||||
double dmu; // Quick storage of the mu spacing
|
||||
double_3dvec fmu; // The angular distribution function
|
||||
|
||||
|
|
@ -204,8 +204,8 @@ protected:
|
|||
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,
|
||||
void init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs) override;
|
||||
|
||||
void combine(const vector<ScattData*>& those_scatts,
|
||||
|
|
@ -218,7 +218,7 @@ public:
|
|||
|
||||
size_t get_order() override { return dist[0][0].size(); };
|
||||
|
||||
xt::xtensor<double, 3> get_matrix(size_t max_order) override;
|
||||
tensor::Tensor<double> get_matrix(size_t max_order) override;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define OPENMC_SECONDARY_CORRELATED_H
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/angle_energy.h"
|
||||
#include "openmc/distribution.h"
|
||||
|
|
@ -25,9 +25,9 @@ public:
|
|||
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
|
||||
tensor::Tensor<double> e_out; //!< Outgoing energies [eV]
|
||||
tensor::Tensor<double> p; //!< Probability density
|
||||
tensor::Tensor<double> c; //!< Cumulative distribution
|
||||
vector<unique_ptr<Tabular>> angle; //!< Angle distribution
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define OPENMC_SECONDARY_KALBACH_H
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/angle_energy.h"
|
||||
#include "openmc/constants.h"
|
||||
|
|
@ -37,11 +37,11 @@ private:
|
|||
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
|
||||
tensor::Tensor<double> e_out; //!< Outgoing energies [eV]
|
||||
tensor::Tensor<double> p; //!< Probability density
|
||||
tensor::Tensor<double> c; //!< Cumulative distribution
|
||||
tensor::Tensor<double> r; //!< Pre-compound fraction
|
||||
tensor::Tensor<double> a; //!< Parameterized function
|
||||
};
|
||||
|
||||
int n_region_; //!< Number of interpolation regions
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "openmc/secondary_correlated.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <hdf5.h>
|
||||
|
||||
namespace openmc {
|
||||
|
|
@ -83,7 +83,7 @@ public:
|
|||
|
||||
private:
|
||||
const vector<double>& energy_; //!< Energies at which cosines are tabulated
|
||||
xt::xtensor<double, 2> mu_out_; //!< Cosines for each incident energy
|
||||
tensor::Tensor<double> mu_out_; //!< Cosines for each incident energy
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -109,9 +109,9 @@ public:
|
|||
|
||||
private:
|
||||
const vector<double>& energy_; //!< Incident energies
|
||||
xt::xtensor<double, 2>
|
||||
tensor::Tensor<double>
|
||||
energy_out_; //!< Outgoing energies for each incident energy
|
||||
xt::xtensor<double, 3>
|
||||
tensor::Tensor<double>
|
||||
mu_out_; //!< Outgoing cosines for each incident/outgoing energy
|
||||
bool skewed_; //!< Whether outgoing energy distribution is skewed
|
||||
};
|
||||
|
|
@ -139,10 +139,10 @@ 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
|
||||
tensor::Tensor<double> e_out; //!< Outgoing energies
|
||||
tensor::Tensor<double> e_out_pdf; //!< Probability density function
|
||||
tensor::Tensor<double> e_out_cdf; //!< Cumulative distribution function
|
||||
tensor::Tensor<double> mu; //!< Equiprobable angles at each outgoing energy
|
||||
};
|
||||
|
||||
vector<double> energy_; //!< Incident energies
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@
|
|||
#include "openmc/tallies/trigger.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include "openmc/tensor.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "xtensor/xfixed.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
|
@ -55,7 +54,7 @@ public:
|
|||
|
||||
void set_nuclides(const vector<std::string>& nuclides);
|
||||
|
||||
const xt::xtensor<double, 3>& results() const { return results_; }
|
||||
const tensor::Tensor<double>& results() const { return results_; }
|
||||
|
||||
//! returns vector of indices corresponding to the tally this is called on
|
||||
const vector<int32_t>& filters() const { return filters_; }
|
||||
|
|
@ -125,7 +124,7 @@ public:
|
|||
int score_index(const std::string& score) const;
|
||||
|
||||
//! Tally results reshaped according to filter sizes
|
||||
xt::xarray<double> get_reshaped_data() const;
|
||||
tensor::Tensor<double> get_reshaped_data() const;
|
||||
|
||||
//! A string representing the i-th score on this tally
|
||||
std::string score_name(int score_idx) const;
|
||||
|
|
@ -160,7 +159,7 @@ public:
|
|||
//! combination of filters (e.g. specific cell, specific energy group, etc.)
|
||||
//! and the second dimension of the array is for scores (e.g. flux, total
|
||||
//! reaction rate, fission reaction rate, etc.)
|
||||
xt::xtensor<double, 3> results_;
|
||||
tensor::Tensor<double> results_;
|
||||
|
||||
//! True if this tally should be written to statepoint files
|
||||
bool writable_ {true};
|
||||
|
|
@ -220,8 +219,7 @@ extern vector<double> time_grid;
|
|||
|
||||
namespace simulation {
|
||||
//! Global tallies (such as k-effective estimators)
|
||||
extern xt::xtensor_fixed<double, xt::xshape<N_GLOBAL_TALLIES, 3>>
|
||||
global_tallies;
|
||||
extern tensor::StaticTensor2D<double, N_GLOBAL_TALLIES, 3> global_tallies;
|
||||
|
||||
//! Number of realizations for global tallies
|
||||
extern "C" int32_t n_realizations;
|
||||
|
|
@ -257,12 +255,6 @@ double distance_to_time_boundary(double time, double speed);
|
|||
//! 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();
|
||||
|
|
|
|||
1185
include/openmc/tensor.h
Normal file
1185
include/openmc/tensor.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/angle_energy.h"
|
||||
#include "openmc/endf.h"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef OPENMC_URR_H
|
||||
#define OPENMC_URR_H
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
|
|
@ -40,11 +40,11 @@ public:
|
|||
* below, obviously, values of the CDF are stored. For the xs_values
|
||||
* variable, the columns line up with the index of cdf_values.
|
||||
*/
|
||||
xt::xtensor<double, 2> cdf_values_; // Note: must be row major!
|
||||
xt::xtensor<XSSet, 2> xs_values_;
|
||||
tensor::Tensor<double> cdf_values_; // Note: must be row major!
|
||||
tensor::Tensor<XSSet> xs_values_;
|
||||
|
||||
// Number of points in the CDF
|
||||
auto n_cdf() const { return cdf_values_.shape()[1]; }
|
||||
auto n_cdf() const { return cdf_values_.shape(1); }
|
||||
|
||||
//! \brief Load the URR data from the provided HDF5 group
|
||||
explicit UrrData(hid_t group_id);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#include "openmc/tallies/trigger.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include "openmc/tensor.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -143,10 +143,10 @@ public:
|
|||
|
||||
const vector<double>& energy_bounds() const { return energy_bounds_; }
|
||||
|
||||
void set_bounds(const xt::xtensor<double, 2>& lower_ww_bounds,
|
||||
const xt::xtensor<double, 2>& upper_bounds);
|
||||
void set_bounds(const tensor::Tensor<double>& lower_ww_bounds,
|
||||
const tensor::Tensor<double>& upper_bounds);
|
||||
|
||||
void set_bounds(const xt::xtensor<double, 2>& lower_bounds, double ratio);
|
||||
void set_bounds(const tensor::Tensor<double>& lower_bounds, double ratio);
|
||||
|
||||
void set_bounds(
|
||||
span<const double> lower_bounds, span<const double> upper_bounds);
|
||||
|
|
@ -182,11 +182,11 @@ public:
|
|||
|
||||
const std::unique_ptr<Mesh>& mesh() const { return model::meshes[mesh_idx_]; }
|
||||
|
||||
const xt::xtensor<double, 2>& lower_ww_bounds() const { return lower_ww_; }
|
||||
xt::xtensor<double, 2>& lower_ww_bounds() { return lower_ww_; }
|
||||
const tensor::Tensor<double>& lower_ww_bounds() const { return lower_ww_; }
|
||||
tensor::Tensor<double>& lower_ww_bounds() { return lower_ww_; }
|
||||
|
||||
const xt::xtensor<double, 2>& upper_ww_bounds() const { return upper_ww_; }
|
||||
xt::xtensor<double, 2>& upper_ww_bounds() { return upper_ww_; }
|
||||
const tensor::Tensor<double>& upper_ww_bounds() const { return upper_ww_; }
|
||||
tensor::Tensor<double>& upper_ww_bounds() { return upper_ww_; }
|
||||
|
||||
ParticleType particle_type() const { return particle_type_; }
|
||||
|
||||
|
|
@ -197,9 +197,9 @@ private:
|
|||
int64_t index_; //!< Index into weight windows vector
|
||||
ParticleType particle_type_; //!< Particle type to apply weight windows to
|
||||
vector<double> energy_bounds_; //!< Energy boundaries [eV]
|
||||
xt::xtensor<double, 2> lower_ww_; //!< Lower weight window bounds (shape:
|
||||
tensor::Tensor<double> lower_ww_; //!< Lower weight window bounds (shape:
|
||||
//!< energy_bins, mesh_bins (k, j, i))
|
||||
xt::xtensor<double, 2>
|
||||
tensor::Tensor<double>
|
||||
upper_ww_; //!< Upper weight window bounds (shape: energy_bins, mesh_bins)
|
||||
double survival_ratio_ {3.0}; //!< Survival weight ratio
|
||||
double max_lb_ratio_ {1.0}; //!< Maximum lower bound to particle weight ratio
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define OPENMC_WMP_H
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include <complex>
|
||||
#include <string>
|
||||
|
|
@ -78,9 +78,9 @@ public:
|
|||
int fit_order_; //!< Order of the fit
|
||||
bool fissionable_; //!< Is the nuclide fissionable?
|
||||
vector<WindowInfo> window_info_; // Information about a window
|
||||
xt::xtensor<double, 3>
|
||||
tensor::Tensor<double>
|
||||
curvefit_; // Curve fit coefficients (window, poly order, reaction)
|
||||
xt::xtensor<std::complex<double>, 2> data_; //!< Poles and residues
|
||||
tensor::Tensor<std::complex<double>> data_; //!< Poles and residues
|
||||
|
||||
// Constant data
|
||||
static constexpr int MAX_POLY_COEFFICIENTS =
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@
|
|||
#include <sstream> // for stringstream
|
||||
#include <string>
|
||||
|
||||
#include "openmc/tensor.h"
|
||||
#include "pugixml.hpp"
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xarray.hpp"
|
||||
|
||||
#include "openmc/position.h"
|
||||
#include "openmc/vector.h"
|
||||
|
|
@ -42,12 +41,11 @@ vector<T> get_node_array(
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
xt::xarray<T> get_node_xarray(
|
||||
tensor::Tensor<T> get_node_tensor(
|
||||
pugi::xml_node node, const char* name, bool lowercase = false)
|
||||
{
|
||||
vector<T> v = get_node_array<T>(node, name, lowercase);
|
||||
vector<std::size_t> shape = {v.size()};
|
||||
return xt::adapt(v, shape);
|
||||
return tensor::Tensor<T>(v.data(), v.size());
|
||||
}
|
||||
|
||||
std::vector<Position> get_node_position_array(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#ifndef OPENMC_XSDATA_H
|
||||
#define OPENMC_XSDATA_H
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/memory.h"
|
||||
|
|
@ -69,26 +69,26 @@ private:
|
|||
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;
|
||||
tensor::Tensor<double> total;
|
||||
tensor::Tensor<double> absorption;
|
||||
tensor::Tensor<double> nu_fission;
|
||||
tensor::Tensor<double> prompt_nu_fission;
|
||||
tensor::Tensor<double> kappa_fission;
|
||||
tensor::Tensor<double> fission;
|
||||
tensor::Tensor<double> inverse_velocity;
|
||||
|
||||
// decay_rate has the following dimensions:
|
||||
// [angle][delayed group]
|
||||
xt::xtensor<double, 2> decay_rate;
|
||||
tensor::Tensor<double> decay_rate;
|
||||
// delayed_nu_fission has the following dimensions:
|
||||
// [angle][delayed group][incoming group]
|
||||
xt::xtensor<double, 3> delayed_nu_fission;
|
||||
tensor::Tensor<double> delayed_nu_fission;
|
||||
// chi_prompt has the following dimensions:
|
||||
// [angle][incoming group][outgoing group]
|
||||
xt::xtensor<double, 3> chi_prompt;
|
||||
tensor::Tensor<double> chi_prompt;
|
||||
// chi_delayed has the following dimensions:
|
||||
// [angle][incoming group][outgoing group][delayed group]
|
||||
xt::xtensor<double, 4> chi_delayed;
|
||||
tensor::Tensor<double> chi_delayed;
|
||||
// scatter has the following dimensions: [angle]
|
||||
vector<std::shared_ptr<ScattData>> scatter;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "openmc/vector.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "openmc/search.h"
|
||||
#include "openmc/settings.h"
|
||||
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -16,8 +16,8 @@ namespace openmc {
|
|||
|
||||
namespace data {
|
||||
|
||||
xt::xtensor<double, 1> ttb_e_grid;
|
||||
xt::xtensor<double, 1> ttb_k_grid;
|
||||
tensor::Tensor<double> ttb_e_grid;
|
||||
tensor::Tensor<double> ttb_k_grid;
|
||||
vector<Bremsstrahlung> ttb;
|
||||
|
||||
} // namespace data
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/bank.h"
|
||||
#include "openmc/capi.h"
|
||||
|
|
@ -36,7 +36,7 @@ double spectral;
|
|||
|
||||
int nx, ny, nz, ng;
|
||||
|
||||
xt::xtensor<int, 2> indexmap;
|
||||
tensor::Tensor<int> indexmap;
|
||||
|
||||
int use_all_threads;
|
||||
|
||||
|
|
@ -79,15 +79,14 @@ int get_cmfd_energy_bin(const double E)
|
|||
// COUNT_BANK_SITES bins fission sites according to CMFD mesh and energy
|
||||
//==============================================================================
|
||||
|
||||
xt::xtensor<double, 1> count_bank_sites(
|
||||
xt::xtensor<int, 1>& bins, bool* outside)
|
||||
tensor::Tensor<double> count_bank_sites(
|
||||
tensor::Tensor<int>& bins, bool* outside)
|
||||
{
|
||||
// Determine shape of array for counts
|
||||
std::size_t cnt_size = cmfd::nx * cmfd::ny * cmfd::nz * cmfd::ng;
|
||||
vector<std::size_t> cnt_shape = {cnt_size};
|
||||
|
||||
// Create array of zeros
|
||||
xt::xarray<double> cnt {cnt_shape, 0.0};
|
||||
tensor::Tensor<double> cnt = tensor::zeros<double>({cnt_size});
|
||||
bool outside_ = false;
|
||||
|
||||
auto bank_size = simulation::source_bank.size();
|
||||
|
|
@ -113,29 +112,22 @@ xt::xtensor<double, 1> count_bank_sites(
|
|||
bins[i] = mesh_bin * cmfd::ng + energy_bin;
|
||||
}
|
||||
|
||||
// Create copy of count data. Since ownership will be acquired by xtensor,
|
||||
// std::allocator must be used to avoid Valgrind mismatched free() / delete
|
||||
// warnings.
|
||||
int total = cnt.size();
|
||||
double* cnt_reduced = std::allocator<double> {}.allocate(total);
|
||||
tensor::Tensor<double> counts = tensor::zeros<double>({cnt_size});
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
// collect values from all processors
|
||||
MPI_Reduce(
|
||||
cnt.data(), cnt_reduced, total, MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm);
|
||||
cnt.data(), counts.data(), total, MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm);
|
||||
|
||||
// Check if there were sites outside the mesh for any processor
|
||||
MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm);
|
||||
|
||||
#else
|
||||
std::copy(cnt.data(), cnt.data() + total, cnt_reduced);
|
||||
std::copy(cnt.data(), cnt.data() + total, counts.data());
|
||||
*outside = outside_;
|
||||
#endif
|
||||
|
||||
// Adapt reduced values in array back into an xarray
|
||||
auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), cnt_shape);
|
||||
xt::xarray<double> counts = arr;
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
|
@ -151,19 +143,19 @@ extern "C" void openmc_cmfd_reweight(
|
|||
std::size_t src_size = cmfd::nx * cmfd::ny * cmfd::nz * cmfd::ng;
|
||||
|
||||
// count bank sites for CMFD mesh, store bins in bank_bins for reweighting
|
||||
xt::xtensor<int, 1> bank_bins({bank_size}, 0);
|
||||
tensor::Tensor<int> bank_bins = tensor::zeros<int>({bank_size});
|
||||
bool sites_outside;
|
||||
xt::xtensor<double, 1> sourcecounts =
|
||||
tensor::Tensor<double> sourcecounts =
|
||||
count_bank_sites(bank_bins, &sites_outside);
|
||||
|
||||
// Compute CMFD weightfactors
|
||||
xt::xtensor<double, 1> weightfactors = xt::xtensor<double, 1>({src_size}, 1.);
|
||||
tensor::Tensor<double> weightfactors = tensor::ones<double>({src_size});
|
||||
if (mpi::master) {
|
||||
if (sites_outside) {
|
||||
fatal_error("Source sites outside of the CMFD mesh");
|
||||
}
|
||||
|
||||
double norm = xt::sum(sourcecounts)() / cmfd::norm;
|
||||
double norm = sourcecounts.sum() / cmfd::norm;
|
||||
for (int i = 0; i < src_size; i++) {
|
||||
if (sourcecounts[i] > 0 && cmfd_src[i] > 0) {
|
||||
weightfactors[i] = cmfd_src[i] * norm / sourcecounts[i];
|
||||
|
|
@ -561,7 +553,7 @@ void free_memory_cmfd()
|
|||
cmfd::indices.clear();
|
||||
cmfd::egrid.clear();
|
||||
|
||||
// Resize xtensors to be empty
|
||||
// Resize tensors to be empty
|
||||
cmfd::indexmap.resize({0});
|
||||
|
||||
// Set pointers to null
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ void read_ce_cross_sections(const vector<vector<double>>& nuc_temps,
|
|||
if (settings::photon_transport &&
|
||||
settings::electron_treatment == ElectronTreatment::TTB) {
|
||||
// Take logarithm of energies since they are log-log interpolated
|
||||
data::ttb_e_grid = xt::log(data::ttb_e_grid);
|
||||
data::ttb_e_grid = tensor::log(data::ttb_e_grid);
|
||||
}
|
||||
|
||||
// Show minimum/maximum temperature
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
#include <cmath> // for abs, copysign
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/endf.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
|
|
@ -30,7 +29,7 @@ AngleDistribution::AngleDistribution(hid_t group)
|
|||
hid_t dset = open_dataset(group, "mu");
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
xt::xarray<double> temp;
|
||||
tensor::Tensor<double> temp;
|
||||
read_dataset(dset, temp);
|
||||
close_dataset(dset);
|
||||
|
||||
|
|
@ -41,13 +40,13 @@ AngleDistribution::AngleDistribution(hid_t group)
|
|||
if (i < n_energy - 1) {
|
||||
n = offsets[i + 1] - j;
|
||||
} else {
|
||||
n = temp.shape()[1] - j;
|
||||
n = temp.shape(1) - j;
|
||||
}
|
||||
|
||||
// Create and initialize tabular distribution
|
||||
auto xs = xt::view(temp, 0, xt::range(j, j + n));
|
||||
auto ps = xt::view(temp, 1, xt::range(j, j + n));
|
||||
auto cs = xt::view(temp, 2, xt::range(j, j + n));
|
||||
tensor::View<double> xs = temp.slice(0, tensor::range(j, j + n));
|
||||
tensor::View<double> ps = temp.slice(1, tensor::range(j, j + n));
|
||||
tensor::View<double> cs = temp.slice(2, tensor::range(j, j + n));
|
||||
vector<double> x {xs.begin(), xs.end()};
|
||||
vector<double> p {ps.begin(), ps.end()};
|
||||
vector<double> c {cs.begin(), cs.end()};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/endf.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
|
|
@ -60,11 +60,11 @@ ContinuousTabular::ContinuousTabular(hid_t group)
|
|||
hid_t dset = open_dataset(group, "energy");
|
||||
|
||||
// Get interpolation parameters
|
||||
xt::xarray<int> temp;
|
||||
tensor::Tensor<int> temp;
|
||||
read_attribute(dset, "interpolation", temp);
|
||||
|
||||
auto temp_b = xt::view(temp, 0); // view of breakpoints
|
||||
auto temp_i = xt::view(temp, 1); // view of interpolation parameters
|
||||
tensor::View<int> temp_b = temp.slice(0); // breakpoints
|
||||
tensor::View<int> temp_i = temp.slice(1); // interpolation parameters
|
||||
|
||||
std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_));
|
||||
for (const auto i : temp_i)
|
||||
|
|
@ -85,7 +85,7 @@ ContinuousTabular::ContinuousTabular(hid_t group)
|
|||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
||||
xt::xarray<double> eout;
|
||||
tensor::Tensor<double> eout;
|
||||
read_dataset(dset, eout);
|
||||
close_dataset(dset);
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ ContinuousTabular::ContinuousTabular(hid_t group)
|
|||
if (i < n_energy - 1) {
|
||||
n = offsets[i + 1] - j;
|
||||
} else {
|
||||
n = eout.shape()[1] - j;
|
||||
n = eout.shape(1) - j;
|
||||
}
|
||||
|
||||
// Assign interpolation scheme and number of discrete lines
|
||||
|
|
@ -105,15 +105,15 @@ ContinuousTabular::ContinuousTabular(hid_t group)
|
|||
d.n_discrete = n_discrete[i];
|
||||
|
||||
// Copy data
|
||||
d.e_out = xt::view(eout, 0, xt::range(j, j + n));
|
||||
d.p = xt::view(eout, 1, xt::range(j, j + n));
|
||||
d.e_out = eout.slice(0, tensor::range(j, j + n));
|
||||
d.p = eout.slice(1, tensor::range(j, j + n));
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
// time, we can remove the CDF values from the HDF5 library and
|
||||
// reconstruct them using the PDF
|
||||
if (true) {
|
||||
d.c = xt::view(eout, 2, xt::range(j, j + n));
|
||||
d.c = eout.slice(2, tensor::range(j, j + n));
|
||||
} else {
|
||||
// Calculate cumulative distribution function -- discrete portion
|
||||
for (int k = 0; k < d.n_discrete; ++k) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
#include "openmc/eigenvalue.h"
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/bank.h"
|
||||
|
|
@ -39,7 +36,7 @@ namespace simulation {
|
|||
double keff_generation;
|
||||
array<double, 2> k_sum;
|
||||
vector<double> entropy;
|
||||
xt::xtensor<double, 1> source_frac;
|
||||
tensor::Tensor<double> source_frac;
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
|
|
@ -452,7 +449,7 @@ int openmc_get_keff(double* k_combined)
|
|||
const auto& gt = simulation::global_tallies;
|
||||
|
||||
array<double, 3> kv {};
|
||||
xt::xtensor<double, 2> cov = xt::zeros<double>({3, 3});
|
||||
tensor::Tensor<double> cov = tensor::zeros<double>({3, 3});
|
||||
kv[0] = gt(GlobalTally::K_COLLISION, TallyResult::SUM) / n;
|
||||
kv[1] = gt(GlobalTally::K_ABSORPTION, TallyResult::SUM) / n;
|
||||
kv[2] = gt(GlobalTally::K_TRACKLENGTH, TallyResult::SUM) / n;
|
||||
|
|
@ -591,7 +588,7 @@ void shannon_entropy()
|
|||
{
|
||||
// Get source weight in each mesh bin
|
||||
bool sites_outside;
|
||||
xt::xtensor<double, 1> p =
|
||||
tensor::Tensor<double> p =
|
||||
simulation::entropy_mesh->count_sites(simulation::fission_bank.data(),
|
||||
simulation::fission_bank.size(), &sites_outside);
|
||||
|
||||
|
|
@ -603,7 +600,7 @@ void shannon_entropy()
|
|||
|
||||
if (mpi::master) {
|
||||
// Normalize to total weight of bank sites
|
||||
p /= xt::sum(p);
|
||||
p /= p.sum();
|
||||
|
||||
// Sum values to obtain Shannon entropy
|
||||
double H = 0.0;
|
||||
|
|
@ -627,7 +624,7 @@ void ufs_count_sites()
|
|||
|
||||
std::size_t n = simulation::ufs_mesh->n_bins();
|
||||
double vol_frac = simulation::ufs_mesh->volume_frac_;
|
||||
simulation::source_frac = xt::xtensor<double, 1>({n}, vol_frac);
|
||||
simulation::source_frac = tensor::Tensor<double>({n}, vol_frac);
|
||||
|
||||
} else {
|
||||
// count number of source sites in each ufs mesh cell
|
||||
|
|
@ -649,7 +646,7 @@ void ufs_count_sites()
|
|||
#endif
|
||||
|
||||
// Normalize to total weight to get fraction of source in each cell
|
||||
double total = xt::sum(simulation::source_frac)();
|
||||
double total = simulation::source_frac.sum();
|
||||
simulation::source_frac /= total;
|
||||
|
||||
// Since the total starting weight is not equal to n_particles, we need to
|
||||
|
|
|
|||
15
src/endf.cpp
15
src/endf.cpp
|
|
@ -5,8 +5,7 @@
|
|||
#include <iterator> // for back_inserter
|
||||
#include <stdexcept> // for runtime_error
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/constants.h"
|
||||
|
|
@ -153,11 +152,11 @@ Tabulated1D::Tabulated1D(hid_t dset)
|
|||
for (const auto i : int_temp)
|
||||
int_.push_back(int2interp(i));
|
||||
|
||||
xt::xarray<double> arr;
|
||||
tensor::Tensor<double> arr;
|
||||
read_dataset(dset, arr);
|
||||
|
||||
auto xs = xt::view(arr, 0);
|
||||
auto ys = xt::view(arr, 1);
|
||||
tensor::View<double> xs = arr.slice(0);
|
||||
tensor::View<double> ys = arr.slice(1);
|
||||
|
||||
std::copy(xs.begin(), xs.end(), std::back_inserter(x_));
|
||||
std::copy(ys.begin(), ys.end(), std::back_inserter(y_));
|
||||
|
|
@ -229,12 +228,12 @@ double Tabulated1D::operator()(double x) const
|
|||
CoherentElasticXS::CoherentElasticXS(hid_t dset)
|
||||
{
|
||||
// Read 2D array from dataset
|
||||
xt::xarray<double> arr;
|
||||
tensor::Tensor<double> arr;
|
||||
read_dataset(dset, arr);
|
||||
|
||||
// Get views for Bragg edges and structure factors
|
||||
auto E = xt::view(arr, 0);
|
||||
auto s = xt::view(arr, 1);
|
||||
tensor::View<double> E = arr.slice(0);
|
||||
tensor::View<double> s = arr.slice(1);
|
||||
|
||||
// Copy Bragg edges and partial sums of structure factors
|
||||
std::copy(E.begin(), E.end(), std::back_inserter(bragg_edges_));
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "openmc/volume_calc.h"
|
||||
#include "openmc/weight_windows.h"
|
||||
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ int openmc_reset()
|
|||
|
||||
// Reset global tallies
|
||||
simulation::n_realizations = 0;
|
||||
xt::view(simulation::global_tallies, xt::all()) = 0.0;
|
||||
simulation::global_tallies.fill(0.0);
|
||||
|
||||
simulation::k_col_abs = 0.0;
|
||||
simulation::k_col_tra = 0.0;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "hdf5.h"
|
||||
|
|
@ -466,22 +465,19 @@ void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
|
|||
}
|
||||
|
||||
template<>
|
||||
void read_dataset(hid_t dset, xt::xarray<std::complex<double>>& arr, bool indep)
|
||||
void read_dataset(
|
||||
hid_t dset, tensor::Tensor<std::complex<double>>& tensor, bool indep)
|
||||
{
|
||||
// Get shape of dataset
|
||||
vector<hsize_t> shape = object_shape(dset);
|
||||
|
||||
// Allocate new array to read data into
|
||||
std::size_t size = 1;
|
||||
for (const auto x : shape)
|
||||
size *= x;
|
||||
vector<std::complex<double>> buffer(size);
|
||||
// Resize tensor and read data directly
|
||||
vector<size_t> tshape(shape.begin(), shape.end());
|
||||
tensor.resize(tshape);
|
||||
|
||||
// Read data from attribute
|
||||
read_complex(dset, nullptr, buffer.data(), indep);
|
||||
|
||||
// Adapt into xarray
|
||||
arr = xt::adapt(buffer, shape);
|
||||
// Read data from dataset
|
||||
read_complex(dset, nullptr,
|
||||
reinterpret_cast<std::complex<double>*>(tensor.data()), indep);
|
||||
}
|
||||
|
||||
void read_double(hid_t obj_id, const char* name, double* buffer, bool indep)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@
|
|||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xoperation.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/container_util.h"
|
||||
|
|
@ -216,7 +214,7 @@ Material::Material(pugi::xml_node node)
|
|||
// allocate arrays in Material object
|
||||
auto n = names.size();
|
||||
nuclide_.reserve(n);
|
||||
atom_density_ = xt::empty<double>({n});
|
||||
atom_density_ = tensor::Tensor<double>({n});
|
||||
if (settings::photon_transport)
|
||||
element_.reserve(n);
|
||||
|
||||
|
|
@ -290,14 +288,14 @@ Material::Material(pugi::xml_node node)
|
|||
|
||||
// Check to make sure either all atom percents or all weight percents are
|
||||
// given
|
||||
if (!(xt::all(atom_density_ >= 0.0) || xt::all(atom_density_ <= 0.0))) {
|
||||
if (!((atom_density_ >= 0.0).all() || (atom_density_ <= 0.0).all())) {
|
||||
fatal_error(
|
||||
"Cannot mix atom and weight percents in material " + std::to_string(id_));
|
||||
}
|
||||
|
||||
// Determine density if it is a sum value
|
||||
if (sum_density)
|
||||
density_ = xt::sum(atom_density_)();
|
||||
density_ = atom_density_.sum();
|
||||
|
||||
if (check_for_node(node, "temperature")) {
|
||||
temperature_ = std::stod(get_node_value(node, "temperature"));
|
||||
|
|
@ -435,7 +433,7 @@ void Material::normalize_density()
|
|||
// determine normalized atom percents. if given atom percents, this is
|
||||
// straightforward. if given weight percents, the value is w/awr and is
|
||||
// divided by sum(w/awr)
|
||||
atom_density_ /= xt::sum(atom_density_)();
|
||||
atom_density_ /= atom_density_.sum();
|
||||
|
||||
// Change density in g/cm^3 to atom/b-cm. Since all values are now in
|
||||
// atom percent, the sum needs to be re-evaluated as 1/sum(x*awr)
|
||||
|
|
@ -641,14 +639,14 @@ void Material::init_bremsstrahlung()
|
|||
bool positron = (particle == 1);
|
||||
|
||||
// Allocate arrays for TTB data
|
||||
ttb->pdf = xt::zeros<double>({n_e, n_e});
|
||||
ttb->cdf = xt::zeros<double>({n_e, n_e});
|
||||
ttb->yield = xt::zeros<double>({n_e});
|
||||
ttb->pdf = tensor::zeros<double>({n_e, n_e});
|
||||
ttb->cdf = tensor::zeros<double>({n_e, n_e});
|
||||
ttb->yield = tensor::zeros<double>({n_e});
|
||||
|
||||
// Allocate temporary arrays
|
||||
xt::xtensor<double, 1> stopping_power_collision({n_e}, 0.0);
|
||||
xt::xtensor<double, 1> stopping_power_radiative({n_e}, 0.0);
|
||||
xt::xtensor<double, 2> dcs({n_e, n_k}, 0.0);
|
||||
auto stopping_power_collision = tensor::zeros<double>({n_e});
|
||||
auto stopping_power_radiative = tensor::zeros<double>({n_e});
|
||||
auto dcs = tensor::zeros<double>({n_e, n_k});
|
||||
|
||||
double Z_eq_sq = 0.0;
|
||||
double sum_density = 0.0;
|
||||
|
|
@ -698,18 +696,18 @@ void Material::init_bremsstrahlung()
|
|||
1.0595e-3 * std::pow(t, 5) + 7.0568e-5 * std::pow(t, 6) -
|
||||
1.808e-6 * std::pow(t, 7));
|
||||
stopping_power_radiative(i) *= r;
|
||||
auto dcs_i = xt::view(dcs, i, xt::all());
|
||||
tensor::View<double> dcs_i = dcs.slice(i);
|
||||
dcs_i *= r;
|
||||
}
|
||||
}
|
||||
|
||||
// Total material stopping power
|
||||
xt::xtensor<double, 1> stopping_power =
|
||||
tensor::Tensor<double> stopping_power =
|
||||
stopping_power_collision + stopping_power_radiative;
|
||||
|
||||
// Loop over photon energies
|
||||
xt::xtensor<double, 1> f({n_e}, 0.0);
|
||||
xt::xtensor<double, 1> z({n_e}, 0.0);
|
||||
auto f = tensor::zeros<double>({n_e});
|
||||
auto z = tensor::zeros<double>({n_e});
|
||||
for (int i = 0; i < n_e - 1; ++i) {
|
||||
double w = data::ttb_e_grid(i);
|
||||
|
||||
|
|
@ -797,7 +795,8 @@ void Material::init_bremsstrahlung()
|
|||
}
|
||||
|
||||
// Use logarithm of number yield since it is log-log interpolated
|
||||
ttb->yield = xt::where(ttb->yield > 0.0, xt::log(ttb->yield), -500.0);
|
||||
ttb->yield =
|
||||
tensor::where(ttb->yield > 0.0, tensor::log(ttb->yield), -500.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -979,7 +978,7 @@ void Material::set_density(double density, const std::string& units)
|
|||
density_ = density;
|
||||
|
||||
// Determine normalized atom percents
|
||||
double sum_percent = xt::sum(atom_density_)();
|
||||
double sum_percent = atom_density_.sum();
|
||||
atom_density_ /= sum_percent;
|
||||
|
||||
// Recalculate nuclide atom densities based on given density
|
||||
|
|
@ -1020,7 +1019,7 @@ void Material::set_densities(
|
|||
|
||||
if (n != nuclide_.size()) {
|
||||
nuclide_.resize(n);
|
||||
atom_density_ = xt::zeros<double>({n});
|
||||
atom_density_ = tensor::zeros<double>({n});
|
||||
if (settings::photon_transport)
|
||||
element_.resize(n);
|
||||
}
|
||||
|
|
@ -1181,8 +1180,8 @@ void Material::add_nuclide(const std::string& name, double density)
|
|||
auto n = nuclide_.size();
|
||||
|
||||
// Create copy of atom_density_ array with one extra entry
|
||||
xt::xtensor<double, 1> atom_density = xt::zeros<double>({n});
|
||||
xt::view(atom_density, xt::range(0, n - 1)) = atom_density_;
|
||||
tensor::Tensor<double> atom_density = tensor::zeros<double>({n});
|
||||
atom_density.slice(tensor::range(0, n - 1)) = atom_density_;
|
||||
atom_density(n - 1) = density;
|
||||
atom_density_ = atom_density;
|
||||
|
||||
|
|
|
|||
131
src/mesh.cpp
131
src/mesh.cpp
|
|
@ -6,6 +6,7 @@
|
|||
#define _USE_MATH_DEFINES // to make M_PI declared in Intel and MSVC compilers
|
||||
#include <cmath> // for ceil
|
||||
#include <cstddef> // for size_t
|
||||
#include <numeric> // for accumulate
|
||||
#include <string>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
@ -16,13 +17,7 @@
|
|||
#include "mpi.h"
|
||||
#endif
|
||||
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xeval.hpp"
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "xtensor/xsort.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h> // for fmt
|
||||
|
||||
#include "openmc/capi.h"
|
||||
|
|
@ -772,11 +767,9 @@ std::string StructuredMesh::bin_label(int bin) const
|
|||
}
|
||||
}
|
||||
|
||||
xt::xtensor<int, 1> StructuredMesh::get_x_shape() const
|
||||
tensor::Tensor<int> StructuredMesh::get_shape_tensor() const
|
||||
{
|
||||
// because method is const, shape_ is const as well and can't be adapted
|
||||
auto tmp_shape = shape_;
|
||||
return xt::adapt(tmp_shape, {n_dimension_});
|
||||
return tensor::Tensor<int>(shape_.data(), static_cast<size_t>(n_dimension_));
|
||||
}
|
||||
|
||||
Position StructuredMesh::sample_element(
|
||||
|
|
@ -961,10 +954,11 @@ void UnstructuredMesh::to_hdf5_inner(hid_t mesh_group) const
|
|||
write_dataset(mesh_group, "length_multiplier", length_multiplier_);
|
||||
|
||||
// write vertex coordinates
|
||||
xt::xtensor<double, 2> vertices({static_cast<size_t>(this->n_vertices()), 3});
|
||||
tensor::Tensor<double> vertices(
|
||||
{static_cast<size_t>(this->n_vertices()), static_cast<size_t>(3)});
|
||||
for (int i = 0; i < this->n_vertices(); i++) {
|
||||
auto v = this->vertex(i);
|
||||
xt::view(vertices, i, xt::all()) = xt::xarray<double>({v.x, v.y, v.z});
|
||||
vertices.slice(i) = {v.x, v.y, v.z};
|
||||
}
|
||||
write_dataset(mesh_group, "vertices", vertices);
|
||||
|
||||
|
|
@ -972,8 +966,10 @@ void UnstructuredMesh::to_hdf5_inner(hid_t mesh_group) const
|
|||
|
||||
// write element types and connectivity
|
||||
vector<double> volumes;
|
||||
xt::xtensor<int, 2> connectivity({static_cast<size_t>(this->n_bins()), 8});
|
||||
xt::xtensor<int, 2> elem_types({static_cast<size_t>(this->n_bins()), 1});
|
||||
tensor::Tensor<int> connectivity(
|
||||
{static_cast<size_t>(this->n_bins()), static_cast<size_t>(8)});
|
||||
tensor::Tensor<int> elem_types(
|
||||
{static_cast<size_t>(this->n_bins()), static_cast<size_t>(1)});
|
||||
for (int i = 0; i < this->n_bins(); i++) {
|
||||
auto conn = this->connectivity(i);
|
||||
|
||||
|
|
@ -981,21 +977,18 @@ void UnstructuredMesh::to_hdf5_inner(hid_t mesh_group) const
|
|||
|
||||
// write linear tet element
|
||||
if (conn.size() == 4) {
|
||||
xt::view(elem_types, i, xt::all()) =
|
||||
static_cast<int>(ElementType::LINEAR_TET);
|
||||
xt::view(connectivity, i, xt::all()) =
|
||||
xt::xarray<int>({conn[0], conn[1], conn[2], conn[3], -1, -1, -1, -1});
|
||||
elem_types.slice(i) = static_cast<int>(ElementType::LINEAR_TET);
|
||||
connectivity.slice(i) = {
|
||||
conn[0], conn[1], conn[2], conn[3], -1, -1, -1, -1};
|
||||
// write linear hex element
|
||||
} else if (conn.size() == 8) {
|
||||
xt::view(elem_types, i, xt::all()) =
|
||||
static_cast<int>(ElementType::LINEAR_HEX);
|
||||
xt::view(connectivity, i, xt::all()) = xt::xarray<int>({conn[0], conn[1],
|
||||
conn[2], conn[3], conn[4], conn[5], conn[6], conn[7]});
|
||||
elem_types.slice(i) = static_cast<int>(ElementType::LINEAR_HEX);
|
||||
connectivity.slice(i) = {
|
||||
conn[0], conn[1], conn[2], conn[3], conn[4], conn[5], conn[6], conn[7]};
|
||||
} else {
|
||||
num_elem_skipped++;
|
||||
xt::view(elem_types, i, xt::all()) =
|
||||
static_cast<int>(ElementType::UNSUPPORTED);
|
||||
xt::view(connectivity, i, xt::all()) = -1;
|
||||
elem_types.slice(i) = static_cast<int>(ElementType::UNSUPPORTED);
|
||||
connectivity.slice(i) = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1096,7 +1089,7 @@ int StructuredMesh::n_surface_bins() const
|
|||
return 4 * n_dimension_ * n_bins();
|
||||
}
|
||||
|
||||
xt::xtensor<double, 1> StructuredMesh::count_sites(
|
||||
tensor::Tensor<double> StructuredMesh::count_sites(
|
||||
const SourceSite* bank, int64_t length, bool* outside) const
|
||||
{
|
||||
// Determine shape of array for counts
|
||||
|
|
@ -1104,7 +1097,7 @@ xt::xtensor<double, 1> StructuredMesh::count_sites(
|
|||
vector<std::size_t> shape = {m};
|
||||
|
||||
// Create array of zeros
|
||||
xt::xarray<double> cnt {shape, 0.0};
|
||||
auto cnt = tensor::zeros<double>(shape);
|
||||
bool outside_ = false;
|
||||
|
||||
for (int64_t i = 0; i < length; i++) {
|
||||
|
|
@ -1123,31 +1116,25 @@ xt::xtensor<double, 1> StructuredMesh::count_sites(
|
|||
cnt(mesh_bin) += site.wgt;
|
||||
}
|
||||
|
||||
// Create copy of count data. Since ownership will be acquired by xtensor,
|
||||
// std::allocator must be used to avoid Valgrind mismatched free() / delete
|
||||
// warnings.
|
||||
// Create reduced count data
|
||||
auto counts = tensor::zeros<double>(shape);
|
||||
int total = cnt.size();
|
||||
double* cnt_reduced = std::allocator<double> {}.allocate(total);
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
// collect values from all processors
|
||||
MPI_Reduce(
|
||||
cnt.data(), cnt_reduced, total, MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm);
|
||||
cnt.data(), counts.data(), total, MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm);
|
||||
|
||||
// Check if there were sites outside the mesh for any processor
|
||||
if (outside) {
|
||||
MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm);
|
||||
}
|
||||
#else
|
||||
std::copy(cnt.data(), cnt.data() + total, cnt_reduced);
|
||||
std::copy(cnt.data(), cnt.data() + total, counts.data());
|
||||
if (outside)
|
||||
*outside = outside_;
|
||||
#endif
|
||||
|
||||
// Adapt reduced values in array back into an xarray
|
||||
auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), shape);
|
||||
xt::xarray<double> counts = arr;
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
|
@ -1340,10 +1327,10 @@ void StructuredMesh::surface_bins_crossed(
|
|||
|
||||
int RegularMesh::set_grid()
|
||||
{
|
||||
auto shape = xt::adapt(shape_, {n_dimension_});
|
||||
tensor::Tensor<int> shape(shape_.data(), static_cast<size_t>(n_dimension_));
|
||||
|
||||
// Check that dimensions are all greater than zero
|
||||
if (xt::any(shape <= 0)) {
|
||||
if ((shape <= 0).any()) {
|
||||
set_errmsg("All entries for a regular mesh dimensions "
|
||||
"must be positive.");
|
||||
return OPENMC_E_INVALID_ARGUMENT;
|
||||
|
|
@ -1365,13 +1352,13 @@ int RegularMesh::set_grid()
|
|||
}
|
||||
|
||||
// Check for negative widths
|
||||
if (xt::any(width_ < 0.0)) {
|
||||
if ((width_ < 0.0).any()) {
|
||||
set_errmsg("Cannot have a negative width on a regular mesh.");
|
||||
return OPENMC_E_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Set width and upper right coordinate
|
||||
upper_right_ = xt::eval(lower_left_ + shape * width_);
|
||||
upper_right_ = lower_left_ + shape * width_;
|
||||
|
||||
} else if (upper_right_.size() > 0) {
|
||||
|
||||
|
|
@ -1383,7 +1370,7 @@ int RegularMesh::set_grid()
|
|||
}
|
||||
|
||||
// Check that upper-right is above lower-left
|
||||
if (xt::any(upper_right_ < lower_left_)) {
|
||||
if ((upper_right_ < lower_left_).any()) {
|
||||
set_errmsg(
|
||||
"The upper_right coordinates of a regular mesh must be greater than "
|
||||
"the lower_left coordinates.");
|
||||
|
|
@ -1391,11 +1378,11 @@ int RegularMesh::set_grid()
|
|||
}
|
||||
|
||||
// Set width
|
||||
width_ = xt::eval((upper_right_ - lower_left_) / shape);
|
||||
width_ = (upper_right_ - lower_left_) / shape;
|
||||
}
|
||||
|
||||
// Set material volumes
|
||||
volume_frac_ = 1.0 / xt::prod(shape)();
|
||||
volume_frac_ = 1.0 / shape.prod();
|
||||
|
||||
element_volume_ = 1.0;
|
||||
for (int i = 0; i < n_dimension_; i++) {
|
||||
|
|
@ -1411,7 +1398,7 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node}
|
|||
fatal_error("Must specify <dimension> on a regular mesh.");
|
||||
}
|
||||
|
||||
xt::xtensor<int, 1> shape = get_node_xarray<int>(node, "dimension");
|
||||
tensor::Tensor<int> shape = get_node_tensor<int>(node, "dimension");
|
||||
int n = n_dimension_ = shape.size();
|
||||
if (n != 1 && n != 2 && n != 3) {
|
||||
fatal_error("Mesh must be one, two, or three dimensions.");
|
||||
|
|
@ -1421,7 +1408,7 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node}
|
|||
// Check for lower-left coordinates
|
||||
if (check_for_node(node, "lower_left")) {
|
||||
// Read mesh lower-left corner location
|
||||
lower_left_ = get_node_xarray<double>(node, "lower_left");
|
||||
lower_left_ = get_node_tensor<double>(node, "lower_left");
|
||||
} else {
|
||||
fatal_error("Must specify <lower_left> on a mesh.");
|
||||
}
|
||||
|
|
@ -1432,11 +1419,11 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node}
|
|||
fatal_error("Cannot specify both <upper_right> and <width> on a mesh.");
|
||||
}
|
||||
|
||||
width_ = get_node_xarray<double>(node, "width");
|
||||
width_ = get_node_tensor<double>(node, "width");
|
||||
|
||||
} else if (check_for_node(node, "upper_right")) {
|
||||
|
||||
upper_right_ = get_node_xarray<double>(node, "upper_right");
|
||||
upper_right_ = get_node_tensor<double>(node, "upper_right");
|
||||
|
||||
} else {
|
||||
fatal_error("Must specify either <upper_right> or <width> on a mesh.");
|
||||
|
|
@ -1454,7 +1441,7 @@ RegularMesh::RegularMesh(hid_t group) : StructuredMesh {group}
|
|||
fatal_error("Must specify <dimension> on a regular mesh.");
|
||||
}
|
||||
|
||||
xt::xtensor<int, 1> shape;
|
||||
tensor::Tensor<int> shape;
|
||||
read_dataset(group, "dimension", shape);
|
||||
int n = n_dimension_ = shape.size();
|
||||
if (n != 1 && n != 2 && n != 3) {
|
||||
|
|
@ -1569,13 +1556,13 @@ std::pair<vector<double>, vector<double>> RegularMesh::plot(
|
|||
|
||||
void RegularMesh::to_hdf5_inner(hid_t mesh_group) const
|
||||
{
|
||||
write_dataset(mesh_group, "dimension", get_x_shape());
|
||||
write_dataset(mesh_group, "dimension", get_shape_tensor());
|
||||
write_dataset(mesh_group, "lower_left", lower_left_);
|
||||
write_dataset(mesh_group, "upper_right", upper_right_);
|
||||
write_dataset(mesh_group, "width", width_);
|
||||
}
|
||||
|
||||
xt::xtensor<double, 1> RegularMesh::count_sites(
|
||||
tensor::Tensor<double> RegularMesh::count_sites(
|
||||
const SourceSite* bank, int64_t length, bool* outside) const
|
||||
{
|
||||
// Determine shape of array for counts
|
||||
|
|
@ -1583,7 +1570,7 @@ xt::xtensor<double, 1> RegularMesh::count_sites(
|
|||
vector<std::size_t> shape = {m};
|
||||
|
||||
// Create array of zeros
|
||||
xt::xarray<double> cnt {shape, 0.0};
|
||||
auto cnt = tensor::zeros<double>(shape);
|
||||
bool outside_ = false;
|
||||
|
||||
for (int64_t i = 0; i < length; i++) {
|
||||
|
|
@ -1602,31 +1589,25 @@ xt::xtensor<double, 1> RegularMesh::count_sites(
|
|||
cnt(mesh_bin) += site.wgt;
|
||||
}
|
||||
|
||||
// Create copy of count data. Since ownership will be acquired by xtensor,
|
||||
// std::allocator must be used to avoid Valgrind mismatched free() / delete
|
||||
// warnings.
|
||||
// Create reduced count data
|
||||
auto counts = tensor::zeros<double>(shape);
|
||||
int total = cnt.size();
|
||||
double* cnt_reduced = std::allocator<double> {}.allocate(total);
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
// collect values from all processors
|
||||
MPI_Reduce(
|
||||
cnt.data(), cnt_reduced, total, MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm);
|
||||
cnt.data(), counts.data(), total, MPI_DOUBLE, MPI_SUM, 0, mpi::intracomm);
|
||||
|
||||
// Check if there were sites outside the mesh for any processor
|
||||
if (outside) {
|
||||
MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm);
|
||||
}
|
||||
#else
|
||||
std::copy(cnt.data(), cnt.data() + total, cnt_reduced);
|
||||
std::copy(cnt.data(), cnt.data() + total, counts.data());
|
||||
if (outside)
|
||||
*outside = outside_;
|
||||
#endif
|
||||
|
||||
// Adapt reduced values in array back into an xarray
|
||||
auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), shape);
|
||||
xt::xarray<double> counts = arr;
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
|
@ -2698,7 +2679,7 @@ extern "C" int openmc_regular_mesh_get_params(
|
|||
return err;
|
||||
RegularMesh* m = dynamic_cast<RegularMesh*>(model::meshes[index].get());
|
||||
|
||||
if (m->lower_left_.dimension() == 0) {
|
||||
if (m->lower_left_.empty()) {
|
||||
set_errmsg("Mesh parameters have not been set.");
|
||||
return OPENMC_E_ALLOCATE;
|
||||
}
|
||||
|
|
@ -2725,17 +2706,17 @@ extern "C" int openmc_regular_mesh_set_params(
|
|||
|
||||
vector<std::size_t> shape = {static_cast<std::size_t>(n)};
|
||||
if (ll && ur) {
|
||||
m->lower_left_ = xt::adapt(ll, n, xt::no_ownership(), shape);
|
||||
m->upper_right_ = xt::adapt(ur, n, xt::no_ownership(), shape);
|
||||
m->width_ = (m->upper_right_ - m->lower_left_) / m->get_x_shape();
|
||||
m->lower_left_ = tensor::Tensor<double>(ll, n);
|
||||
m->upper_right_ = tensor::Tensor<double>(ur, n);
|
||||
m->width_ = (m->upper_right_ - m->lower_left_) / m->get_shape_tensor();
|
||||
} else if (ll && width) {
|
||||
m->lower_left_ = xt::adapt(ll, n, xt::no_ownership(), shape);
|
||||
m->width_ = xt::adapt(width, n, xt::no_ownership(), shape);
|
||||
m->upper_right_ = m->lower_left_ + m->get_x_shape() * m->width_;
|
||||
m->lower_left_ = tensor::Tensor<double>(ll, n);
|
||||
m->width_ = tensor::Tensor<double>(width, n);
|
||||
m->upper_right_ = m->lower_left_ + m->get_shape_tensor() * m->width_;
|
||||
} else if (ur && width) {
|
||||
m->upper_right_ = xt::adapt(ur, n, xt::no_ownership(), shape);
|
||||
m->width_ = xt::adapt(width, n, xt::no_ownership(), shape);
|
||||
m->lower_left_ = m->upper_right_ - m->get_x_shape() * m->width_;
|
||||
m->upper_right_ = tensor::Tensor<double>(ur, n);
|
||||
m->width_ = tensor::Tensor<double>(width, n);
|
||||
m->lower_left_ = m->upper_right_ - m->get_shape_tensor() * m->width_;
|
||||
} else {
|
||||
set_errmsg("At least two parameters must be specified.");
|
||||
return OPENMC_E_INVALID_ARGUMENT;
|
||||
|
|
@ -2745,7 +2726,7 @@ extern "C" int openmc_regular_mesh_set_params(
|
|||
|
||||
// TODO: incorporate this into method in RegularMesh that can be called from
|
||||
// here and from constructor
|
||||
m->volume_frac_ = 1.0 / xt::prod(m->get_x_shape())();
|
||||
m->volume_frac_ = 1.0 / m->get_shape_tensor().prod();
|
||||
m->element_volume_ = 1.0;
|
||||
for (int i = 0; i < m->n_dimension_; i++) {
|
||||
m->element_volume_ *= m->width_[i];
|
||||
|
|
@ -2794,7 +2775,7 @@ int openmc_structured_mesh_get_grid_impl(int32_t index, double** grid_x,
|
|||
return err;
|
||||
C* m = dynamic_cast<C*>(model::meshes[index].get());
|
||||
|
||||
if (m->lower_left_.dimension() == 0) {
|
||||
if (m->lower_left_.empty()) {
|
||||
set_errmsg("Mesh parameters have not been set.");
|
||||
return OPENMC_E_ALLOCATE;
|
||||
}
|
||||
|
|
|
|||
40
src/mgxs.cpp
40
src/mgxs.cpp
|
|
@ -5,10 +5,7 @@
|
|||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "xtensor/xsort.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -33,8 +30,7 @@ void Mgxs::init(const std::string& in_name, double in_awr,
|
|||
// Set the metadata
|
||||
name = in_name;
|
||||
awr = in_awr;
|
||||
// TODO: Remove adapt when in_KTs is an xtensor
|
||||
kTs = xt::adapt(in_kTs);
|
||||
kTs = tensor::Tensor<double>(in_kTs.data(), in_kTs.size());
|
||||
fissionable = in_fissionable;
|
||||
scatter_format = in_scatter_format;
|
||||
xs.resize(in_kTs.size());
|
||||
|
|
@ -73,7 +69,7 @@ void Mgxs::metadata_from_hdf5(hid_t xs_id, const vector<double>& temperature,
|
|||
}
|
||||
get_datasets(kT_group, dset_names);
|
||||
vector<size_t> shape = {num_temps};
|
||||
xt::xarray<double> temps_available(shape);
|
||||
tensor::Tensor<double> temps_available(shape);
|
||||
for (int i = 0; i < num_temps; i++) {
|
||||
read_double(kT_group, dset_names[i], &temps_available[i], true);
|
||||
|
||||
|
|
@ -108,19 +104,7 @@ void Mgxs::metadata_from_hdf5(hid_t xs_id, const vector<double>& temperature,
|
|||
// Determine actual temperatures to read
|
||||
for (const auto& T : temperature) {
|
||||
// Determine the closest temperature value
|
||||
// NOTE: the below block could be replaced with the following line,
|
||||
// though this gives a runtime error if using LLVM 20 or newer,
|
||||
// likely due to a bug in xtensor.
|
||||
// auto i_closest = xt::argmin(xt::abs(temps_available - T))[0];
|
||||
double closest = std::numeric_limits<double>::max();
|
||||
int i_closest = 0;
|
||||
for (int i = 0; i < temps_available.size(); i++) {
|
||||
double diff = std::abs(temps_available[i] - T);
|
||||
if (diff < closest) {
|
||||
closest = diff;
|
||||
i_closest = i;
|
||||
}
|
||||
}
|
||||
auto i_closest = tensor::abs(temps_available - T).argmin();
|
||||
|
||||
double temp_actual = temps_available[i_closest];
|
||||
if (std::fabs(temp_actual - T) < settings::temperature_tolerance) {
|
||||
|
|
@ -355,7 +339,7 @@ Mgxs::Mgxs(const std::string& in_name, const vector<double>& mat_kTs,
|
|||
for (int m = 0; m < micros.size(); m++) {
|
||||
switch (settings::temperature_method) {
|
||||
case TemperatureMethod::NEAREST: {
|
||||
micro_t[m] = xt::argmin(xt::abs(micros[m]->kTs - temp_desired))[0];
|
||||
micro_t[m] = tensor::abs(micros[m]->kTs - temp_desired).argmin();
|
||||
auto temp_actual = micros[m]->kTs[micro_t[m]];
|
||||
|
||||
if (std::abs(temp_actual - temp_desired) >=
|
||||
|
|
@ -368,7 +352,7 @@ Mgxs::Mgxs(const std::string& in_name, const vector<double>& mat_kTs,
|
|||
case TemperatureMethod::INTERPOLATION:
|
||||
// Get a list of bounding temperatures for each actual temperature
|
||||
// present in the model
|
||||
for (int k = 0; k < micros[m]->kTs.shape()[0] - 1; k++) {
|
||||
for (int k = 0; k < micros[m]->kTs.shape(0) - 1; k++) {
|
||||
if ((micros[m]->kTs[k] <= temp_desired) &&
|
||||
(temp_desired < micros[m]->kTs[k + 1])) {
|
||||
micro_t[m] = k;
|
||||
|
|
@ -474,7 +458,7 @@ double Mgxs::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu,
|
|||
val = xs_t->delayed_nu_fission(a, *dg, gin);
|
||||
} else {
|
||||
val = 0.;
|
||||
for (int d = 0; d < xs_t->delayed_nu_fission.shape()[1]; d++) {
|
||||
for (int d = 0; d < xs_t->delayed_nu_fission.shape(1); d++) {
|
||||
val += xs_t->delayed_nu_fission(a, d, gin);
|
||||
}
|
||||
}
|
||||
|
|
@ -489,7 +473,7 @@ double Mgxs::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu,
|
|||
} else {
|
||||
// provide an outgoing group-wise sum
|
||||
val = 0.;
|
||||
for (int g = 0; g < xs_t->chi_prompt.shape()[2]; g++) {
|
||||
for (int g = 0; g < xs_t->chi_prompt.shape(2); g++) {
|
||||
val += xs_t->chi_prompt(a, gin, g);
|
||||
}
|
||||
}
|
||||
|
|
@ -508,13 +492,13 @@ double Mgxs::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu,
|
|||
} else {
|
||||
if (dg != nullptr) {
|
||||
val = 0.;
|
||||
for (int g = 0; g < xs_t->delayed_nu_fission.shape()[2]; g++) {
|
||||
for (int g = 0; g < xs_t->delayed_nu_fission.shape(2); g++) {
|
||||
val += xs_t->delayed_nu_fission(a, *dg, gin, g);
|
||||
}
|
||||
} else {
|
||||
val = 0.;
|
||||
for (int g = 0; g < xs_t->delayed_nu_fission.shape()[2]; g++) {
|
||||
for (int d = 0; d < xs_t->delayed_nu_fission.shape()[3]; d++) {
|
||||
for (int g = 0; g < xs_t->delayed_nu_fission.shape(2); g++) {
|
||||
for (int d = 0; d < xs_t->delayed_nu_fission.shape(3); d++) {
|
||||
val += xs_t->delayed_nu_fission(a, d, gin, g);
|
||||
}
|
||||
}
|
||||
|
|
@ -650,7 +634,7 @@ bool Mgxs::equiv(const Mgxs& that)
|
|||
|
||||
int Mgxs::get_temperature_index(double sqrtkT) const
|
||||
{
|
||||
return xt::argmin(xt::abs(kTs - sqrtkT * sqrtkT))[0];
|
||||
return tensor::abs(kTs - sqrtkT * sqrtkT).argmin();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include <algorithm> // for sort, min_element
|
||||
#include <cassert>
|
||||
|
|
@ -361,8 +360,7 @@ void Nuclide::create_derived(
|
|||
{
|
||||
for (const auto& grid : grid_) {
|
||||
// Allocate and initialize cross section
|
||||
array<size_t, 2> shape {grid.energy.size(), 5};
|
||||
xs_.emplace_back(shape, 0.0);
|
||||
xs_.push_back(tensor::zeros<double>({grid.energy.size(), 5}));
|
||||
}
|
||||
|
||||
reaction_index_.fill(C_NONE);
|
||||
|
|
@ -375,9 +373,8 @@ void Nuclide::create_derived(
|
|||
for (int t = 0; t < kTs_.size(); ++t) {
|
||||
int j = rx->xs_[t].threshold;
|
||||
int n = rx->xs_[t].value.size();
|
||||
auto xs = xt::adapt(rx->xs_[t].value);
|
||||
auto pprod = xt::view(xs_[t], xt::range(j, j + n), XS_PHOTON_PROD);
|
||||
|
||||
auto xs = tensor::Tensor<double>(
|
||||
rx->xs_[t].value.data(), rx->xs_[t].value.size());
|
||||
for (const auto& p : rx->products_) {
|
||||
if (p.particle_.is_photon()) {
|
||||
for (int k = 0; k < n; ++k) {
|
||||
|
|
@ -396,7 +393,7 @@ void Nuclide::create_derived(
|
|||
}
|
||||
}
|
||||
|
||||
pprod[k] += f * xs[k] * (*p.yield_)(E);
|
||||
xs_[t](j + k, XS_PHOTON_PROD) += f * xs[k] * (*p.yield_)(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -406,20 +403,17 @@ void Nuclide::create_derived(
|
|||
continue;
|
||||
|
||||
// Add contribution to total cross section
|
||||
auto total = xt::view(xs_[t], xt::range(j, j + n), XS_TOTAL);
|
||||
total += xs;
|
||||
xs_[t].slice(tensor::range(j, j + n), XS_TOTAL) += xs;
|
||||
|
||||
// Add contribution to absorption cross section
|
||||
auto absorption = xt::view(xs_[t], xt::range(j, j + n), XS_ABSORPTION);
|
||||
if (is_disappearance(rx->mt_)) {
|
||||
absorption += xs;
|
||||
xs_[t].slice(tensor::range(j, j + n), XS_ABSORPTION) += xs;
|
||||
}
|
||||
|
||||
if (is_fission(rx->mt_)) {
|
||||
fissionable_ = true;
|
||||
auto fission = xt::view(xs_[t], xt::range(j, j + n), XS_FISSION);
|
||||
fission += xs;
|
||||
absorption += xs;
|
||||
xs_[t].slice(tensor::range(j, j + n), XS_FISSION) += xs;
|
||||
xs_[t].slice(tensor::range(j, j + n), XS_ABSORPTION) += xs;
|
||||
|
||||
// Keep track of fission reactions
|
||||
if (t == 0) {
|
||||
|
|
@ -510,7 +504,7 @@ void Nuclide::init_grid()
|
|||
double spacing = std::log(E_max / E_min) / M;
|
||||
|
||||
// Create equally log-spaced energy grid
|
||||
auto umesh = xt::linspace(0.0, M * spacing, M + 1);
|
||||
auto umesh = tensor::linspace(0.0, M * spacing, M + 1);
|
||||
|
||||
for (auto& grid : grid_) {
|
||||
// Resize array for storing grid indices
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/cell.h"
|
||||
|
|
|
|||
|
|
@ -13,11 +13,7 @@
|
|||
#include "openmc/search.h"
|
||||
#include "openmc/settings.h"
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "xtensor/xoperation.hpp"
|
||||
#include "xtensor/xslice.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <fmt/core.h>
|
||||
|
|
@ -33,7 +29,7 @@ constexpr int PhotonInteraction::MAX_STACK_SIZE;
|
|||
|
||||
namespace data {
|
||||
|
||||
xt::xtensor<double, 1> compton_profile_pz;
|
||||
tensor::Tensor<double> compton_profile_pz;
|
||||
|
||||
std::unordered_map<std::string, int> element_map;
|
||||
vector<unique_ptr<PhotonInteraction>> elements;
|
||||
|
|
@ -46,8 +42,6 @@ vector<unique_ptr<PhotonInteraction>> elements;
|
|||
|
||||
PhotonInteraction::PhotonInteraction(hid_t group)
|
||||
{
|
||||
using namespace xt::placeholders;
|
||||
|
||||
// Set index of element in global vector
|
||||
index_ = data::elements.size();
|
||||
|
||||
|
|
@ -96,7 +90,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
read_dataset(rgroup, "xs", pair_production_electron_);
|
||||
close_group(rgroup);
|
||||
} else {
|
||||
pair_production_electron_ = xt::zeros_like(energy_);
|
||||
pair_production_electron_ = tensor::zeros_like(energy_);
|
||||
}
|
||||
|
||||
// Read pair production
|
||||
|
|
@ -105,7 +99,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
read_dataset(rgroup, "xs", pair_production_nuclear_);
|
||||
close_group(rgroup);
|
||||
} else {
|
||||
pair_production_nuclear_ = xt::zeros_like(energy_);
|
||||
pair_production_nuclear_ = tensor::zeros_like(energy_);
|
||||
}
|
||||
|
||||
// Read photoelectric
|
||||
|
|
@ -119,7 +113,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
read_dataset(rgroup, "xs", heating_);
|
||||
close_group(rgroup);
|
||||
} else {
|
||||
heating_ = xt::zeros_like(energy_);
|
||||
heating_ = tensor::zeros_like(energy_);
|
||||
}
|
||||
|
||||
// Read subshell photoionization cross section and atomic relaxation data
|
||||
|
|
@ -133,7 +127,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
}
|
||||
|
||||
shells_.resize(n_shell);
|
||||
cross_sections_ = xt::zeros<double>({energy_.size(), n_shell});
|
||||
cross_sections_ = tensor::zeros<double>({energy_.size(), n_shell});
|
||||
|
||||
// Create mapping from designator to index
|
||||
std::unordered_map<int, int> shell_map;
|
||||
|
|
@ -168,15 +162,17 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
}
|
||||
|
||||
// Read subshell cross section
|
||||
xt::xtensor<double, 1> xs;
|
||||
tensor::Tensor<double> xs;
|
||||
dset = open_dataset(tgroup, "xs");
|
||||
read_attribute(dset, "threshold_idx", shell.threshold);
|
||||
close_dataset(dset);
|
||||
read_dataset(tgroup, "xs", xs);
|
||||
|
||||
auto cross_section =
|
||||
xt::view(cross_sections_, xt::range(shell.threshold, _), i);
|
||||
cross_section = xt::where(xs > 0, xt::log(xs), 0);
|
||||
cross_sections_.slice(tensor::range(static_cast<size_t>(shell.threshold),
|
||||
cross_sections_.shape(0)),
|
||||
i);
|
||||
cross_section = tensor::where(xs > 0, tensor::log(xs), 0);
|
||||
|
||||
if (object_exists(tgroup, "transitions")) {
|
||||
// Determine dimensions of transitions
|
||||
|
|
@ -186,11 +182,12 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
|
||||
int n_transition = dims[0];
|
||||
if (n_transition > 0) {
|
||||
xt::xtensor<double, 2> matrix;
|
||||
tensor::Tensor<double> matrix;
|
||||
read_dataset(tgroup, "transitions", matrix);
|
||||
|
||||
// Transition probability normalization
|
||||
double norm = xt::sum(xt::col(matrix, 3))();
|
||||
double norm =
|
||||
tensor::Tensor<double>(matrix.slice(tensor::all, 3)).sum();
|
||||
|
||||
shell.transitions.resize(n_transition);
|
||||
for (int j = 0; j < n_transition; ++j) {
|
||||
|
|
@ -220,7 +217,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
|
||||
// Read electron shell PDF and binding energies
|
||||
read_dataset(rgroup, "num_electrons", electron_pdf_);
|
||||
electron_pdf_ /= xt::sum(electron_pdf_);
|
||||
electron_pdf_ /= electron_pdf_.sum();
|
||||
read_dataset(rgroup, "binding_energy", binding_energy_);
|
||||
|
||||
// Read Compton profiles
|
||||
|
|
@ -238,7 +235,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
auto is_close = [](double a, double b) {
|
||||
return std::abs(a - b) / a < FP_REL_PRECISION;
|
||||
};
|
||||
subshell_map_ = xt::full_like(binding_energy_, -1);
|
||||
subshell_map_ = tensor::Tensor<int>(binding_energy_.shape(), -1);
|
||||
for (int i = 0; i < binding_energy_.size(); ++i) {
|
||||
double E_b = binding_energy_[i];
|
||||
if (i < n_shell && is_close(E_b, shells_[i].binding_energy)) {
|
||||
|
|
@ -257,7 +254,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
// Create Compton profile CDF
|
||||
auto n_profile = data::compton_profile_pz.size();
|
||||
auto n_shell_compton = profile_pdf_.shape(0);
|
||||
profile_cdf_ = xt::empty<double>({n_shell_compton, n_profile});
|
||||
profile_cdf_ = tensor::Tensor<double>({n_shell_compton, n_profile});
|
||||
for (int i = 0; i < n_shell_compton; ++i) {
|
||||
double c = 0.0;
|
||||
profile_cdf_(i, 0) = 0.0;
|
||||
|
|
@ -276,11 +273,11 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
// Read bremsstrahlung scaled DCS
|
||||
rgroup = open_group(group, "bremsstrahlung");
|
||||
read_dataset(rgroup, "dcs", dcs_);
|
||||
auto n_e = dcs_.shape()[0];
|
||||
auto n_k = dcs_.shape()[1];
|
||||
auto n_e = dcs_.shape(0);
|
||||
auto n_k = dcs_.shape(1);
|
||||
|
||||
// Get energy grids used for bremsstrahlung DCS and for stopping powers
|
||||
xt::xtensor<double, 1> electron_energy;
|
||||
tensor::Tensor<double> electron_energy;
|
||||
read_dataset(rgroup, "electron_energy", electron_energy);
|
||||
if (data::ttb_k_grid.size() == 0) {
|
||||
read_dataset(rgroup, "photon_energy", data::ttb_k_grid);
|
||||
|
|
@ -305,12 +302,12 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
(std::log(E(i_grid + 1)) - std::log(E(i_grid)));
|
||||
|
||||
// Interpolate bremsstrahlung DCS at the cutoff energy and truncate
|
||||
xt::xtensor<double, 2> dcs({n_e - i_grid, n_k});
|
||||
tensor::Tensor<double> dcs({n_e - i_grid, n_k});
|
||||
for (int i = 0; i < n_k; ++i) {
|
||||
double y = std::exp(
|
||||
std::log(dcs_(i_grid, i)) +
|
||||
f * (std::log(dcs_(i_grid + 1, i)) - std::log(dcs_(i_grid, i))));
|
||||
auto col_i = xt::view(dcs, xt::all(), i);
|
||||
tensor::View<double> col_i = dcs.slice(tensor::all, i);
|
||||
col_i(0) = y;
|
||||
for (int j = i_grid + 1; j < n_e; ++j) {
|
||||
col_i(j - i_grid) = dcs_(j, i);
|
||||
|
|
@ -318,9 +315,11 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
}
|
||||
dcs_ = dcs;
|
||||
|
||||
xt::xtensor<double, 1> frst {cutoff};
|
||||
electron_energy = xt::concatenate(xt::xtuple(
|
||||
frst, xt::view(electron_energy, xt::range(i_grid + 1, n_e))));
|
||||
tensor::Tensor<double> frst({static_cast<size_t>(1)});
|
||||
frst(0) = cutoff;
|
||||
tensor::Tensor<double> rest(electron_energy.slice(
|
||||
tensor::range(i_grid + 1, electron_energy.size())));
|
||||
electron_energy = tensor::concatenate(frst, rest);
|
||||
}
|
||||
|
||||
// Set incident particle energy grid
|
||||
|
|
@ -329,7 +328,8 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
}
|
||||
|
||||
// Calculate the radiative stopping power
|
||||
stopping_power_radiative_ = xt::empty<double>({data::ttb_e_grid.size()});
|
||||
stopping_power_radiative_ =
|
||||
tensor::Tensor<double>({data::ttb_e_grid.size()});
|
||||
for (int i = 0; i < data::ttb_e_grid.size(); ++i) {
|
||||
// Integrate over reduced photon energy
|
||||
double c = 0.0;
|
||||
|
|
@ -354,14 +354,15 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
// values below exp(-499) we store the log as -900, for which exp(-900)
|
||||
// evaluates to zero.
|
||||
double limit = std::exp(-499.0);
|
||||
energy_ = xt::log(energy_);
|
||||
coherent_ = xt::where(coherent_ > limit, xt::log(coherent_), -900.0);
|
||||
incoherent_ = xt::where(incoherent_ > limit, xt::log(incoherent_), -900.0);
|
||||
photoelectric_total_ = xt::where(
|
||||
photoelectric_total_ > limit, xt::log(photoelectric_total_), -900.0);
|
||||
pair_production_total_ = xt::where(
|
||||
pair_production_total_ > limit, xt::log(pair_production_total_), -900.0);
|
||||
heating_ = xt::where(heating_ > limit, xt::log(heating_), -900.0);
|
||||
energy_ = tensor::log(energy_);
|
||||
coherent_ = tensor::where(coherent_ > limit, tensor::log(coherent_), -900.0);
|
||||
incoherent_ =
|
||||
tensor::where(incoherent_ > limit, tensor::log(incoherent_), -900.0);
|
||||
photoelectric_total_ = tensor::where(
|
||||
photoelectric_total_ > limit, tensor::log(photoelectric_total_), -900.0);
|
||||
pair_production_total_ = tensor::where(pair_production_total_ > limit,
|
||||
tensor::log(pair_production_total_), -900.0);
|
||||
heating_ = tensor::where(heating_ > limit, tensor::log(heating_), -900.0);
|
||||
}
|
||||
|
||||
PhotonInteraction::~PhotonInteraction()
|
||||
|
|
@ -512,7 +513,7 @@ void PhotonInteraction::compton_doppler(
|
|||
c = prn(seed) * c_max;
|
||||
|
||||
// Determine pz corresponding to sampled cdf value
|
||||
auto cdf_shell = xt::view(profile_cdf_, shell, xt::all());
|
||||
tensor::View<const double> cdf_shell = profile_cdf_.slice(shell);
|
||||
int i = lower_bound_index(cdf_shell.cbegin(), cdf_shell.cend(), c);
|
||||
double pz_l = data::compton_profile_pz(i);
|
||||
double pz_r = data::compton_profile_pz(i + 1);
|
||||
|
|
@ -608,8 +609,8 @@ void PhotonInteraction::calculate_xs(Particle& p) const
|
|||
|
||||
// Calculate microscopic photoelectric cross section
|
||||
xs.photoelectric = 0.0;
|
||||
const auto& xs_lower = xt::row(cross_sections_, i_grid);
|
||||
const auto& xs_upper = xt::row(cross_sections_, i_grid + 1);
|
||||
tensor::View<const double> xs_lower = cross_sections_.slice(i_grid);
|
||||
tensor::View<const double> xs_upper = cross_sections_.slice(i_grid + 1);
|
||||
|
||||
for (int i = 0; i < xs_upper.size(); ++i)
|
||||
if (xs_lower(i) != 0)
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@
|
|||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/tensor.h"
|
||||
#include <algorithm> // for max, min, max_element
|
||||
#include <cmath> // for sqrt, exp, log, abs, copysign
|
||||
#include <xtensor/xview.hpp>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -375,8 +375,9 @@ void sample_photon_reaction(Particle& p)
|
|||
// cross sections
|
||||
int i_grid = micro.index_grid;
|
||||
double f = micro.interp_factor;
|
||||
const auto& xs_lower = xt::row(element.cross_sections_, i_grid);
|
||||
const auto& xs_upper = xt::row(element.cross_sections_, i_grid + 1);
|
||||
tensor::View<const double> xs_lower = element.cross_sections_.slice(i_grid);
|
||||
tensor::View<const double> xs_upper =
|
||||
element.cross_sections_.slice(i_grid + 1);
|
||||
|
||||
for (int i_shell = 0; i_shell < element.shells_.size(); ++i_shell) {
|
||||
const auto& shell {element.shells_[i_shell]};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/bank.h"
|
||||
|
|
|
|||
30
src/plot.cpp
30
src/plot.cpp
|
|
@ -7,8 +7,7 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "xtensor/xmanipulation.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/ostream.h>
|
||||
#ifdef USE_LIBPNG
|
||||
|
|
@ -74,7 +73,8 @@ void IdData::set_value(size_t y, size_t x, const GeometryState& p, int level)
|
|||
|
||||
void IdData::set_overlap(size_t y, size_t x)
|
||||
{
|
||||
xt::view(data_, y, x, xt::all()) = OVERLAP;
|
||||
for (size_t k = 0; k < data_.shape(2); ++k)
|
||||
data_(y, x, k) = OVERLAP;
|
||||
}
|
||||
|
||||
PropertyData::PropertyData(size_t h_res, size_t v_res)
|
||||
|
|
@ -783,14 +783,14 @@ void output_ppm(const std::string& filename, const ImageData& data)
|
|||
|
||||
// Write header
|
||||
of << "P6\n";
|
||||
of << data.shape()[0] << " " << data.shape()[1] << "\n";
|
||||
of << data.shape(0) << " " << data.shape(1) << "\n";
|
||||
of << "255\n";
|
||||
of.close();
|
||||
|
||||
of.open(fname, std::ios::binary | std::ios::app);
|
||||
// Write color for each pixel
|
||||
for (int y = 0; y < data.shape()[1]; y++) {
|
||||
for (int x = 0; x < data.shape()[0]; x++) {
|
||||
for (int y = 0; y < data.shape(1); y++) {
|
||||
for (int x = 0; x < data.shape(0); x++) {
|
||||
RGBColor rgb = data(x, y);
|
||||
of << rgb.red << rgb.green << rgb.blue;
|
||||
}
|
||||
|
|
@ -822,8 +822,8 @@ void output_png(const std::string& filename, const ImageData& data)
|
|||
png_init_io(png_ptr, fp);
|
||||
|
||||
// Write header (8 bit colour depth)
|
||||
int width = data.shape()[0];
|
||||
int height = data.shape()[1];
|
||||
int width = data.shape(0);
|
||||
int height = data.shape(1);
|
||||
png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
|
@ -1024,9 +1024,14 @@ void Plot::create_voxel() const
|
|||
|
||||
// select only cell/material ID data and flip the y-axis
|
||||
int idx = color_by_ == PlotColorBy::cells ? 0 : 2;
|
||||
xt::xtensor<int32_t, 2> data_slice =
|
||||
xt::view(ids.data_, xt::all(), xt::all(), idx);
|
||||
xt::xtensor<int32_t, 2> data_flipped = xt::flip(data_slice, 0);
|
||||
// Extract 2D slice at index idx from 3D data
|
||||
size_t rows = ids.data_.shape(0);
|
||||
size_t cols = ids.data_.shape(1);
|
||||
tensor::Tensor<int32_t> data_slice({rows, cols});
|
||||
for (size_t r = 0; r < rows; ++r)
|
||||
for (size_t c = 0; c < cols; ++c)
|
||||
data_slice(r, c) = ids.data_(r, c, idx);
|
||||
tensor::Tensor<int32_t> data_flipped = data_slice.flip(0);
|
||||
|
||||
// Write to HDF5 dataset
|
||||
voxel_write_slice(z, dspace, dset, memspace, data_flipped.data());
|
||||
|
|
@ -1272,7 +1277,8 @@ ImageData WireframeRayTracePlot::create_image() const
|
|||
// This array marks where the initial wireframe was drawn. We convolve it with
|
||||
// a filter that gets adjusted with the wireframe thickness in order to
|
||||
// thicken the lines.
|
||||
xt::xtensor<int, 2> wireframe_initial({width, height}, 0);
|
||||
tensor::Tensor<int> wireframe_initial(
|
||||
{static_cast<size_t>(width), static_cast<size_t>(height)}, 0);
|
||||
|
||||
/* Holds all of the track segments for the current rendered line of pixels.
|
||||
* old_segments holds a copy of this_line_segments from the previous line.
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "openmc/weight_windows.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <numeric>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -63,8 +64,7 @@ FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_)
|
|||
|
||||
// Create a new 2D tensor with the same size as the first
|
||||
// two dimensions of the 3D tensor
|
||||
tally_volumes_[i] =
|
||||
xt::xtensor<double, 2>::from_shape({shape[0], shape[1]});
|
||||
tally_volumes_[i] = tensor::Tensor<double>({shape[0], shape[1]});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include "openmc/settings.h"
|
||||
#include "openmc/simulation.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include "openmc/distribution_spatial.h"
|
||||
#include "openmc/random_dist.h"
|
||||
#include "openmc/source.h"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
#include <cmath>
|
||||
#include <numeric>
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -19,8 +18,8 @@ namespace openmc {
|
|||
// ScattData base-class methods
|
||||
//==============================================================================
|
||||
|
||||
void ScattData::base_init(int order, const xt::xtensor<int, 1>& in_gmin,
|
||||
const xt::xtensor<int, 1>& in_gmax, const double_2dvec& in_energy,
|
||||
void ScattData::base_init(int order, const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_energy,
|
||||
const double_2dvec& in_mult)
|
||||
{
|
||||
size_t groups = in_energy.size();
|
||||
|
|
@ -63,23 +62,26 @@ void ScattData::base_init(int order, const xt::xtensor<int, 1>& in_gmin,
|
|||
|
||||
void ScattData::base_combine(size_t max_order, size_t order_dim,
|
||||
const vector<ScattData*>& those_scatts, const vector<double>& scalars,
|
||||
xt::xtensor<int, 1>& in_gmin, xt::xtensor<int, 1>& in_gmax,
|
||||
tensor::Tensor<int>& in_gmin, tensor::Tensor<int>& in_gmax,
|
||||
double_2dvec& sparse_mult, double_3dvec& sparse_scatter)
|
||||
{
|
||||
size_t groups = those_scatts[0]->energy.size();
|
||||
|
||||
// Now allocate and zero our storage spaces
|
||||
xt::xtensor<double, 3> this_nuscatt_matrix({groups, groups, order_dim}, 0.);
|
||||
xt::xtensor<double, 2> this_nuscatt_P0({groups, groups}, 0.);
|
||||
xt::xtensor<double, 2> this_scatt_P0({groups, groups}, 0.);
|
||||
xt::xtensor<double, 2> this_mult({groups, groups}, 1.);
|
||||
tensor::Tensor<double> this_nuscatt_matrix =
|
||||
tensor::zeros<double>({groups, groups, order_dim});
|
||||
tensor::Tensor<double> this_nuscatt_P0 =
|
||||
tensor::zeros<double>({groups, groups});
|
||||
tensor::Tensor<double> this_scatt_P0 =
|
||||
tensor::zeros<double>({groups, groups});
|
||||
tensor::Tensor<double> this_mult = tensor::ones<double>({groups, groups});
|
||||
|
||||
// Build the dense scattering and multiplicity matrices
|
||||
for (int i = 0; i < those_scatts.size(); i++) {
|
||||
ScattData* that = those_scatts[i];
|
||||
|
||||
// Build the dense matrix for that object
|
||||
xt::xtensor<double, 3> that_matrix = that->get_matrix(max_order);
|
||||
tensor::Tensor<double> that_matrix = that->get_matrix(max_order);
|
||||
|
||||
// Now add that to this for the nu-scatter matrix
|
||||
this_nuscatt_matrix += scalars[i] * that_matrix;
|
||||
|
|
@ -97,7 +99,7 @@ void ScattData::base_combine(size_t max_order, size_t order_dim,
|
|||
|
||||
// Now we have the dense nuscatt and scatt, we can easily compute the
|
||||
// multiplicity matrix by dividing the two and fixing any nans
|
||||
this_mult = xt::nan_to_num(this_nuscatt_P0 / this_scatt_P0);
|
||||
this_mult = tensor::nan_to_num(this_nuscatt_P0 / this_scatt_P0);
|
||||
|
||||
// We have the data, now we need to convert to a jagged array and then use
|
||||
// the initialize function to store it on the object.
|
||||
|
|
@ -106,7 +108,7 @@ void ScattData::base_combine(size_t max_order, size_t order_dim,
|
|||
int gmin_;
|
||||
for (gmin_ = 0; gmin_ < groups; gmin_++) {
|
||||
bool non_zero = false;
|
||||
for (int l = 0; l < this_nuscatt_matrix.shape()[2]; l++) {
|
||||
for (int l = 0; l < this_nuscatt_matrix.shape(2); l++) {
|
||||
if (this_nuscatt_matrix(gin, gmin_, l) != 0.) {
|
||||
non_zero = true;
|
||||
break;
|
||||
|
|
@ -118,7 +120,7 @@ void ScattData::base_combine(size_t max_order, size_t order_dim,
|
|||
int gmax_;
|
||||
for (gmax_ = groups - 1; gmax_ >= 0; gmax_--) {
|
||||
bool non_zero = false;
|
||||
for (int l = 0; l < this_nuscatt_matrix.shape()[2]; l++) {
|
||||
for (int l = 0; l < this_nuscatt_matrix.shape(2); l++) {
|
||||
if (this_nuscatt_matrix(gin, gmax_, l) != 0.) {
|
||||
non_zero = true;
|
||||
break;
|
||||
|
|
@ -143,8 +145,8 @@ void ScattData::base_combine(size_t max_order, size_t order_dim,
|
|||
sparse_mult[gin].resize(gmax_ - gmin_ + 1);
|
||||
int i_gout = 0;
|
||||
for (int gout = gmin_; gout <= gmax_; gout++) {
|
||||
sparse_scatter[gin][i_gout].resize(this_nuscatt_matrix.shape()[2]);
|
||||
for (int l = 0; l < this_nuscatt_matrix.shape()[2]; l++) {
|
||||
sparse_scatter[gin][i_gout].resize(this_nuscatt_matrix.shape(2));
|
||||
for (int l = 0; l < this_nuscatt_matrix.shape(2); l++) {
|
||||
sparse_scatter[gin][i_gout][l] = this_nuscatt_matrix(gin, gout, l);
|
||||
}
|
||||
sparse_mult[gin][i_gout] = this_mult(gin, gout);
|
||||
|
|
@ -227,8 +229,8 @@ double ScattData::get_xs(
|
|||
// ScattDataLegendre methods
|
||||
//==============================================================================
|
||||
|
||||
void ScattDataLegendre::init(const xt::xtensor<int, 1>& in_gmin,
|
||||
const xt::xtensor<int, 1>& in_gmax, const double_2dvec& in_mult,
|
||||
void ScattDataLegendre::init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs)
|
||||
{
|
||||
size_t groups = coeffs.size();
|
||||
|
|
@ -239,7 +241,7 @@ void ScattDataLegendre::init(const xt::xtensor<int, 1>& in_gmin,
|
|||
|
||||
// Get the scattering cross section value by summing the un-normalized P0
|
||||
// coefficient in the variable matrix over all outgoing groups.
|
||||
scattxs = xt::zeros<double>({groups});
|
||||
scattxs = tensor::zeros<double>({groups});
|
||||
for (int gin = 0; gin < groups; gin++) {
|
||||
int num_groups = in_gmax[gin] - in_gmin[gin] + 1;
|
||||
for (int i_gout = 0; i_gout < num_groups; i_gout++) {
|
||||
|
|
@ -386,8 +388,8 @@ void ScattDataLegendre::combine(
|
|||
|
||||
size_t groups = those_scatts[0]->energy.size();
|
||||
|
||||
xt::xtensor<int, 1> in_gmin({groups}, 0);
|
||||
xt::xtensor<int, 1> in_gmax({groups}, 0);
|
||||
tensor::Tensor<int> in_gmin({groups}, 0);
|
||||
tensor::Tensor<int> in_gmax({groups}, 0);
|
||||
double_3dvec sparse_scatter(groups);
|
||||
double_2dvec sparse_mult(groups);
|
||||
|
||||
|
|
@ -404,12 +406,13 @@ void ScattDataLegendre::combine(
|
|||
|
||||
//==============================================================================
|
||||
|
||||
xt::xtensor<double, 3> ScattDataLegendre::get_matrix(size_t max_order)
|
||||
tensor::Tensor<double> ScattDataLegendre::get_matrix(size_t max_order)
|
||||
{
|
||||
// Get the sizes and initialize the data to 0
|
||||
size_t groups = energy.size();
|
||||
size_t order_dim = max_order + 1;
|
||||
xt::xtensor<double, 3> matrix({groups, groups, order_dim}, 0.);
|
||||
tensor::Tensor<double> matrix =
|
||||
tensor::zeros<double>({groups, groups, order_dim});
|
||||
|
||||
for (int gin = 0; gin < groups; gin++) {
|
||||
for (int i_gout = 0; i_gout < energy[gin].size(); i_gout++) {
|
||||
|
|
@ -427,8 +430,8 @@ xt::xtensor<double, 3> ScattDataLegendre::get_matrix(size_t max_order)
|
|||
// ScattDataHistogram methods
|
||||
//==============================================================================
|
||||
|
||||
void ScattDataHistogram::init(const xt::xtensor<int, 1>& in_gmin,
|
||||
const xt::xtensor<int, 1>& in_gmax, const double_2dvec& in_mult,
|
||||
void ScattDataHistogram::init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs)
|
||||
{
|
||||
size_t groups = coeffs.size();
|
||||
|
|
@ -439,7 +442,7 @@ void ScattDataHistogram::init(const xt::xtensor<int, 1>& in_gmin,
|
|||
|
||||
// Get the scattering cross section value by summing the distribution
|
||||
// over all the histogram bins in angle and outgoing energy groups
|
||||
scattxs = xt::zeros<double>({groups});
|
||||
scattxs = tensor::zeros<double>({groups});
|
||||
for (int gin = 0; gin < groups; gin++) {
|
||||
for (int i_gout = 0; i_gout < matrix[gin].size(); i_gout++) {
|
||||
scattxs[gin] += std::accumulate(
|
||||
|
|
@ -468,7 +471,7 @@ void ScattDataHistogram::init(const xt::xtensor<int, 1>& in_gmin,
|
|||
ScattData::base_init(order, in_gmin, in_gmax, in_energy, in_mult);
|
||||
|
||||
// Build the angular distribution mu values
|
||||
mu = xt::linspace(-1., 1., order + 1);
|
||||
mu = tensor::linspace(-1., 1., order + 1);
|
||||
dmu = 2. / order;
|
||||
|
||||
// Calculate f(mu) and integrate it so we can avoid rejection sampling
|
||||
|
|
@ -513,7 +516,7 @@ double ScattDataHistogram::calc_f(int gin, int gout, double mu)
|
|||
int imu;
|
||||
if (mu == 1.) {
|
||||
// use size -2 to have the index one before the end
|
||||
imu = this->mu.shape()[0] - 2;
|
||||
imu = this->mu.shape(0) - 2;
|
||||
} else {
|
||||
imu = std::floor((mu + 1.) / dmu + 1.) - 1;
|
||||
}
|
||||
|
|
@ -559,13 +562,13 @@ void ScattDataHistogram::sample(
|
|||
|
||||
//==============================================================================
|
||||
|
||||
xt::xtensor<double, 3> ScattDataHistogram::get_matrix(size_t max_order)
|
||||
tensor::Tensor<double> ScattDataHistogram::get_matrix(size_t max_order)
|
||||
{
|
||||
// Get the sizes and initialize the data to 0
|
||||
size_t groups = energy.size();
|
||||
// We ignore the requested order for Histogram and Tabular representations
|
||||
size_t order_dim = get_order();
|
||||
xt::xtensor<double, 3> matrix({groups, groups, order_dim}, 0);
|
||||
tensor::Tensor<double> matrix({groups, groups, order_dim}, 0);
|
||||
|
||||
for (int gin = 0; gin < groups; gin++) {
|
||||
for (int i_gout = 0; i_gout < energy[gin].size(); i_gout++) {
|
||||
|
|
@ -600,8 +603,8 @@ void ScattDataHistogram::combine(
|
|||
|
||||
size_t groups = those_scatts[0]->energy.size();
|
||||
|
||||
xt::xtensor<int, 1> in_gmin({groups}, 0);
|
||||
xt::xtensor<int, 1> in_gmax({groups}, 0);
|
||||
tensor::Tensor<int> in_gmin({groups}, 0);
|
||||
tensor::Tensor<int> in_gmax({groups}, 0);
|
||||
double_3dvec sparse_scatter(groups);
|
||||
double_2dvec sparse_mult(groups);
|
||||
|
||||
|
|
@ -620,8 +623,8 @@ void ScattDataHistogram::combine(
|
|||
// ScattDataTabular methods
|
||||
//==============================================================================
|
||||
|
||||
void ScattDataTabular::init(const xt::xtensor<int, 1>& in_gmin,
|
||||
const xt::xtensor<int, 1>& in_gmax, const double_2dvec& in_mult,
|
||||
void ScattDataTabular::init(const tensor::Tensor<int>& in_gmin,
|
||||
const tensor::Tensor<int>& in_gmax, const double_2dvec& in_mult,
|
||||
const double_3dvec& coeffs)
|
||||
{
|
||||
size_t groups = coeffs.size();
|
||||
|
|
@ -631,12 +634,12 @@ void ScattDataTabular::init(const xt::xtensor<int, 1>& in_gmin,
|
|||
double_3dvec matrix = coeffs;
|
||||
|
||||
// Build the angular distribution mu values
|
||||
mu = xt::linspace(-1., 1., order);
|
||||
mu = tensor::linspace(-1., 1., order);
|
||||
dmu = 2. / (order - 1);
|
||||
|
||||
// Get the scattering cross section value by integrating the distribution
|
||||
// over all mu points and then combining over all outgoing groups
|
||||
scattxs = xt::zeros<double>({groups});
|
||||
scattxs = tensor::zeros<double>({groups});
|
||||
for (int gin = 0; gin < groups; gin++) {
|
||||
for (int i_gout = 0; i_gout < matrix[gin].size(); i_gout++) {
|
||||
for (int imu = 1; imu < order; imu++) {
|
||||
|
|
@ -713,7 +716,7 @@ double ScattDataTabular::calc_f(int gin, int gout, double mu)
|
|||
int imu;
|
||||
if (mu == 1.) {
|
||||
// use size -2 to have the index one before the end
|
||||
imu = this->mu.shape()[0] - 2;
|
||||
imu = this->mu.shape(0) - 2;
|
||||
} else {
|
||||
imu = std::floor((mu + 1.) / dmu + 1.) - 1;
|
||||
}
|
||||
|
|
@ -734,7 +737,7 @@ void ScattDataTabular::sample(
|
|||
sample_energy(gin, gout, i_gout, seed);
|
||||
|
||||
// Determine the outgoing cosine bin
|
||||
int NP = this->mu.shape()[0];
|
||||
int NP = this->mu.shape(0);
|
||||
double xi = prn(seed);
|
||||
|
||||
double c_k = dist[gin][i_gout][0];
|
||||
|
|
@ -776,13 +779,14 @@ void ScattDataTabular::sample(
|
|||
|
||||
//==============================================================================
|
||||
|
||||
xt::xtensor<double, 3> ScattDataTabular::get_matrix(size_t max_order)
|
||||
tensor::Tensor<double> ScattDataTabular::get_matrix(size_t max_order)
|
||||
{
|
||||
// Get the sizes and initialize the data to 0
|
||||
size_t groups = energy.size();
|
||||
// We ignore the requested order for Histogram and Tabular representations
|
||||
size_t order_dim = get_order();
|
||||
xt::xtensor<double, 3> matrix({groups, groups, order_dim}, 0.);
|
||||
tensor::Tensor<double> matrix =
|
||||
tensor::zeros<double>({groups, groups, order_dim});
|
||||
|
||||
for (int gin = 0; gin < groups; gin++) {
|
||||
for (int i_gout = 0; i_gout < energy[gin].size(); i_gout++) {
|
||||
|
|
@ -816,8 +820,8 @@ void ScattDataTabular::combine(
|
|||
|
||||
size_t groups = those_scatts[0]->energy.size();
|
||||
|
||||
xt::xtensor<int, 1> in_gmin({groups}, 0);
|
||||
xt::xtensor<int, 1> in_gmax({groups}, 0);
|
||||
tensor::Tensor<int> in_gmin({groups}, 0);
|
||||
tensor::Tensor<int> in_gmax({groups}, 0);
|
||||
double_3dvec sparse_scatter(groups);
|
||||
double_2dvec sparse_mult(groups);
|
||||
|
||||
|
|
@ -854,7 +858,7 @@ void convert_legendre_to_tabular(ScattDataLegendre& leg, ScattDataTabular& tab)
|
|||
tab.scattxs = leg.scattxs;
|
||||
|
||||
// Build mu and dmu
|
||||
tab.mu = xt::linspace(-1., 1., n_mu);
|
||||
tab.mu = tensor::linspace(-1., 1., n_mu);
|
||||
tab.dmu = 2. / (n_mu - 1);
|
||||
|
||||
// Calculate f(mu) and integrate it so we can avoid rejection sampling
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/endf.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
|
|
@ -26,11 +25,11 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
hid_t dset = open_dataset(group, "energy");
|
||||
|
||||
// Get interpolation parameters
|
||||
xt::xarray<int> temp;
|
||||
tensor::Tensor<int> temp;
|
||||
read_attribute(dset, "interpolation", temp);
|
||||
|
||||
auto temp_b = xt::view(temp, 0); // view of breakpoints
|
||||
auto temp_i = xt::view(temp, 1); // view of interpolation parameters
|
||||
tensor::View<int> temp_b = temp.slice(0); // breakpoints
|
||||
tensor::View<int> temp_i = temp.slice(1); // interpolation parameters
|
||||
|
||||
std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_));
|
||||
for (const auto i : temp_i)
|
||||
|
|
@ -51,12 +50,12 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
||||
xt::xarray<double> eout;
|
||||
tensor::Tensor<double> eout;
|
||||
read_dataset(dset, eout);
|
||||
close_dataset(dset);
|
||||
|
||||
// Read angle distributions
|
||||
xt::xarray<double> mu;
|
||||
tensor::Tensor<double> mu;
|
||||
read_dataset(group, "mu", mu);
|
||||
|
||||
for (int i = 0; i < n_energy; ++i) {
|
||||
|
|
@ -66,7 +65,7 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
if (i < n_energy - 1) {
|
||||
n = offsets[i + 1] - j;
|
||||
} else {
|
||||
n = eout.shape()[1] - j;
|
||||
n = eout.shape(1) - j;
|
||||
}
|
||||
|
||||
// Assign interpolation scheme and number of discrete lines
|
||||
|
|
@ -75,9 +74,9 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
d.n_discrete = n_discrete[i];
|
||||
|
||||
// Copy data
|
||||
d.e_out = xt::view(eout, 0, xt::range(j, j + n));
|
||||
d.p = xt::view(eout, 1, xt::range(j, j + n));
|
||||
d.c = xt::view(eout, 2, xt::range(j, j + n));
|
||||
d.e_out = eout.slice(0, tensor::range(j, j + n));
|
||||
d.p = eout.slice(1, tensor::range(j, j + n));
|
||||
d.c = eout.slice(2, tensor::range(j, j + n));
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
|
|
@ -119,10 +118,10 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
// Determine offset and size of distribution
|
||||
int offset_mu = std::lround(eout(4, offsets[i] + j));
|
||||
int m;
|
||||
if (offsets[i] + j + 1 < eout.shape()[1]) {
|
||||
if (offsets[i] + j + 1 < eout.shape(1)) {
|
||||
m = std::lround(eout(4, offsets[i] + j + 1)) - offset_mu;
|
||||
} else {
|
||||
m = mu.shape()[1] - offset_mu;
|
||||
m = mu.shape(1) - offset_mu;
|
||||
}
|
||||
|
||||
// For incoherent inelastic thermal scattering, the angle distributions
|
||||
|
|
@ -133,9 +132,12 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
interp_mu = 1;
|
||||
|
||||
auto interp = int2interp(interp_mu);
|
||||
auto xs = xt::view(mu, 0, xt::range(offset_mu, offset_mu + m));
|
||||
auto ps = xt::view(mu, 1, xt::range(offset_mu, offset_mu + m));
|
||||
auto cs = xt::view(mu, 2, xt::range(offset_mu, offset_mu + m));
|
||||
tensor::View<double> xs =
|
||||
mu.slice(0, tensor::range(offset_mu, offset_mu + m));
|
||||
tensor::View<double> ps =
|
||||
mu.slice(1, tensor::range(offset_mu, offset_mu + m));
|
||||
tensor::View<double> cs =
|
||||
mu.slice(2, tensor::range(offset_mu, offset_mu + m));
|
||||
|
||||
vector<double> x {xs.begin(), xs.end()};
|
||||
vector<double> p {ps.begin(), ps.end()};
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/math_functions.h"
|
||||
|
|
@ -27,11 +26,11 @@ KalbachMann::KalbachMann(hid_t group)
|
|||
hid_t dset = open_dataset(group, "energy");
|
||||
|
||||
// Get interpolation parameters
|
||||
xt::xarray<int> temp;
|
||||
tensor::Tensor<int> temp;
|
||||
read_attribute(dset, "interpolation", temp);
|
||||
|
||||
auto temp_b = xt::view(temp, 0); // view of breakpoints
|
||||
auto temp_i = xt::view(temp, 1); // view of interpolation parameters
|
||||
tensor::View<int> temp_b = temp.slice(0); // breakpoints
|
||||
tensor::View<int> temp_i = temp.slice(1); // interpolation parameters
|
||||
|
||||
std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_));
|
||||
for (const auto i : temp_i)
|
||||
|
|
@ -52,7 +51,7 @@ KalbachMann::KalbachMann(hid_t group)
|
|||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
||||
xt::xarray<double> eout;
|
||||
tensor::Tensor<double> eout;
|
||||
read_dataset(dset, eout);
|
||||
close_dataset(dset);
|
||||
|
||||
|
|
@ -63,7 +62,7 @@ KalbachMann::KalbachMann(hid_t group)
|
|||
if (i < n_energy - 1) {
|
||||
n = offsets[i + 1] - j;
|
||||
} else {
|
||||
n = eout.shape()[1] - j;
|
||||
n = eout.shape(1) - j;
|
||||
}
|
||||
|
||||
// Assign interpolation scheme and number of discrete lines
|
||||
|
|
@ -72,11 +71,11 @@ KalbachMann::KalbachMann(hid_t group)
|
|||
d.n_discrete = n_discrete[i];
|
||||
|
||||
// Copy data
|
||||
d.e_out = xt::view(eout, 0, xt::range(j, j + n));
|
||||
d.p = xt::view(eout, 1, xt::range(j, j + n));
|
||||
d.c = xt::view(eout, 2, xt::range(j, j + n));
|
||||
d.r = xt::view(eout, 3, xt::range(j, j + n));
|
||||
d.a = xt::view(eout, 4, xt::range(j, j + n));
|
||||
d.e_out = eout.slice(0, tensor::range(j, j + n));
|
||||
d.p = eout.slice(1, tensor::range(j, j + n));
|
||||
d.c = eout.slice(2, tensor::range(j, j + n));
|
||||
d.r = eout.slice(3, tensor::range(j, j + n));
|
||||
d.a = eout.slice(4, tensor::range(j, j + n));
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/search.h"
|
||||
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath> // for log, exp
|
||||
|
|
@ -85,7 +85,7 @@ void IncoherentElasticAEDiscrete::sample(
|
|||
// incoming energies.
|
||||
|
||||
// Sample outgoing cosine bin
|
||||
int n_mu = mu_out_.shape()[1];
|
||||
int n_mu = mu_out_.shape(1);
|
||||
int k = prn(seed) * n_mu;
|
||||
|
||||
// Rather than use the sampled discrete mu directly, it is smeared over
|
||||
|
|
@ -145,7 +145,7 @@ void IncoherentInelasticAEDiscrete::sample(
|
|||
// probability of 1). Otherwise, each bin is equally probable.
|
||||
|
||||
int j;
|
||||
int n = energy_out_.shape()[1];
|
||||
int n = energy_out_.shape(1);
|
||||
if (!skewed_) {
|
||||
// All bins equally likely
|
||||
j = prn(seed) * n;
|
||||
|
|
@ -178,7 +178,7 @@ void IncoherentInelasticAEDiscrete::sample(
|
|||
E_out = (1 - f) * E_ij + f * E_i1j;
|
||||
|
||||
// Sample outgoing cosine bin
|
||||
int m = mu_out_.shape()[2];
|
||||
int m = mu_out_.shape(2);
|
||||
int k = prn(seed) * m;
|
||||
|
||||
// Determine outgoing cosine corresponding to E_in[i] and E_in[i+1]
|
||||
|
|
@ -218,11 +218,11 @@ IncoherentInelasticAE::IncoherentInelasticAE(hid_t group)
|
|||
// On first pass, allocate space for angles
|
||||
if (j == 0) {
|
||||
auto n_mu = adist->x().size();
|
||||
d.mu = xt::empty<double>({d.n_e_out, n_mu});
|
||||
d.mu = tensor::Tensor<double>({d.n_e_out, n_mu});
|
||||
}
|
||||
|
||||
// Copy outgoing angles
|
||||
auto mu_j = xt::view(d.mu, j);
|
||||
tensor::View<double> mu_j = d.mu.slice(j);
|
||||
std::copy(adist->x().begin(), adist->x().end(), mu_j.begin());
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +287,7 @@ void IncoherentInelasticAE::sample(
|
|||
}
|
||||
|
||||
// Sample outgoing cosine bin
|
||||
int n_mu = distribution_[l].mu.shape()[1];
|
||||
int n_mu = distribution_[l].mu.shape(1);
|
||||
std::size_t k = prn(seed) * n_mu;
|
||||
|
||||
// Rather than use the sampled discrete mu directly, it is smeared over
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
#include <mpi.h>
|
||||
|
|
@ -413,7 +413,7 @@ void finalize_batch()
|
|||
|
||||
// Reset global tally results
|
||||
if (simulation::current_batch <= settings::n_inactive) {
|
||||
xt::view(simulation::global_tallies, xt::all()) = 0.0;
|
||||
simulation::global_tallies.fill(0.0);
|
||||
simulation::n_realizations = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <dlfcn.h> // for dlopen, dlsym, dlclose, dlerror
|
||||
#endif
|
||||
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/bank.h"
|
||||
|
|
@ -400,8 +400,9 @@ SourceSite IndependentSource::sample(uint64_t* seed) const
|
|||
auto p = particle_.transport_index();
|
||||
auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
|
||||
if (energy_ptr) {
|
||||
auto energies = xt::adapt(energy_ptr->x());
|
||||
if (xt::any(energies > data::energy_max[p])) {
|
||||
auto energies =
|
||||
tensor::Tensor<double>(energy_ptr->x().data(), energy_ptr->x().size());
|
||||
if ((energies > data::energy_max[p]).any()) {
|
||||
fatal_error("Source energy above range of energies of at least "
|
||||
"one cross section table");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
#include <cstdint> // for int64_t
|
||||
#include <string>
|
||||
|
||||
#include "xtensor/xbuilder.hpp" // for empty_like
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/bank.h"
|
||||
|
|
@ -277,8 +276,8 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source)
|
|||
std::string name = "tally " + std::to_string(tally->id_);
|
||||
hid_t tally_group = open_group(tallies_group, name.c_str());
|
||||
auto& results = tally->results_;
|
||||
write_tally_results(tally_group, results.shape()[0],
|
||||
results.shape()[1], results.shape()[2], results.data());
|
||||
write_tally_results(tally_group, results.shape(0), results.shape(1),
|
||||
results.shape(2), results.data());
|
||||
close_group(tally_group);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -517,8 +516,8 @@ extern "C" int openmc_statepoint_load(const char* filename)
|
|||
tally->writable_ = false;
|
||||
} else {
|
||||
auto& results = tally->results_;
|
||||
read_tally_results(tally_group, results.shape()[0],
|
||||
results.shape()[1], results.shape()[2], results.data());
|
||||
read_tally_results(tally_group, results.shape(0), results.shape(1),
|
||||
results.shape(2), results.data());
|
||||
|
||||
read_dataset(tally_group, "n_realizations", tally->n_realizations_);
|
||||
close_group(tally_group);
|
||||
|
|
@ -827,7 +826,7 @@ void write_unstructured_mesh_results()
|
|||
// construct result vectors
|
||||
vector<double> mean_vec(umesh->n_bins()),
|
||||
std_dev_vec(umesh->n_bins());
|
||||
for (int j = 0; j < tally->results_.shape()[0]; j++) {
|
||||
for (int j = 0; j < tally->results_.shape(0); j++) {
|
||||
// get the volume for this bin
|
||||
double volume = umesh->volume(j);
|
||||
// compute the mean
|
||||
|
|
@ -889,7 +888,7 @@ void write_tally_results_nr(hid_t file_id)
|
|||
|
||||
#ifdef OPENMC_MPI
|
||||
// Reduce global tallies
|
||||
xt::xtensor<double, 2> gt_reduced = xt::empty_like(gt);
|
||||
tensor::Tensor<double> gt_reduced({N_GLOBAL_TALLIES, 3});
|
||||
MPI_Reduce(gt.data(), gt_reduced.data(), gt.size(), MPI_DOUBLE, MPI_SUM, 0,
|
||||
mpi::intracomm);
|
||||
|
||||
|
|
@ -918,13 +917,18 @@ void write_tally_results_nr(hid_t file_id)
|
|||
write_attribute(file_id, "tallies_present", 1);
|
||||
}
|
||||
|
||||
// Get view of accumulated tally values
|
||||
auto values_view = xt::view(t->results_, xt::all(), xt::all(),
|
||||
xt::range(static_cast<int>(TallyResult::SUM),
|
||||
static_cast<int>(TallyResult::SUM_SQ) + 1));
|
||||
|
||||
// Make copy of tally values in contiguous array
|
||||
xt::xtensor<double, 3> values = values_view;
|
||||
// Copy the SUM and SUM_SQ columns from the tally results into a
|
||||
// contiguous array for MPI reduction
|
||||
const int r_start = static_cast<int>(TallyResult::SUM);
|
||||
const int r_end = static_cast<int>(TallyResult::SUM_SQ) + 1;
|
||||
const size_t r_count = r_end - r_start;
|
||||
const size_t ni = t->results_.shape(0);
|
||||
const size_t nj = t->results_.shape(1);
|
||||
tensor::Tensor<double> values({ni, nj, r_count});
|
||||
for (size_t i = 0; i < ni; i++)
|
||||
for (size_t j = 0; j < nj; j++)
|
||||
for (size_t r = 0; r < r_count; r++)
|
||||
values(i, j, r) = t->results_(i, j, r_start + r);
|
||||
|
||||
if (mpi::master) {
|
||||
// Open group for tally
|
||||
|
|
@ -938,19 +942,22 @@ void write_tally_results_nr(hid_t file_id)
|
|||
MPI_SUM, 0, mpi::intracomm);
|
||||
#endif
|
||||
|
||||
// At the end of the simulation, store the results back in the
|
||||
// regular TallyResults array
|
||||
// At the end of the simulation, store the reduced results back
|
||||
// into the tally results array
|
||||
if (simulation::current_batch == settings::n_max_batches ||
|
||||
simulation::satisfy_triggers) {
|
||||
values_view = values;
|
||||
for (size_t i = 0; i < ni; i++)
|
||||
for (size_t j = 0; j < nj; j++)
|
||||
for (size_t r = 0; r < r_count; r++)
|
||||
t->results_(i, j, r_start + r) = values(i, j, r);
|
||||
}
|
||||
|
||||
// Put in temporary tally result
|
||||
xt::xtensor<double, 3> results_copy = xt::zeros_like(t->results_);
|
||||
auto copy_view = xt::view(results_copy, xt::all(), xt::all(),
|
||||
xt::range(static_cast<int>(TallyResult::SUM),
|
||||
static_cast<int>(TallyResult::SUM_SQ) + 1));
|
||||
copy_view = values;
|
||||
// Put reduced values into a full-sized copy for writing to HDF5
|
||||
tensor::Tensor<double> results_copy = tensor::zeros_like(t->results_);
|
||||
for (size_t i = 0; i < ni; i++)
|
||||
for (size_t j = 0; j < nj; j++)
|
||||
for (size_t r = 0; r < r_count; r++)
|
||||
results_copy(i, j, r_start + r) = values(i, j, r);
|
||||
|
||||
// Write reduced tally results to file
|
||||
auto shape = results_copy.shape();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "openmc/cell.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/geometry.h"
|
||||
#include "openmc/tensor.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
namespace openmc {
|
||||
|
|
@ -108,7 +109,7 @@ void CellInstanceFilter::to_statepoint(hid_t filter_group) const
|
|||
{
|
||||
Filter::to_statepoint(filter_group);
|
||||
size_t n = cell_instances_.size();
|
||||
xt::xtensor<size_t, 2> data({n, 2});
|
||||
tensor::Tensor<size_t> data({n, 2});
|
||||
for (int64_t i = 0; i < n; ++i) {
|
||||
const auto& x = cell_instances_[i];
|
||||
data(i, 0) = model::cells[x.index_cell]->id_;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "openmc/tallies/filter_meshmaterial.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <utility> // for move
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
#include "openmc/error.h"
|
||||
#include "openmc/material.h"
|
||||
#include "openmc/mesh.h"
|
||||
#include "openmc/tensor.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
namespace openmc {
|
||||
|
|
@ -161,7 +163,7 @@ void MeshMaterialFilter::to_statepoint(hid_t filter_group) const
|
|||
write_dataset(filter_group, "mesh", model::meshes[mesh_]->id_);
|
||||
|
||||
size_t n = bins_.size();
|
||||
xt::xtensor<size_t, 2> data({n, 2});
|
||||
tensor::Tensor<size_t> data({n, 2});
|
||||
for (int64_t i = 0; i < n; ++i) {
|
||||
const auto& x = bins_[i];
|
||||
data(i, 0) = x.index_element;
|
||||
|
|
|
|||
|
|
@ -35,9 +35,7 @@
|
|||
#include "openmc/tallies/filter_time.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xbuilder.hpp" // for empty_like
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <algorithm> // for max, set_union
|
||||
|
|
@ -69,7 +67,7 @@ vector<double> time_grid;
|
|||
} // namespace model
|
||||
|
||||
namespace simulation {
|
||||
xt::xtensor_fixed<double, xt::xshape<N_GLOBAL_TALLIES, 3>> global_tallies;
|
||||
tensor::StaticTensor2D<double, N_GLOBAL_TALLIES, 3> global_tallies;
|
||||
int32_t n_realizations {0};
|
||||
} // namespace simulation
|
||||
|
||||
|
|
@ -806,9 +804,11 @@ void Tally::init_results()
|
|||
{
|
||||
int n_scores = scores_.size() * nuclides_.size();
|
||||
if (higher_moments_) {
|
||||
results_ = xt::empty<double>({n_filter_bins_, n_scores, 5});
|
||||
results_ = tensor::Tensor<double>({static_cast<size_t>(n_filter_bins_),
|
||||
static_cast<size_t>(n_scores), size_t {5}});
|
||||
} else {
|
||||
results_ = xt::empty<double>({n_filter_bins_, n_scores, 3});
|
||||
results_ = tensor::Tensor<double>({static_cast<size_t>(n_filter_bins_),
|
||||
static_cast<size_t>(n_scores), size_t {3}});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -816,7 +816,7 @@ void Tally::reset()
|
|||
{
|
||||
n_realizations_ = 0;
|
||||
if (results_.size() != 0) {
|
||||
xt::view(results_, xt::all()) = 0.0;
|
||||
results_.fill(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -851,9 +851,9 @@ void Tally::accumulate()
|
|||
if (higher_moments_) {
|
||||
#pragma omp parallel for
|
||||
// filter bins (specific cell, energy bins)
|
||||
for (int i = 0; i < results_.shape()[0]; ++i) {
|
||||
for (int i = 0; i < results_.shape(0); ++i) {
|
||||
// score bins (flux, total reaction rate, fission reaction rate, etc.)
|
||||
for (int j = 0; j < results_.shape()[1]; ++j) {
|
||||
for (int j = 0; j < results_.shape(1); ++j) {
|
||||
double val = results_(i, j, TallyResult::VALUE) * norm;
|
||||
double val2 = val * val;
|
||||
results_(i, j, TallyResult::VALUE) = 0.0;
|
||||
|
|
@ -866,9 +866,9 @@ void Tally::accumulate()
|
|||
} else {
|
||||
#pragma omp parallel for
|
||||
// filter bins (specific cell, energy bins)
|
||||
for (int i = 0; i < results_.shape()[0]; ++i) {
|
||||
for (int i = 0; i < results_.shape(0); ++i) {
|
||||
// score bins (flux, total reaction rate, fission reaction rate, etc.)
|
||||
for (int j = 0; j < results_.shape()[1]; ++j) {
|
||||
for (int j = 0; j < results_.shape(1); ++j) {
|
||||
double val = results_(i, j, TallyResult::VALUE) * norm;
|
||||
results_(i, j, TallyResult::VALUE) = 0.0;
|
||||
results_(i, j, TallyResult::SUM) += val;
|
||||
|
|
@ -888,18 +888,18 @@ int Tally::score_index(const std::string& score) const
|
|||
return -1;
|
||||
}
|
||||
|
||||
xt::xarray<double> Tally::get_reshaped_data() const
|
||||
tensor::Tensor<double> Tally::get_reshaped_data() const
|
||||
{
|
||||
std::vector<uint64_t> shape;
|
||||
vector<size_t> shape;
|
||||
for (auto f : filters()) {
|
||||
shape.push_back(model::tally_filters[f]->n_bins());
|
||||
}
|
||||
|
||||
// add number of scores and nuclides to tally
|
||||
shape.push_back(results_.shape()[1]);
|
||||
shape.push_back(results_.shape()[2]);
|
||||
shape.push_back(results_.shape(1));
|
||||
shape.push_back(results_.shape(2));
|
||||
|
||||
xt::xarray<double> reshaped_results = results_;
|
||||
tensor::Tensor<double> reshaped_results = results_;
|
||||
reshaped_results.reshape(shape);
|
||||
return reshaped_results;
|
||||
}
|
||||
|
|
@ -1004,13 +1004,14 @@ void reduce_tally_results()
|
|||
// Skip any tallies that are not active
|
||||
auto& tally {model::tallies[i_tally]};
|
||||
|
||||
// Get view of accumulated tally values
|
||||
auto values_view = xt::view(tally->results_, xt::all(), xt::all(),
|
||||
static_cast<int>(TallyResult::VALUE));
|
||||
// Extract 2D view of the VALUE column from the 3D results tensor,
|
||||
// then copy into a contiguous array for MPI reduction
|
||||
const int val_idx = static_cast<int>(TallyResult::VALUE);
|
||||
tensor::View<double> val_view =
|
||||
tally->results_.slice(tensor::all, tensor::all, val_idx);
|
||||
tensor::Tensor<double> values(val_view);
|
||||
|
||||
// Make copy of tally values in contiguous array
|
||||
xt::xtensor<double, 2> values = values_view;
|
||||
xt::xtensor<double, 2> values_reduced = xt::empty_like(values);
|
||||
tensor::Tensor<double> values_reduced(values.shape());
|
||||
|
||||
// Reduce contiguous set of tally results
|
||||
MPI_Reduce(values.data(), values_reduced.data(), values.size(),
|
||||
|
|
@ -1018,9 +1019,9 @@ void reduce_tally_results()
|
|||
|
||||
// Transfer values on master and reset on other ranks
|
||||
if (mpi::master) {
|
||||
values_view = values_reduced;
|
||||
val_view = values_reduced;
|
||||
} else {
|
||||
values_view = 0.0;
|
||||
val_view = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1028,14 +1029,13 @@ void reduce_tally_results()
|
|||
// Note that global tallies are *always* reduced even when no_reduce option
|
||||
// is on.
|
||||
|
||||
// Get view of global tally values
|
||||
// Get reference to global tallies
|
||||
auto& gt = simulation::global_tallies;
|
||||
auto gt_values_view =
|
||||
xt::view(gt, xt::all(), static_cast<int>(TallyResult::VALUE));
|
||||
const int val_col = static_cast<int>(TallyResult::VALUE);
|
||||
|
||||
// Make copy of values in contiguous array
|
||||
xt::xtensor<double, 1> gt_values = gt_values_view;
|
||||
xt::xtensor<double, 1> gt_values_reduced = xt::empty_like(gt_values);
|
||||
// Copy VALUE column into contiguous array for MPI reduction
|
||||
tensor::Tensor<double> gt_values(gt.slice(tensor::all, val_col));
|
||||
tensor::Tensor<double> gt_values_reduced({size_t {N_GLOBAL_TALLIES}});
|
||||
|
||||
// Reduce contiguous data
|
||||
MPI_Reduce(gt_values.data(), gt_values_reduced.data(), N_GLOBAL_TALLIES,
|
||||
|
|
@ -1043,9 +1043,9 @@ void reduce_tally_results()
|
|||
|
||||
// Transfer values on master and reset on other ranks
|
||||
if (mpi::master) {
|
||||
gt_values_view = gt_values_reduced;
|
||||
gt.slice(tensor::all, val_col) = gt_values_reduced;
|
||||
} else {
|
||||
gt_values_view = 0.0;
|
||||
gt.slice(tensor::all, val_col) = 0.0;
|
||||
}
|
||||
|
||||
// We also need to determine the total starting weight of particles from the
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "openmc/tallies/filter_delayedgroup.h"
|
||||
#include "openmc/tallies/filter_energy.h"
|
||||
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
|
||||
namespace openmc {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ void check_tally_triggers(double& ratio, int& tally_id, int& score)
|
|||
continue;
|
||||
|
||||
const auto& results = t.results_;
|
||||
for (auto filter_index = 0; filter_index < results.shape()[0];
|
||||
for (auto filter_index = 0; filter_index < results.shape(0);
|
||||
++filter_index) {
|
||||
// Compute the tally uncertainty metrics.
|
||||
auto uncert_pair =
|
||||
|
|
|
|||
|
|
@ -3,12 +3,7 @@
|
|||
#include <algorithm> // for sort, move, min, max, find
|
||||
#include <cmath> // for round, sqrt, abs
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "xtensor/xsort.hpp"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/constants.h"
|
||||
|
|
@ -55,7 +50,7 @@ ThermalScattering::ThermalScattering(
|
|||
// Determine temperatures available
|
||||
auto dset_names = dataset_names(kT_group);
|
||||
auto n = dset_names.size();
|
||||
auto temps_available = xt::empty<double>({n});
|
||||
auto temps_available = tensor::Tensor<double>({n});
|
||||
for (int i = 0; i < dset_names.size(); ++i) {
|
||||
// Read temperature value
|
||||
double T;
|
||||
|
|
@ -82,7 +77,7 @@ ThermalScattering::ThermalScattering(
|
|||
// Determine actual temperatures to read
|
||||
for (const auto& T : temperature) {
|
||||
|
||||
auto i_closest = xt::argmin(xt::abs(temps_available - T))[0];
|
||||
auto i_closest = tensor::abs(temps_available - T).argmin();
|
||||
auto temp_actual = temps_available[i_closest];
|
||||
if (std::abs(temp_actual - T) < settings::temperature_tolerance) {
|
||||
if (std::find(temps_to_read.begin(), temps_to_read.end(),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "openmc/simulation.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
#include <hdf5.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ UrrData::UrrData(hid_t group_id)
|
|||
// Read URR tables. The HDF5 format is a little
|
||||
// different from how we want it laid out in memory.
|
||||
// This array used to be called "prob_".
|
||||
xt::xtensor<double, 3> tmp_prob;
|
||||
tensor::Tensor<double> tmp_prob;
|
||||
read_dataset(group_id, "table", tmp_prob);
|
||||
auto shape = tmp_prob.shape();
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ UrrData::UrrData(hid_t group_id)
|
|||
xs_values_.resize({n_energy, n_cdf_values});
|
||||
|
||||
// Now fill in the values. Using manual loops here since we might
|
||||
// not have fancy xtensor slicing code written for GPU tensors.
|
||||
// not have fancy tensor slicing code written for GPU tensors.
|
||||
// The below enum gives how URR tables are laid out in our HDF5 tables.
|
||||
enum class URRTableParam {
|
||||
CUM_PROB,
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
#include "openmc/timer.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <algorithm> // for copy
|
||||
|
|
@ -242,7 +241,8 @@ vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
// non-zero
|
||||
auto n_nuc =
|
||||
settings::run_CE ? data::nuclides.size() : data::mg.nuclides_.size();
|
||||
xt::xtensor<double, 2> atoms({n_nuc, 2}, 0.0);
|
||||
auto atoms =
|
||||
tensor::zeros<double>({static_cast<size_t>(n_nuc), size_t {2}});
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
if (mpi::master) {
|
||||
|
|
@ -452,9 +452,11 @@ void VolumeCalculation::to_hdf5(
|
|||
}
|
||||
|
||||
// Create array of total # of atoms with uncertainty for each nuclide
|
||||
xt::xtensor<double, 2> atom_data({n_nuc, 2});
|
||||
xt::view(atom_data, xt::all(), 0) = xt::adapt(result.atoms);
|
||||
xt::view(atom_data, xt::all(), 1) = xt::adapt(result.uncertainty);
|
||||
tensor::Tensor<double> atom_data({static_cast<size_t>(n_nuc), size_t {2}});
|
||||
for (size_t k = 0; k < static_cast<size_t>(n_nuc); ++k) {
|
||||
atom_data(k, 0) = result.atoms[k];
|
||||
atom_data(k, 1) = result.uncertainty[k];
|
||||
}
|
||||
|
||||
// Write results
|
||||
write_dataset(group_id, "nuclides", nucnames);
|
||||
|
|
|
|||
|
|
@ -6,12 +6,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "xtensor/xdynamic_view.hpp"
|
||||
#include "xtensor/xindex_view.hpp"
|
||||
#include "xtensor/xio.hpp"
|
||||
#include "xtensor/xmasked_view.hpp"
|
||||
#include "xtensor/xnoalias.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/file_utils.h"
|
||||
|
|
@ -265,8 +260,12 @@ WeightWindows* WeightWindows::from_hdf5(
|
|||
}
|
||||
wws->set_mesh(model::mesh_map[mesh_id]);
|
||||
|
||||
wws->lower_ww_ = xt::empty<double>(wws->bounds_size());
|
||||
wws->upper_ww_ = xt::empty<double>(wws->bounds_size());
|
||||
wws->lower_ww_ =
|
||||
tensor::Tensor<double>({static_cast<size_t>(wws->bounds_size()[0]),
|
||||
static_cast<size_t>(wws->bounds_size()[1])});
|
||||
wws->upper_ww_ =
|
||||
tensor::Tensor<double>({static_cast<size_t>(wws->bounds_size()[0]),
|
||||
static_cast<size_t>(wws->bounds_size()[1])});
|
||||
|
||||
read_dataset<double>(ww_group, "lower_ww_bounds", wws->lower_ww_);
|
||||
read_dataset<double>(ww_group, "upper_ww_bounds", wws->upper_ww_);
|
||||
|
|
@ -301,9 +300,11 @@ void WeightWindows::allocate_ww_bounds()
|
|||
"Size of weight window bounds is zero for WeightWindows {}", id());
|
||||
warning(msg);
|
||||
}
|
||||
lower_ww_ = xt::empty<double>(shape);
|
||||
lower_ww_ = tensor::Tensor<double>(
|
||||
{static_cast<size_t>(shape[0]), static_cast<size_t>(shape[1])});
|
||||
lower_ww_.fill(-1);
|
||||
upper_ww_ = xt::empty<double>(shape);
|
||||
upper_ww_ = tensor::Tensor<double>(
|
||||
{static_cast<size_t>(shape[0]), static_cast<size_t>(shape[1])});
|
||||
upper_ww_.fill(-1);
|
||||
}
|
||||
|
||||
|
|
@ -448,8 +449,8 @@ void WeightWindows::check_bounds(const T& bounds) const
|
|||
}
|
||||
}
|
||||
|
||||
void WeightWindows::set_bounds(const xt::xtensor<double, 2>& lower_bounds,
|
||||
const xt::xtensor<double, 2>& upper_bounds)
|
||||
void WeightWindows::set_bounds(const tensor::Tensor<double>& lower_bounds,
|
||||
const tensor::Tensor<double>& upper_bounds)
|
||||
{
|
||||
|
||||
this->check_bounds(lower_bounds, upper_bounds);
|
||||
|
|
@ -460,7 +461,7 @@ void WeightWindows::set_bounds(const xt::xtensor<double, 2>& lower_bounds,
|
|||
}
|
||||
|
||||
void WeightWindows::set_bounds(
|
||||
const xt::xtensor<double, 2>& lower_bounds, double ratio)
|
||||
const tensor::Tensor<double>& lower_bounds, double ratio)
|
||||
{
|
||||
this->check_bounds(lower_bounds);
|
||||
|
||||
|
|
@ -475,14 +476,16 @@ void WeightWindows::set_bounds(
|
|||
{
|
||||
check_bounds(lower_bounds, upper_bounds);
|
||||
auto shape = this->bounds_size();
|
||||
lower_ww_ = xt::empty<double>(shape);
|
||||
upper_ww_ = xt::empty<double>(shape);
|
||||
lower_ww_ = tensor::Tensor<double>(
|
||||
{static_cast<size_t>(shape[0]), static_cast<size_t>(shape[1])});
|
||||
upper_ww_ = tensor::Tensor<double>(
|
||||
{static_cast<size_t>(shape[0]), static_cast<size_t>(shape[1])});
|
||||
|
||||
// set new weight window values
|
||||
xt::view(lower_ww_, xt::all()) =
|
||||
xt::adapt(lower_bounds.data(), lower_ww_.shape());
|
||||
xt::view(upper_ww_, xt::all()) =
|
||||
xt::adapt(upper_bounds.data(), upper_ww_.shape());
|
||||
// Copy weight window values from input spans into the tensors
|
||||
std::copy(lower_bounds.data(), lower_bounds.data() + lower_ww_.size(),
|
||||
lower_ww_.data());
|
||||
std::copy(upper_bounds.data(), upper_bounds.data() + upper_ww_.size(),
|
||||
upper_ww_.data());
|
||||
}
|
||||
|
||||
void WeightWindows::set_bounds(span<const double> lower_bounds, double ratio)
|
||||
|
|
@ -490,14 +493,16 @@ void WeightWindows::set_bounds(span<const double> lower_bounds, double ratio)
|
|||
this->check_bounds(lower_bounds);
|
||||
|
||||
auto shape = this->bounds_size();
|
||||
lower_ww_ = xt::empty<double>(shape);
|
||||
upper_ww_ = xt::empty<double>(shape);
|
||||
lower_ww_ = tensor::Tensor<double>(
|
||||
{static_cast<size_t>(shape[0]), static_cast<size_t>(shape[1])});
|
||||
upper_ww_ = tensor::Tensor<double>(
|
||||
{static_cast<size_t>(shape[0]), static_cast<size_t>(shape[1])});
|
||||
|
||||
// set new weight window values
|
||||
xt::view(lower_ww_, xt::all()) =
|
||||
xt::adapt(lower_bounds.data(), lower_ww_.shape());
|
||||
xt::view(upper_ww_, xt::all()) =
|
||||
xt::adapt(lower_bounds.data(), upper_ww_.shape());
|
||||
// Copy lower bounds into both arrays, then scale upper by ratio
|
||||
std::copy(lower_bounds.data(), lower_bounds.data() + lower_ww_.size(),
|
||||
lower_ww_.data());
|
||||
std::copy(lower_bounds.data(), lower_bounds.data() + upper_ww_.size(),
|
||||
upper_ww_.data());
|
||||
upper_ww_ *= ratio;
|
||||
}
|
||||
|
||||
|
|
@ -510,8 +515,8 @@ void WeightWindows::update_weights(const Tally* tally, const std::string& value,
|
|||
this->check_tally_update_compatibility(tally);
|
||||
|
||||
// Dimensions of weight window arrays
|
||||
int e_bins = lower_ww_.shape()[0];
|
||||
int64_t mesh_bins = lower_ww_.shape()[1];
|
||||
int e_bins = lower_ww_.shape(0);
|
||||
int64_t mesh_bins = lower_ww_.shape(1);
|
||||
|
||||
// Initialize weight window arrays to -1.0 by default
|
||||
#pragma omp parallel for collapse(2) schedule(static)
|
||||
|
|
@ -542,16 +547,16 @@ void WeightWindows::update_weights(const Tally* tally, const std::string& value,
|
|||
///////////////////////////
|
||||
// Extract tally data
|
||||
//
|
||||
// At the end of this section, the mean and rel_err array
|
||||
// is a 2D view of tally data (n_e_groups, n_mesh_bins)
|
||||
// At the end of this section, mean and rel_err are
|
||||
// 2D tensors of tally data (n_e_groups, n_mesh_bins)
|
||||
//
|
||||
///////////////////////////
|
||||
|
||||
// build a shape for a view of the tally results, this will always be
|
||||
// build a shape for the tally results, this will always be
|
||||
// dimension 5 (3 filter dimensions, 1 score dimension, 1 results dimension)
|
||||
// Look for the size of the last dimension of the results array
|
||||
const auto& results_arr = tally->results();
|
||||
const int results_dim = static_cast<int>(results_arr.shape()[2]);
|
||||
// Look for the size of the last dimension of the results tensor
|
||||
const auto& results = tally->results();
|
||||
const int results_dim = static_cast<int>(results.shape(2));
|
||||
std::array<int, 5> shape = {1, 1, 1, tally->n_scores(), results_dim};
|
||||
|
||||
// set the shape for the filters applied on the tally
|
||||
|
|
@ -588,25 +593,14 @@ void WeightWindows::update_weights(const Tally* tally, const std::string& value,
|
|||
std::find(filter_types.begin(), filter_types.end(), FilterType::MESH) -
|
||||
filter_types.begin();
|
||||
|
||||
// get a fully reshaped view of the tally according to tally ordering of
|
||||
// filters
|
||||
auto tally_values = xt::reshape_view(results_arr, shape);
|
||||
|
||||
// get a that is (particle, energy, mesh, scores, values)
|
||||
auto transposed_view = xt::transpose(tally_values, transpose);
|
||||
|
||||
// determine the dimension and index of the particle data
|
||||
// determine the index of the particle within its filter
|
||||
int particle_idx = 0;
|
||||
if (tally->has_filter(FilterType::PARTICLE)) {
|
||||
// get the particle filter
|
||||
auto pf = tally->get_filter<ParticleFilter>();
|
||||
const auto& particles = pf->particles();
|
||||
|
||||
// find the index of the particle that matches these weight windows
|
||||
auto p_it =
|
||||
std::find(particles.begin(), particles.end(), this->particle_type_);
|
||||
// if the particle filter doesn't have particle data for the particle
|
||||
// used on this weight windows instance, report an error
|
||||
if (p_it == particles.end()) {
|
||||
auto msg = fmt::format("Particle type '{}' not present on Filter {} for "
|
||||
"Tally {} used to update WeightWindows {}",
|
||||
|
|
@ -614,17 +608,46 @@ void WeightWindows::update_weights(const Tally* tally, const std::string& value,
|
|||
fatal_error(msg);
|
||||
}
|
||||
|
||||
// use the index of the particle in the filter to down-select data later
|
||||
particle_idx = p_it - particles.begin();
|
||||
}
|
||||
|
||||
// down-select data based on particle and score
|
||||
auto sum = xt::dynamic_view(
|
||||
transposed_view, {particle_idx, xt::all(), xt::all(), score_index,
|
||||
static_cast<int>(TallyResult::SUM)});
|
||||
auto sum_sq = xt::dynamic_view(
|
||||
transposed_view, {particle_idx, xt::all(), xt::all(), score_index,
|
||||
static_cast<int>(TallyResult::SUM_SQ)});
|
||||
// The tally results array is 3D: (n_filter_combos, n_scores, n_result_types).
|
||||
// The first dimension is a row-major flattening of up to 3 filter dimensions
|
||||
// (particle, energy, mesh) whose storage order depends on which filters the
|
||||
// tally has. We need to map our desired indices (particle, energy, mesh)
|
||||
// into the correct flat filter combination index.
|
||||
//
|
||||
// transpose[i] tells us which storage position holds dimension i:
|
||||
// i=0 -> particle, i=1 -> energy, i=2 -> mesh
|
||||
// shape[j] gives the number of bins for filter storage position j.
|
||||
|
||||
// Row-major strides for the 3 filter dimensions
|
||||
const int stride0 = shape[1] * shape[2];
|
||||
const int stride1 = shape[2];
|
||||
|
||||
tensor::Tensor<double> sum(
|
||||
{static_cast<size_t>(e_bins), static_cast<size_t>(mesh_bins)});
|
||||
tensor::Tensor<double> sum_sq(
|
||||
{static_cast<size_t>(e_bins), static_cast<size_t>(mesh_bins)});
|
||||
|
||||
const int i_sum = static_cast<int>(TallyResult::SUM);
|
||||
const int i_sum_sq = static_cast<int>(TallyResult::SUM_SQ);
|
||||
|
||||
for (int e = 0; e < e_bins; e++) {
|
||||
for (int64_t m = 0; m < mesh_bins; m++) {
|
||||
// Place particle, energy, and mesh indices into their storage positions
|
||||
std::array<int, 3> idx = {0, 0, 0};
|
||||
idx[transpose[0]] = particle_idx;
|
||||
idx[transpose[1]] = e;
|
||||
idx[transpose[2]] = static_cast<int>(m);
|
||||
|
||||
// Compute flat filter combination index (row-major over filter dims)
|
||||
int flat = idx[0] * stride0 + idx[1] * stride1 + idx[2];
|
||||
|
||||
sum(e, m) = results(flat, score_index, i_sum);
|
||||
sum_sq(e, m) = results(flat, score_index, i_sum_sq);
|
||||
}
|
||||
}
|
||||
int n = tally->n_realizations_;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
|
@ -1155,7 +1178,8 @@ extern "C" int openmc_weight_windows_set_bounds(int32_t index,
|
|||
return err;
|
||||
|
||||
const auto& wws = variance_reduction::weight_windows[index];
|
||||
wws->set_bounds({lower_bounds, size}, {upper_bounds, size});
|
||||
wws->set_bounds(span<const double>(lower_bounds, size),
|
||||
span<const double>(upper_bounds, size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
14
src/wmp.cpp
14
src/wmp.cpp
|
|
@ -33,22 +33,22 @@ WindowedMultipole::WindowedMultipole(hid_t group)
|
|||
// Read the "data" array. Use its shape to figure out the number of poles
|
||||
// and residue types in this data.
|
||||
read_dataset(group, "data", data_);
|
||||
int n_residues = data_.shape()[1] - 1;
|
||||
int n_residues = data_.shape(1) - 1;
|
||||
|
||||
// Check to see if this data includes fission residues.
|
||||
fissionable_ = (n_residues == 3);
|
||||
|
||||
// Read the "windows" array and use its shape to figure out the number of
|
||||
// windows.
|
||||
xt::xtensor<int, 2> windows;
|
||||
tensor::Tensor<int> windows;
|
||||
read_dataset(group, "windows", windows);
|
||||
int n_windows = windows.shape()[0];
|
||||
int n_windows = windows.shape(0);
|
||||
windows -= 1; // Adjust to 0-based indices
|
||||
|
||||
// Read the "broaden_poly" arrays.
|
||||
xt::xtensor<bool, 1> broaden_poly;
|
||||
tensor::Tensor<bool> broaden_poly;
|
||||
read_dataset(group, "broaden_poly", broaden_poly);
|
||||
if (n_windows != broaden_poly.shape()[0]) {
|
||||
if (n_windows != broaden_poly.shape(0)) {
|
||||
fatal_error("broaden_poly array shape is not consistent with the windows "
|
||||
"array shape in WMP library for " +
|
||||
name_ + ".");
|
||||
|
|
@ -56,12 +56,12 @@ WindowedMultipole::WindowedMultipole(hid_t group)
|
|||
|
||||
// Read the "curvefit" array.
|
||||
read_dataset(group, "curvefit", curvefit_);
|
||||
if (n_windows != curvefit_.shape()[0]) {
|
||||
if (n_windows != curvefit_.shape(0)) {
|
||||
fatal_error("curvefit array shape is not consistent with the windows "
|
||||
"array shape in WMP library for " +
|
||||
name_ + ".");
|
||||
}
|
||||
fit_order_ = curvefit_.shape()[1] - 1;
|
||||
fit_order_ = curvefit_.shape(1) - 1;
|
||||
|
||||
// Check the code is compiling to work with sufficiently high fit order
|
||||
if (fit_order_ + 1 > MAX_POLY_COEFFICIENTS) {
|
||||
|
|
|
|||
459
src/xsdata.cpp
459
src/xsdata.cpp
|
|
@ -5,10 +5,7 @@
|
|||
#include <cstdlib>
|
||||
#include <numeric>
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xindex_view.hpp"
|
||||
#include "xtensor/xmath.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -37,32 +34,32 @@ XsData::XsData(bool fissionable, AngleDistributionType scatter_format,
|
|||
}
|
||||
// allocate all [temperature][angle][in group] quantities
|
||||
vector<size_t> shape {n_ang, n_g_};
|
||||
total = xt::zeros<double>(shape);
|
||||
absorption = xt::zeros<double>(shape);
|
||||
inverse_velocity = xt::zeros<double>(shape);
|
||||
total = tensor::zeros<double>(shape);
|
||||
absorption = tensor::zeros<double>(shape);
|
||||
inverse_velocity = tensor::zeros<double>(shape);
|
||||
if (fissionable) {
|
||||
fission = xt::zeros<double>(shape);
|
||||
nu_fission = xt::zeros<double>(shape);
|
||||
prompt_nu_fission = xt::zeros<double>(shape);
|
||||
kappa_fission = xt::zeros<double>(shape);
|
||||
fission = tensor::zeros<double>(shape);
|
||||
nu_fission = tensor::zeros<double>(shape);
|
||||
prompt_nu_fission = tensor::zeros<double>(shape);
|
||||
kappa_fission = tensor::zeros<double>(shape);
|
||||
}
|
||||
|
||||
// allocate decay_rate; [temperature][angle][delayed group]
|
||||
shape[1] = n_dg_;
|
||||
decay_rate = xt::zeros<double>(shape);
|
||||
decay_rate = tensor::zeros<double>(shape);
|
||||
|
||||
if (fissionable) {
|
||||
shape = {n_ang, n_dg_, n_g_};
|
||||
// allocate delayed_nu_fission; [temperature][angle][delay group][in group]
|
||||
delayed_nu_fission = xt::zeros<double>(shape);
|
||||
delayed_nu_fission = tensor::zeros<double>(shape);
|
||||
|
||||
// chi_prompt; [temperature][angle][in group][out group]
|
||||
shape = {n_ang, n_g_, n_g_};
|
||||
chi_prompt = xt::zeros<double>(shape);
|
||||
chi_prompt = tensor::zeros<double>(shape);
|
||||
|
||||
// chi_delayed; [temperature][angle][delay group][in group][out group]
|
||||
shape = {n_ang, n_dg_, n_g_, n_g_};
|
||||
chi_delayed = xt::zeros<double>(shape);
|
||||
chi_delayed = tensor::zeros<double>(shape);
|
||||
}
|
||||
|
||||
for (int a = 0; a < n_ang; a++) {
|
||||
|
|
@ -85,28 +82,30 @@ void XsData::from_hdf5(hid_t xsdata_grp, bool fissionable,
|
|||
{
|
||||
// Reconstruct the dimension information so it doesn't need to be passed
|
||||
size_t n_ang = n_pol * n_azi;
|
||||
size_t energy_groups = total.shape()[1];
|
||||
size_t energy_groups = total.shape(1);
|
||||
|
||||
// Set the fissionable-specific data
|
||||
if (fissionable) {
|
||||
fission_from_hdf5(xsdata_grp, n_ang, is_isotropic);
|
||||
}
|
||||
// Get the non-fission-specific data
|
||||
read_nd_vector(xsdata_grp, "decay-rate", decay_rate);
|
||||
read_nd_vector(xsdata_grp, "absorption", absorption, true);
|
||||
read_nd_vector(xsdata_grp, "inverse-velocity", inverse_velocity);
|
||||
read_nd_tensor(xsdata_grp, "decay-rate", decay_rate);
|
||||
read_nd_tensor(xsdata_grp, "absorption", absorption, true);
|
||||
read_nd_tensor(xsdata_grp, "inverse-velocity", inverse_velocity);
|
||||
|
||||
// Get scattering data
|
||||
scatter_from_hdf5(
|
||||
xsdata_grp, n_ang, scatter_format, final_scatter_format, order_data);
|
||||
|
||||
// Check absorption to ensure it is not 0 since it is often the
|
||||
// denominator in tally methods
|
||||
xt::filtration(absorption, xt::equal(absorption, 0.)) = 1.e-10;
|
||||
// Replace zero absorption values with a small number to avoid
|
||||
// division by zero in tally methods
|
||||
for (size_t i = 0; i < absorption.size(); i++)
|
||||
if (absorption.data()[i] == 0.0)
|
||||
absorption.data()[i] = 1.e-10;
|
||||
|
||||
// Get or calculate the total x/s
|
||||
if (object_exists(xsdata_grp, "total")) {
|
||||
read_nd_vector(xsdata_grp, "total", total);
|
||||
read_nd_tensor(xsdata_grp, "total", total);
|
||||
} else {
|
||||
for (size_t a = 0; a < n_ang; a++) {
|
||||
for (size_t gin = 0; gin < energy_groups; gin++) {
|
||||
|
|
@ -115,8 +114,11 @@ void XsData::from_hdf5(hid_t xsdata_grp, bool fissionable,
|
|||
}
|
||||
}
|
||||
|
||||
// Fix if total is 0, since it is in the denominator when tallying
|
||||
xt::filtration(total, xt::equal(total, 0.)) = 1.e-10;
|
||||
// Replace zero total cross sections with a small number to avoid
|
||||
// division by zero in tally methods
|
||||
for (size_t i = 0; i < total.size(); i++)
|
||||
if (total.data()[i] == 0.0)
|
||||
total.data()[i] = 1.e-10;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -127,21 +129,30 @@ void XsData::fission_vector_beta_from_hdf5(
|
|||
// Data is provided as nu-fission and chi with a beta for delayed info
|
||||
|
||||
// Get chi
|
||||
xt::xtensor<double, 2> temp_chi({n_ang, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "chi", temp_chi, true);
|
||||
tensor::Tensor<double> temp_chi = tensor::zeros<double>({n_ang, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "chi", temp_chi, true);
|
||||
|
||||
// Normalize chi by summing over the outgoing groups for each incoming angle
|
||||
temp_chi /= xt::view(xt::sum(temp_chi, {1}), xt::all(), xt::newaxis());
|
||||
// Normalize chi so it sums to 1 over outgoing groups for each angle
|
||||
for (size_t a = 0; a < n_ang; a++) {
|
||||
tensor::View<double> row = temp_chi.slice(a);
|
||||
row /= row.sum();
|
||||
}
|
||||
|
||||
// Now every incoming group in prompt_chi and delayed_chi is the normalized
|
||||
// chi we just made
|
||||
chi_prompt = xt::view(temp_chi, xt::all(), xt::newaxis(), xt::all());
|
||||
chi_delayed =
|
||||
xt::view(temp_chi, xt::all(), xt::newaxis(), xt::newaxis(), xt::all());
|
||||
// Replicate the energy spectrum across all incoming groups — the
|
||||
// spectrum is independent of the incoming neutron energy
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
chi_prompt.slice(a, gin) = temp_chi.slice(a);
|
||||
|
||||
// Same spectrum for delayed neutrons, replicated across delayed groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
chi_delayed.slice(a, d, gin) = temp_chi.slice(a);
|
||||
|
||||
// Get nu-fission
|
||||
xt::xtensor<double, 2> temp_nufiss({n_ang, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "nu-fission", temp_nufiss, true);
|
||||
tensor::Tensor<double> temp_nufiss = tensor::zeros<double>({n_ang, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "nu-fission", temp_nufiss, true);
|
||||
|
||||
// Get beta (strategy will depend upon the number of dimensions in beta)
|
||||
hid_t beta_dset = open_dataset(xsdata_grp, "beta");
|
||||
|
|
@ -151,26 +162,39 @@ void XsData::fission_vector_beta_from_hdf5(
|
|||
if (!is_isotropic)
|
||||
ndim_target += 2;
|
||||
if (beta_ndims == ndim_target) {
|
||||
xt::xtensor<double, 2> temp_beta({n_ang, n_dg_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "beta", temp_beta, true);
|
||||
tensor::Tensor<double> temp_beta = tensor::zeros<double>({n_ang, n_dg_});
|
||||
read_nd_tensor(xsdata_grp, "beta", temp_beta, true);
|
||||
|
||||
// Set prompt_nu_fission = (1. - beta_total)*nu_fission
|
||||
prompt_nu_fission = temp_nufiss * (1. - xt::sum(temp_beta, {1}));
|
||||
// prompt_nu_fission = (1 - sum_of_beta) * nu_fission
|
||||
auto beta_sum = temp_beta.sum(1);
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
prompt_nu_fission(a, g) = temp_nufiss(a, g) * (1.0 - beta_sum(a));
|
||||
|
||||
// Set delayed_nu_fission as beta * nu_fission
|
||||
delayed_nu_fission =
|
||||
xt::view(temp_beta, xt::all(), xt::all(), xt::newaxis()) *
|
||||
xt::view(temp_nufiss, xt::all(), xt::newaxis(), xt::all());
|
||||
// Delayed nu-fission is the outer product of the delayed neutron
|
||||
// fraction (beta) and the fission production rate (nu-fission)
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
delayed_nu_fission(a, d, g) = temp_beta(a, d) * temp_nufiss(a, g);
|
||||
} else if (beta_ndims == ndim_target + 1) {
|
||||
xt::xtensor<double, 3> temp_beta({n_ang, n_dg_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "beta", temp_beta, true);
|
||||
tensor::Tensor<double> temp_beta =
|
||||
tensor::zeros<double>({n_ang, n_dg_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "beta", temp_beta, true);
|
||||
|
||||
// Set prompt_nu_fission = (1. - beta_total)*nu_fission
|
||||
prompt_nu_fission = temp_nufiss * (1. - xt::sum(temp_beta, {1}));
|
||||
// prompt_nu_fission = (1 - sum_of_beta) * nu_fission
|
||||
// Here beta is energy-dependent, so sum over delayed groups (axis 1)
|
||||
auto beta_sum = temp_beta.sum(1);
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
prompt_nu_fission(a, g) = temp_nufiss(a, g) * (1.0 - beta_sum(a, g));
|
||||
|
||||
// Set delayed_nu_fission as beta * nu_fission
|
||||
delayed_nu_fission =
|
||||
temp_beta * xt::view(temp_nufiss, xt::all(), xt::newaxis(), xt::all());
|
||||
// Delayed nu-fission: beta is already energy-dependent [n_ang, n_dg, n_g],
|
||||
// so scale each delayed group's beta by the total nu-fission for that group
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
delayed_nu_fission(a, d, g) = temp_beta(a, d, g) * temp_nufiss(a, g);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,29 +203,42 @@ void XsData::fission_vector_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
|||
// Data is provided separately as prompt + delayed nu-fission and chi
|
||||
|
||||
// Get chi-prompt
|
||||
xt::xtensor<double, 2> temp_chi_p({n_ang, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "chi-prompt", temp_chi_p, true);
|
||||
tensor::Tensor<double> temp_chi_p = tensor::zeros<double>({n_ang, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "chi-prompt", temp_chi_p, true);
|
||||
|
||||
// Normalize chi by summing over the outgoing groups for each incoming angle
|
||||
temp_chi_p /= xt::view(xt::sum(temp_chi_p, {1}), xt::all(), xt::newaxis());
|
||||
// Normalize prompt chi so it sums to 1 over outgoing groups for each angle
|
||||
for (size_t a = 0; a < n_ang; a++) {
|
||||
tensor::View<double> row = temp_chi_p.slice(a);
|
||||
row /= row.sum();
|
||||
}
|
||||
|
||||
// Get chi-delayed
|
||||
xt::xtensor<double, 3> temp_chi_d({n_ang, n_dg_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "chi-delayed", temp_chi_d, true);
|
||||
tensor::Tensor<double> temp_chi_d =
|
||||
tensor::zeros<double>({n_ang, n_dg_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "chi-delayed", temp_chi_d, true);
|
||||
|
||||
// Normalize chi by summing over the outgoing groups for each incoming angle
|
||||
temp_chi_d /=
|
||||
xt::view(xt::sum(temp_chi_d, {2}), xt::all(), xt::all(), xt::newaxis());
|
||||
// Normalize delayed chi so it sums to 1 over outgoing groups for each
|
||||
// angle and delayed group
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++) {
|
||||
tensor::View<double> row = temp_chi_d.slice(a, d);
|
||||
row /= row.sum();
|
||||
}
|
||||
|
||||
// Now assign the prompt and delayed chis by replicating for each incoming
|
||||
// group
|
||||
chi_prompt = xt::view(temp_chi_p, xt::all(), xt::newaxis(), xt::all());
|
||||
chi_delayed =
|
||||
xt::view(temp_chi_d, xt::all(), xt::all(), xt::newaxis(), xt::all());
|
||||
// Replicate the prompt spectrum across all incoming groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
chi_prompt.slice(a, gin) = temp_chi_p.slice(a);
|
||||
|
||||
// Replicate the delayed spectrum across all incoming groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
chi_delayed.slice(a, d, gin) = temp_chi_d.slice(a, d);
|
||||
|
||||
// Get prompt and delayed nu-fission directly
|
||||
read_nd_vector(xsdata_grp, "prompt-nu-fission", prompt_nu_fission, true);
|
||||
read_nd_vector(xsdata_grp, "delayed-nu-fission", delayed_nu_fission, true);
|
||||
read_nd_tensor(xsdata_grp, "prompt-nu-fission", prompt_nu_fission, true);
|
||||
read_nd_tensor(xsdata_grp, "delayed-nu-fission", delayed_nu_fission, true);
|
||||
}
|
||||
|
||||
void XsData::fission_vector_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
||||
|
|
@ -210,17 +247,22 @@ void XsData::fission_vector_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
|||
// Therefore, the code only considers the data as prompt.
|
||||
|
||||
// Get chi
|
||||
xt::xtensor<double, 2> temp_chi({n_ang, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "chi", temp_chi, true);
|
||||
tensor::Tensor<double> temp_chi = tensor::zeros<double>({n_ang, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "chi", temp_chi, true);
|
||||
|
||||
// Normalize chi by summing over the outgoing groups for each incoming angle
|
||||
temp_chi /= xt::view(xt::sum(temp_chi, {1}), xt::all(), xt::newaxis());
|
||||
// Normalize chi so it sums to 1 over outgoing groups for each angle
|
||||
for (size_t a = 0; a < n_ang; a++) {
|
||||
tensor::View<double> row = temp_chi.slice(a);
|
||||
row /= row.sum();
|
||||
}
|
||||
|
||||
// Now every incoming group in self.chi is the normalized chi we just made
|
||||
chi_prompt = xt::view(temp_chi, xt::all(), xt::newaxis(), xt::all());
|
||||
// Replicate the energy spectrum across all incoming groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
chi_prompt.slice(a, gin) = temp_chi.slice(a);
|
||||
|
||||
// Get nu-fission directly
|
||||
read_nd_vector(xsdata_grp, "nu-fission", prompt_nu_fission, true);
|
||||
read_nd_tensor(xsdata_grp, "nu-fission", prompt_nu_fission, true);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -231,8 +273,9 @@ void XsData::fission_matrix_beta_from_hdf5(
|
|||
// Data is provided as nu-fission and chi with a beta for delayed info
|
||||
|
||||
// Get nu-fission matrix
|
||||
xt::xtensor<double, 3> temp_matrix({n_ang, n_g_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "nu-fission", temp_matrix, true);
|
||||
tensor::Tensor<double> temp_matrix =
|
||||
tensor::zeros<double>({n_ang, n_g_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "nu-fission", temp_matrix, true);
|
||||
|
||||
// Get beta (strategy will depend upon the number of dimensions in beta)
|
||||
hid_t beta_dset = open_dataset(xsdata_grp, "beta");
|
||||
|
|
@ -242,65 +285,92 @@ void XsData::fission_matrix_beta_from_hdf5(
|
|||
if (!is_isotropic)
|
||||
ndim_target += 2;
|
||||
if (beta_ndims == ndim_target) {
|
||||
xt::xtensor<double, 2> temp_beta({n_ang, n_dg_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "beta", temp_beta, true);
|
||||
tensor::Tensor<double> temp_beta = tensor::zeros<double>({n_ang, n_dg_});
|
||||
read_nd_tensor(xsdata_grp, "beta", temp_beta, true);
|
||||
|
||||
xt::xtensor<double, 1> temp_beta_sum({n_ang}, 0.);
|
||||
temp_beta_sum = xt::sum(temp_beta, {1});
|
||||
auto beta_sum = temp_beta.sum(1);
|
||||
auto matrix_gout_sum = temp_matrix.sum(2);
|
||||
|
||||
// prompt_nu_fission is the sum of this matrix over outgoing groups and
|
||||
// multiplied by (1 - beta_sum)
|
||||
prompt_nu_fission = xt::sum(temp_matrix, {2}) * (1. - temp_beta_sum);
|
||||
// prompt_nu_fission = sum_gout(matrix) * (1 - beta_total)
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
prompt_nu_fission(a, g) = matrix_gout_sum(a, g) * (1.0 - beta_sum(a));
|
||||
|
||||
// Store chi-prompt
|
||||
chi_prompt =
|
||||
xt::view(1.0 - temp_beta_sum, xt::all(), xt::newaxis(), xt::newaxis()) *
|
||||
temp_matrix;
|
||||
// chi_prompt = (1 - beta_total) * nu-fission matrix (unnormalized)
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_prompt(a, gin, gout) =
|
||||
(1.0 - beta_sum(a)) * temp_matrix(a, gin, gout);
|
||||
|
||||
// delayed_nu_fission is the sum of this matrix over outgoing groups and
|
||||
// multiplied by beta
|
||||
delayed_nu_fission =
|
||||
xt::view(temp_beta, xt::all(), xt::all(), xt::newaxis()) *
|
||||
xt::view(xt::sum(temp_matrix, {2}), xt::all(), xt::newaxis(), xt::all());
|
||||
// Delayed nu-fission is the outer product of the delayed neutron
|
||||
// fraction (beta) and the total fission rate summed over outgoing groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
delayed_nu_fission(a, d, g) = temp_beta(a, d) * matrix_gout_sum(a, g);
|
||||
|
||||
// Store chi-delayed
|
||||
chi_delayed =
|
||||
xt::view(temp_beta, xt::all(), xt::all(), xt::newaxis(), xt::newaxis()) *
|
||||
xt::view(temp_matrix, xt::all(), xt::newaxis(), xt::all(), xt::all());
|
||||
// chi_delayed = beta * nu-fission matrix, expanded across delayed groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_delayed(a, d, gin, gout) =
|
||||
temp_beta(a, d) * temp_matrix(a, gin, gout);
|
||||
|
||||
} else if (beta_ndims == ndim_target + 1) {
|
||||
xt::xtensor<double, 3> temp_beta({n_ang, n_dg_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "beta", temp_beta, true);
|
||||
tensor::Tensor<double> temp_beta =
|
||||
tensor::zeros<double>({n_ang, n_dg_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "beta", temp_beta, true);
|
||||
|
||||
xt::xtensor<double, 2> temp_beta_sum({n_ang, n_g_}, 0.);
|
||||
temp_beta_sum = xt::sum(temp_beta, {1});
|
||||
auto beta_sum = temp_beta.sum(1);
|
||||
auto matrix_gout_sum = temp_matrix.sum(2);
|
||||
|
||||
// prompt_nu_fission is the sum of this matrix over outgoing groups and
|
||||
// multiplied by (1 - beta_sum)
|
||||
prompt_nu_fission = xt::sum(temp_matrix, {2}) * (1. - temp_beta_sum);
|
||||
// prompt_nu_fission = sum_gout(matrix) * (1 - beta_total)
|
||||
// Here beta is energy-dependent, so beta_sum is 2D [n_ang, n_g]
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
prompt_nu_fission(a, g) =
|
||||
matrix_gout_sum(a, g) * (1.0 - beta_sum(a, g));
|
||||
|
||||
// Store chi-prompt
|
||||
chi_prompt =
|
||||
xt::view(1.0 - temp_beta_sum, xt::all(), xt::all(), xt::newaxis()) *
|
||||
temp_matrix;
|
||||
// chi_prompt = (1 - beta_sum) * nu-fission matrix (unnormalized)
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_prompt(a, gin, gout) =
|
||||
(1.0 - beta_sum(a, gin)) * temp_matrix(a, gin, gout);
|
||||
|
||||
// delayed_nu_fission is the sum of this matrix over outgoing groups and
|
||||
// multiplied by beta
|
||||
delayed_nu_fission = temp_beta * xt::view(xt::sum(temp_matrix, {2}),
|
||||
xt::all(), xt::newaxis(), xt::all());
|
||||
// Delayed nu-fission: beta is energy-dependent [n_ang, n_dg, n_g],
|
||||
// scale by total fission rate summed over outgoing groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t g = 0; g < n_g_; g++)
|
||||
delayed_nu_fission(a, d, g) =
|
||||
temp_beta(a, d, g) * matrix_gout_sum(a, g);
|
||||
|
||||
// Store chi-delayed
|
||||
chi_delayed =
|
||||
xt::view(temp_beta, xt::all(), xt::all(), xt::all(), xt::newaxis()) *
|
||||
xt::view(temp_matrix, xt::all(), xt::newaxis(), xt::all(), xt::all());
|
||||
// chi_delayed = beta * nu-fission matrix, expanded across delayed groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_delayed(a, d, gin, gout) =
|
||||
temp_beta(a, d, gin) * temp_matrix(a, gin, gout);
|
||||
}
|
||||
|
||||
// Normalize both chis
|
||||
chi_prompt /=
|
||||
xt::view(xt::sum(chi_prompt, {2}), xt::all(), xt::all(), xt::newaxis());
|
||||
// Normalize chi_prompt so it sums to 1 over outgoing groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++) {
|
||||
tensor::View<double> row = chi_prompt.slice(a, gin);
|
||||
row /= row.sum();
|
||||
}
|
||||
|
||||
chi_delayed /= xt::view(
|
||||
xt::sum(chi_delayed, {3}), xt::all(), xt::all(), xt::all(), xt::newaxis());
|
||||
// Normalize chi_delayed so it sums to 1 over outgoing groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++) {
|
||||
tensor::View<double> row = chi_delayed.slice(a, d, gin);
|
||||
row /= row.sum();
|
||||
}
|
||||
}
|
||||
|
||||
void XsData::fission_matrix_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
||||
|
|
@ -308,28 +378,36 @@ void XsData::fission_matrix_no_beta_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
|||
// Data is provided separately as prompt + delayed nu-fission and chi
|
||||
|
||||
// Get the prompt nu-fission matrix
|
||||
xt::xtensor<double, 3> temp_matrix_p({n_ang, n_g_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "prompt-nu-fission", temp_matrix_p, true);
|
||||
tensor::Tensor<double> temp_matrix_p =
|
||||
tensor::zeros<double>({n_ang, n_g_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "prompt-nu-fission", temp_matrix_p, true);
|
||||
|
||||
// prompt_nu_fission is the sum over outgoing groups
|
||||
prompt_nu_fission = xt::sum(temp_matrix_p, {2});
|
||||
prompt_nu_fission = temp_matrix_p.sum(2);
|
||||
|
||||
// chi_prompt is this matrix but normalized over outgoing groups, which we
|
||||
// have already stored in prompt_nu_fission
|
||||
chi_prompt = temp_matrix_p /
|
||||
xt::view(prompt_nu_fission, xt::all(), xt::all(), xt::newaxis());
|
||||
// chi_prompt is the nu-fission matrix normalized over outgoing groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_prompt(a, gin, gout) =
|
||||
temp_matrix_p(a, gin, gout) / prompt_nu_fission(a, gin);
|
||||
|
||||
// Get the delayed nu-fission matrix
|
||||
xt::xtensor<double, 4> temp_matrix_d({n_ang, n_dg_, n_g_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "delayed-nu-fission", temp_matrix_d, true);
|
||||
tensor::Tensor<double> temp_matrix_d =
|
||||
tensor::zeros<double>({n_ang, n_dg_, n_g_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "delayed-nu-fission", temp_matrix_d, true);
|
||||
|
||||
// delayed_nu_fission is the sum over outgoing groups
|
||||
delayed_nu_fission = xt::sum(temp_matrix_d, {3});
|
||||
delayed_nu_fission = temp_matrix_d.sum(3);
|
||||
|
||||
// chi_prompt is this matrix but normalized over outgoing groups, which we
|
||||
// have already stored in prompt_nu_fission
|
||||
chi_delayed = temp_matrix_d / xt::view(delayed_nu_fission, xt::all(),
|
||||
xt::all(), xt::all(), xt::newaxis());
|
||||
// chi_delayed is the delayed nu-fission matrix normalized over outgoing
|
||||
// groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg_; d++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_delayed(a, d, gin, gout) =
|
||||
temp_matrix_d(a, d, gin, gout) / delayed_nu_fission(a, d, gin);
|
||||
}
|
||||
|
||||
void XsData::fission_matrix_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
||||
|
|
@ -338,16 +416,19 @@ void XsData::fission_matrix_no_delayed_from_hdf5(hid_t xsdata_grp, size_t n_ang)
|
|||
// Therefore, the code only considers the data as prompt.
|
||||
|
||||
// Get nu-fission matrix
|
||||
xt::xtensor<double, 3> temp_matrix({n_ang, n_g_, n_g_}, 0.);
|
||||
read_nd_vector(xsdata_grp, "nu-fission", temp_matrix, true);
|
||||
tensor::Tensor<double> temp_matrix =
|
||||
tensor::zeros<double>({n_ang, n_g_, n_g_});
|
||||
read_nd_tensor(xsdata_grp, "nu-fission", temp_matrix, true);
|
||||
|
||||
// prompt_nu_fission is the sum over outgoing groups
|
||||
prompt_nu_fission = xt::sum(temp_matrix, {2});
|
||||
prompt_nu_fission = temp_matrix.sum(2);
|
||||
|
||||
// chi_prompt is this matrix but normalized over outgoing groups, which we
|
||||
// have already stored in prompt_nu_fission
|
||||
chi_prompt = temp_matrix /
|
||||
xt::view(prompt_nu_fission, xt::all(), xt::all(), xt::newaxis());
|
||||
// chi_prompt is the nu-fission matrix normalized over outgoing groups
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g_; gin++)
|
||||
for (size_t gout = 0; gout < n_g_; gout++)
|
||||
chi_prompt(a, gin, gout) =
|
||||
temp_matrix(a, gin, gout) / prompt_nu_fission(a, gin);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -356,8 +437,8 @@ void XsData::fission_from_hdf5(
|
|||
hid_t xsdata_grp, size_t n_ang, bool is_isotropic)
|
||||
{
|
||||
// Get the fission and kappa_fission data xs; these are optional
|
||||
read_nd_vector(xsdata_grp, "fission", fission);
|
||||
read_nd_vector(xsdata_grp, "kappa-fission", kappa_fission);
|
||||
read_nd_tensor(xsdata_grp, "fission", fission);
|
||||
read_nd_tensor(xsdata_grp, "kappa-fission", kappa_fission);
|
||||
|
||||
// Get the data; the strategy for doing so depends on if the data is provided
|
||||
// as a nu-fission matrix or a set of chi and nu-fission vectors
|
||||
|
|
@ -388,7 +469,7 @@ void XsData::fission_from_hdf5(
|
|||
if (n_dg_ == 0) {
|
||||
nu_fission = prompt_nu_fission;
|
||||
} else {
|
||||
nu_fission = prompt_nu_fission + xt::sum(delayed_nu_fission, {1});
|
||||
nu_fission = prompt_nu_fission + delayed_nu_fission.sum(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -404,10 +485,10 @@ void XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang,
|
|||
hid_t scatt_grp = open_group(xsdata_grp, "scatter_data");
|
||||
|
||||
// Get the outgoing group boundary indices
|
||||
xt::xtensor<int, 2> gmin({n_ang, n_g_}, 0.);
|
||||
read_nd_vector(scatt_grp, "g_min", gmin, true);
|
||||
xt::xtensor<int, 2> gmax({n_ang, n_g_}, 0.);
|
||||
read_nd_vector(scatt_grp, "g_max", gmax, true);
|
||||
tensor::Tensor<int> gmin = tensor::zeros<int>({n_ang, n_g_});
|
||||
read_nd_tensor(scatt_grp, "g_min", gmin, true);
|
||||
tensor::Tensor<int> gmax = tensor::zeros<int>({n_ang, n_g_});
|
||||
read_nd_tensor(scatt_grp, "g_max", gmax, true);
|
||||
|
||||
// Make gmin and gmax start from 0 vice 1 as they do in the library
|
||||
gmin -= 1;
|
||||
|
|
@ -415,11 +496,11 @@ void XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang,
|
|||
|
||||
// Now use this info to find the length of a vector to hold the flattened
|
||||
// data.
|
||||
size_t length = order_data * xt::sum(gmax - gmin + 1)();
|
||||
size_t length = order_data * (gmax - gmin + 1).sum();
|
||||
|
||||
double_4dvec input_scatt(n_ang, double_3dvec(n_g_));
|
||||
xt::xtensor<double, 1> temp_arr({length}, 0.);
|
||||
read_nd_vector(scatt_grp, "scatter_matrix", temp_arr, true);
|
||||
tensor::Tensor<double> temp_arr = tensor::zeros<double>({length});
|
||||
read_nd_tensor(scatt_grp, "scatter_matrix", temp_arr, true);
|
||||
|
||||
// Compare the number of orders given with the max order of the problem;
|
||||
// strip off the superfluous orders if needed
|
||||
|
|
@ -451,7 +532,7 @@ void XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang,
|
|||
double_3dvec temp_mult(n_ang, double_2dvec(n_g_));
|
||||
if (object_exists(scatt_grp, "multiplicity_matrix")) {
|
||||
temp_arr.resize({length / order_data});
|
||||
read_nd_vector(scatt_grp, "multiplicity_matrix", temp_arr);
|
||||
read_nd_tensor(scatt_grp, "multiplicity_matrix", temp_arr);
|
||||
|
||||
// convert the flat temp_arr to a jagged array for passing to scatt data
|
||||
size_t temp_idx = 0;
|
||||
|
|
@ -481,8 +562,8 @@ void XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang,
|
|||
final_scatter_format == AngleDistributionType::TABULAR) {
|
||||
for (size_t a = 0; a < n_ang; a++) {
|
||||
ScattDataLegendre legendre_scatt;
|
||||
xt::xtensor<int, 1> in_gmin = xt::view(gmin, a, xt::all());
|
||||
xt::xtensor<int, 1> in_gmax = xt::view(gmax, a, xt::all());
|
||||
tensor::Tensor<int> in_gmin(gmin.slice(a));
|
||||
tensor::Tensor<int> in_gmax(gmax.slice(a));
|
||||
|
||||
legendre_scatt.init(in_gmin, in_gmax, temp_mult[a], input_scatt[a]);
|
||||
|
||||
|
|
@ -496,8 +577,8 @@ void XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang,
|
|||
// We are sticking with the current representation
|
||||
// Initialize the ScattData object with this data
|
||||
for (size_t a = 0; a < n_ang; a++) {
|
||||
xt::xtensor<int, 1> in_gmin = xt::view(gmin, a, xt::all());
|
||||
xt::xtensor<int, 1> in_gmax = xt::view(gmax, a, xt::all());
|
||||
tensor::Tensor<int> in_gmin(gmin.slice(a));
|
||||
tensor::Tensor<int> in_gmax(gmax.slice(a));
|
||||
scatter[a]->init(in_gmin, in_gmax, temp_mult[a], input_scatt[a]);
|
||||
}
|
||||
}
|
||||
|
|
@ -519,33 +600,67 @@ void XsData::combine(
|
|||
if (i == 0) {
|
||||
inverse_velocity = that->inverse_velocity;
|
||||
}
|
||||
if (that->prompt_nu_fission.shape()[0] > 0) {
|
||||
if (!that->prompt_nu_fission.empty()) {
|
||||
nu_fission += scalar * that->nu_fission;
|
||||
prompt_nu_fission += scalar * that->prompt_nu_fission;
|
||||
kappa_fission += scalar * that->kappa_fission;
|
||||
fission += scalar * that->fission;
|
||||
delayed_nu_fission += scalar * that->delayed_nu_fission;
|
||||
chi_prompt += scalar *
|
||||
xt::view(xt::sum(that->prompt_nu_fission, {1}), xt::all(),
|
||||
xt::newaxis(), xt::newaxis()) *
|
||||
that->chi_prompt;
|
||||
chi_delayed += scalar *
|
||||
xt::view(xt::sum(that->delayed_nu_fission, {2}), xt::all(),
|
||||
xt::all(), xt::newaxis(), xt::newaxis()) *
|
||||
that->chi_delayed;
|
||||
// Accumulate chi_prompt weighted by total prompt nu-fission
|
||||
// (summed over energy groups) for this constituent
|
||||
{
|
||||
auto pnf_sum = that->prompt_nu_fission.sum(1);
|
||||
size_t n_ang = chi_prompt.shape(0);
|
||||
size_t n_g = chi_prompt.shape(1);
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g; gin++)
|
||||
for (size_t gout = 0; gout < n_g; gout++)
|
||||
chi_prompt(a, gin, gout) +=
|
||||
scalar * pnf_sum(a) * that->chi_prompt(a, gin, gout);
|
||||
}
|
||||
// Accumulate chi_delayed weighted by total delayed nu-fission
|
||||
// (summed over energy groups) for this constituent
|
||||
{
|
||||
auto dnf_sum = that->delayed_nu_fission.sum(2);
|
||||
size_t n_ang = chi_delayed.shape(0);
|
||||
size_t n_dg = chi_delayed.shape(1);
|
||||
size_t n_g = chi_delayed.shape(2);
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg; d++)
|
||||
for (size_t gin = 0; gin < n_g; gin++)
|
||||
for (size_t gout = 0; gout < n_g; gout++)
|
||||
chi_delayed(a, d, gin, gout) +=
|
||||
scalar * dnf_sum(a, d) * that->chi_delayed(a, d, gin, gout);
|
||||
}
|
||||
}
|
||||
decay_rate += scalar * that->decay_rate;
|
||||
}
|
||||
|
||||
// Ensure the chi_prompt and chi_delayed are normalized to 1 for each
|
||||
// azimuthal angle and delayed group (for chi_delayed)
|
||||
chi_prompt /=
|
||||
xt::view(xt::sum(chi_prompt, {2}), xt::all(), xt::all(), xt::newaxis());
|
||||
chi_delayed /= xt::view(
|
||||
xt::sum(chi_delayed, {3}), xt::all(), xt::all(), xt::all(), xt::newaxis());
|
||||
// Normalize chi_prompt so it sums to 1 over outgoing groups
|
||||
{
|
||||
size_t n_ang = chi_prompt.shape(0);
|
||||
size_t n_g = chi_prompt.shape(1);
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t gin = 0; gin < n_g; gin++) {
|
||||
tensor::View<double> row = chi_prompt.slice(a, gin);
|
||||
row /= row.sum();
|
||||
}
|
||||
}
|
||||
// Normalize chi_delayed so it sums to 1 over outgoing groups
|
||||
{
|
||||
size_t n_ang = chi_delayed.shape(0);
|
||||
size_t n_dg = chi_delayed.shape(1);
|
||||
size_t n_g = chi_delayed.shape(2);
|
||||
for (size_t a = 0; a < n_ang; a++)
|
||||
for (size_t d = 0; d < n_dg; d++)
|
||||
for (size_t gin = 0; gin < n_g; gin++) {
|
||||
tensor::View<double> row = chi_delayed.slice(a, d, gin);
|
||||
row /= row.sum();
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the ScattData object to combine itself
|
||||
for (size_t a = 0; a < total.shape()[0]; a++) {
|
||||
for (size_t a = 0; a < total.shape(0); a++) {
|
||||
// Build vector of the scattering objects to incorporate
|
||||
vector<ScattData*> those_scatts(those_xs.size());
|
||||
for (size_t i = 0; i < those_xs.size(); i++) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ set(TEST_NAMES
|
|||
test_mcpl_stat_sum
|
||||
test_mesh
|
||||
test_region
|
||||
test_tensor
|
||||
# Add additional unit test files here
|
||||
)
|
||||
|
||||
|
|
|
|||
987
tests/cpp_unit_tests/test_tensor.cpp
Normal file
987
tests/cpp_unit_tests/test_tensor.cpp
Normal file
|
|
@ -0,0 +1,987 @@
|
|||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
|
||||
#include "openmc/tensor.h"
|
||||
|
||||
using namespace openmc;
|
||||
using namespace openmc::tensor;
|
||||
|
||||
// ============================================================================
|
||||
// Tensor constructors
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor default constructor")
|
||||
{
|
||||
Tensor<double> t;
|
||||
REQUIRE(t.size() == 0);
|
||||
REQUIRE(t.empty());
|
||||
REQUIRE(t.shape().empty());
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor shape constructor")
|
||||
{
|
||||
Tensor<double> t1({5});
|
||||
REQUIRE(t1.size() == 5);
|
||||
REQUIRE(t1.shape().size() == 1);
|
||||
REQUIRE(t1.shape(0) == 5);
|
||||
|
||||
Tensor<double> t2({3, 4});
|
||||
REQUIRE(t2.size() == 12);
|
||||
REQUIRE(t2.shape().size() == 2);
|
||||
REQUIRE(t2.shape(0) == 3);
|
||||
REQUIRE(t2.shape(1) == 4);
|
||||
|
||||
Tensor<int> t3({2, 3, 4});
|
||||
REQUIRE(t3.size() == 24);
|
||||
REQUIRE(t3.shape().size() == 3);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor shape + fill constructor")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 7.0);
|
||||
REQUIRE(t.size() == 6);
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
REQUIRE(t[i] == 7.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor pointer constructor")
|
||||
{
|
||||
double vals[] = {1.0, 2.0, 3.0, 4.0};
|
||||
Tensor<double> t(vals, 4);
|
||||
REQUIRE(t.size() == 4);
|
||||
REQUIRE(t.shape(0) == 4);
|
||||
REQUIRE(t[0] == 1.0);
|
||||
REQUIRE(t[1] == 2.0);
|
||||
REQUIRE(t[2] == 3.0);
|
||||
REQUIRE(t[3] == 4.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor copy and move")
|
||||
{
|
||||
Tensor<double> a({2, 3}, 5.0);
|
||||
Tensor<double> b(a);
|
||||
REQUIRE(b.size() == 6);
|
||||
REQUIRE(b(0, 0) == 5.0);
|
||||
// Modifying copy doesn't affect original
|
||||
b(0, 0) = 99.0;
|
||||
REQUIRE(a(0, 0) == 5.0);
|
||||
|
||||
Tensor<double> c(std::move(b));
|
||||
REQUIRE(c(0, 0) == 99.0);
|
||||
REQUIRE(c.size() == 6);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor indexing
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor 1D indexing")
|
||||
{
|
||||
Tensor<int> t({4}, 0);
|
||||
t[0] = 10;
|
||||
t[1] = 20;
|
||||
t[2] = 30;
|
||||
t[3] = 40;
|
||||
REQUIRE(t(0) == 10);
|
||||
REQUIRE(t(1) == 20);
|
||||
REQUIRE(t(2) == 30);
|
||||
REQUIRE(t(3) == 40);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor 2D indexing (row-major)")
|
||||
{
|
||||
// Layout: [[1, 2, 3], [4, 5, 6]]
|
||||
Tensor<int> t({2, 3}, 0);
|
||||
int val = 1;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
t(i, j) = val++;
|
||||
|
||||
REQUIRE(t(0, 0) == 1);
|
||||
REQUIRE(t(0, 2) == 3);
|
||||
REQUIRE(t(1, 0) == 4);
|
||||
REQUIRE(t(1, 2) == 6);
|
||||
// Flat index should match row-major order
|
||||
REQUIRE(t[0] == 1);
|
||||
REQUIRE(t[3] == 4);
|
||||
REQUIRE(t[5] == 6);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor 3D indexing")
|
||||
{
|
||||
// 2x3x4 tensor
|
||||
Tensor<int> t({2, 3, 4}, 0);
|
||||
t(1, 2, 3) = 42;
|
||||
// Flat index: 1*12 + 2*4 + 3 = 23
|
||||
REQUIRE(t[23] == 42);
|
||||
REQUIRE(t(1, 2, 3) == 42);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor assignment
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor initializer_list assignment")
|
||||
{
|
||||
Tensor<double> t;
|
||||
t = {1.0, 2.0, 3.0};
|
||||
REQUIRE(t.size() == 3);
|
||||
REQUIRE(t.shape(0) == 3);
|
||||
REQUIRE(t[0] == 1.0);
|
||||
REQUIRE(t[2] == 3.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor mutation
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor resize")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 1.0);
|
||||
REQUIRE(t.size() == 6);
|
||||
t.resize({4, 5});
|
||||
REQUIRE(t.size() == 20);
|
||||
REQUIRE(t.shape(0) == 4);
|
||||
REQUIRE(t.shape(1) == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor reshape")
|
||||
{
|
||||
Tensor<int> t({12}, 0);
|
||||
for (size_t i = 0; i < 12; ++i)
|
||||
t[i] = static_cast<int>(i);
|
||||
|
||||
t.reshape({3, 4});
|
||||
REQUIRE(t.shape(0) == 3);
|
||||
REQUIRE(t.shape(1) == 4);
|
||||
REQUIRE(t.size() == 12);
|
||||
// Data unchanged, just reinterpreted
|
||||
REQUIRE(t(0, 0) == 0);
|
||||
REQUIRE(t(1, 0) == 4); // row 1, col 0 = flat index 4
|
||||
REQUIRE(t(2, 3) == 11); // row 2, col 3 = flat index 11
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor fill")
|
||||
{
|
||||
Tensor<double> t({3, 3}, 0.0);
|
||||
t.fill(42.0);
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
REQUIRE(t[i] == 42.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor iterators
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor iterators")
|
||||
{
|
||||
Tensor<int> t({4}, 0);
|
||||
t = {10, 20, 30, 40};
|
||||
int sum = 0;
|
||||
for (auto val : t)
|
||||
sum += val;
|
||||
REQUIRE(sum == 100);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor reductions
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor sum (full)")
|
||||
{
|
||||
Tensor<double> t({3}, 0.0);
|
||||
t = {1.0, 2.0, 3.0};
|
||||
REQUIRE(t.sum() == 6.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor sum (axis) on 2D")
|
||||
{
|
||||
// [[1, 2, 3],
|
||||
// [4, 5, 6]]
|
||||
Tensor<int> t({2, 3}, 0);
|
||||
int v = 1;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
t(i, j) = v++;
|
||||
|
||||
// Sum along axis 0 -> [5, 7, 9]
|
||||
Tensor<int> s0 = t.sum(0);
|
||||
REQUIRE(s0.size() == 3);
|
||||
REQUIRE(s0[0] == 5);
|
||||
REQUIRE(s0[1] == 7);
|
||||
REQUIRE(s0[2] == 9);
|
||||
|
||||
// Sum along axis 1 -> [6, 15]
|
||||
Tensor<int> s1 = t.sum(1);
|
||||
REQUIRE(s1.size() == 2);
|
||||
REQUIRE(s1[0] == 6);
|
||||
REQUIRE(s1[1] == 15);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor sum (axis) on 3D")
|
||||
{
|
||||
// 2x3x2 tensor filled with sequential values 1..12
|
||||
Tensor<int> t({2, 3, 2}, 0);
|
||||
int v = 1;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
for (size_t k = 0; k < 2; ++k)
|
||||
t(i, j, k) = v++;
|
||||
|
||||
// Sum along axis 1 (middle) -> 2x2, each sums 3 values
|
||||
// [0,0]: t(0,0,0)+t(0,1,0)+t(0,2,0) = 1+3+5 = 9
|
||||
// [0,1]: t(0,0,1)+t(0,1,1)+t(0,2,1) = 2+4+6 = 12
|
||||
// [1,0]: t(1,0,0)+t(1,1,0)+t(1,2,0) = 7+9+11 = 27
|
||||
// [1,1]: t(1,0,1)+t(1,1,1)+t(1,2,1) = 8+10+12 = 30
|
||||
Tensor<int> s = t.sum(1);
|
||||
REQUIRE(s.shape(0) == 2);
|
||||
REQUIRE(s.shape(1) == 2);
|
||||
REQUIRE(s(0, 0) == 9);
|
||||
REQUIRE(s(0, 1) == 12);
|
||||
REQUIRE(s(1, 0) == 27);
|
||||
REQUIRE(s(1, 1) == 30);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor prod")
|
||||
{
|
||||
Tensor<int> t({4}, 0);
|
||||
t = {1, 2, 3, 4};
|
||||
REQUIRE(t.prod() == 24);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor any and all")
|
||||
{
|
||||
Tensor<bool> t({4}, false);
|
||||
REQUIRE(!t.any());
|
||||
REQUIRE(!t.all());
|
||||
|
||||
// Set one element true
|
||||
t.data()[0] = true;
|
||||
REQUIRE(t.any());
|
||||
REQUIRE(!t.all());
|
||||
|
||||
// Set all true
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
t.data()[i] = true;
|
||||
REQUIRE(t.any());
|
||||
REQUIRE(t.all());
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor argmin")
|
||||
{
|
||||
Tensor<double> t({5}, 0.0);
|
||||
t = {3.0, 1.0, 4.0, 0.5, 2.0};
|
||||
REQUIRE(t.argmin() == 3);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor flip")
|
||||
{
|
||||
Tensor<int> t({5}, 0);
|
||||
t = {1, 2, 3, 4, 5};
|
||||
Tensor<int> f = t.flip(0);
|
||||
REQUIRE(f[0] == 5);
|
||||
REQUIRE(f[1] == 4);
|
||||
REQUIRE(f[2] == 3);
|
||||
REQUIRE(f[3] == 2);
|
||||
REQUIRE(f[4] == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor flip 2D")
|
||||
{
|
||||
// [[1, 2], [3, 4], [5, 6]]
|
||||
Tensor<int> t({3, 2}, 0);
|
||||
t(0, 0) = 1;
|
||||
t(0, 1) = 2;
|
||||
t(1, 0) = 3;
|
||||
t(1, 1) = 4;
|
||||
t(2, 0) = 5;
|
||||
t(2, 1) = 6;
|
||||
|
||||
// Flip axis 0 reverses rows -> [[5,6],[3,4],[1,2]]
|
||||
Tensor<int> f = t.flip(0);
|
||||
REQUIRE(f(0, 0) == 5);
|
||||
REQUIRE(f(0, 1) == 6);
|
||||
REQUIRE(f(1, 0) == 3);
|
||||
REQUIRE(f(2, 0) == 1);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor operators
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor scalar compound assignment")
|
||||
{
|
||||
Tensor<double> t({3}, 0.0);
|
||||
t = {2.0, 4.0, 6.0};
|
||||
|
||||
t += 1.0;
|
||||
REQUIRE(t[0] == 3.0);
|
||||
REQUIRE(t[1] == 5.0);
|
||||
|
||||
t -= 1.0;
|
||||
REQUIRE(t[0] == 2.0);
|
||||
|
||||
t *= 3.0;
|
||||
REQUIRE(t[0] == 6.0);
|
||||
REQUIRE(t[1] == 12.0);
|
||||
|
||||
t /= 2.0;
|
||||
REQUIRE(t[0] == 3.0);
|
||||
REQUIRE(t[1] == 6.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor element-wise arithmetic")
|
||||
{
|
||||
Tensor<double> a({3}, 0.0);
|
||||
Tensor<double> b({3}, 0.0);
|
||||
a = {1.0, 2.0, 3.0};
|
||||
b = {4.0, 5.0, 6.0};
|
||||
|
||||
Tensor<double> c = a + b;
|
||||
REQUIRE(c[0] == 5.0);
|
||||
REQUIRE(c[1] == 7.0);
|
||||
REQUIRE(c[2] == 9.0);
|
||||
|
||||
c = a - b;
|
||||
REQUIRE(c[0] == -3.0);
|
||||
|
||||
c = a / b;
|
||||
REQUIRE(c[0] == 0.25);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor scalar arithmetic")
|
||||
{
|
||||
Tensor<double> a({3}, 0.0);
|
||||
a = {1.0, 2.0, 3.0};
|
||||
|
||||
Tensor<double> b = a + 10.0;
|
||||
REQUIRE(b[0] == 11.0);
|
||||
REQUIRE(b[2] == 13.0);
|
||||
|
||||
b = a - 1.0;
|
||||
REQUIRE(b[0] == 0.0);
|
||||
|
||||
b = a * 2.0;
|
||||
REQUIRE(b[0] == 2.0);
|
||||
REQUIRE(b[2] == 6.0);
|
||||
|
||||
// Non-member scalar * tensor (commutativity)
|
||||
b = 2.0 * a;
|
||||
REQUIRE(b[0] == 2.0);
|
||||
REQUIRE(b[2] == 6.0);
|
||||
|
||||
// Non-member scalar + tensor
|
||||
b = 10.0 + a;
|
||||
REQUIRE(b[0] == 11.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor compound addition with tensor")
|
||||
{
|
||||
Tensor<double> a({3}, 0.0);
|
||||
Tensor<double> b({3}, 0.0);
|
||||
a = {1.0, 2.0, 3.0};
|
||||
b = {10.0, 20.0, 30.0};
|
||||
a += b;
|
||||
REQUIRE(a[0] == 11.0);
|
||||
REQUIRE(a[1] == 22.0);
|
||||
REQUIRE(a[2] == 33.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor comparison operators")
|
||||
{
|
||||
Tensor<double> t({4}, 0.0);
|
||||
t = {1.0, 2.0, 3.0, 4.0};
|
||||
|
||||
Tensor<bool> r = t < 3.0;
|
||||
REQUIRE(r.data()[0] == true);
|
||||
REQUIRE(r.data()[1] == true);
|
||||
REQUIRE(r.data()[2] == false);
|
||||
REQUIRE(r.data()[3] == false);
|
||||
|
||||
r = t >= 3.0;
|
||||
REQUIRE(r.data()[0] == false);
|
||||
REQUIRE(r.data()[2] == true);
|
||||
REQUIRE(r.data()[3] == true);
|
||||
|
||||
r = t <= 2.0;
|
||||
REQUIRE(r.data()[0] == true);
|
||||
REQUIRE(r.data()[1] == true);
|
||||
REQUIRE(r.data()[2] == false);
|
||||
|
||||
r = t > 3.0;
|
||||
REQUIRE(r.data()[0] == false);
|
||||
REQUIRE(r.data()[3] == true);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor element-wise comparison")
|
||||
{
|
||||
Tensor<double> a({3}, 0.0);
|
||||
Tensor<double> b({3}, 0.0);
|
||||
a = {1.0, 5.0, 3.0};
|
||||
b = {2.0, 4.0, 3.0};
|
||||
|
||||
Tensor<bool> r = a < b;
|
||||
REQUIRE(r.data()[0] == true);
|
||||
REQUIRE(r.data()[1] == false);
|
||||
REQUIRE(r.data()[2] == false);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor mixed-type multiply")
|
||||
{
|
||||
Tensor<int> a({3}, 0);
|
||||
Tensor<double> b({3}, 0.0);
|
||||
a = {2, 3, 4};
|
||||
b = {1.5, 2.5, 3.5};
|
||||
|
||||
Tensor<double> c = a * b;
|
||||
REQUIRE(c[0] == 3.0);
|
||||
REQUIRE(c[1] == 7.5);
|
||||
REQUIRE(c[2] == 14.0);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor mixed-type divide")
|
||||
{
|
||||
Tensor<double> a({3}, 0.0);
|
||||
Tensor<int> b({3}, 0);
|
||||
a = {10.0, 20.0, 30.0};
|
||||
b = {2, 4, 5};
|
||||
|
||||
Tensor<double> c = a / b;
|
||||
REQUIRE(c[0] == 5.0);
|
||||
REQUIRE(c[1] == 5.0);
|
||||
REQUIRE(c[2] == 6.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tensor bool specialization
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor<bool> storage")
|
||||
{
|
||||
// Tensor<bool> uses unsigned char internally to avoid std::vector<bool> proxy
|
||||
Tensor<bool> t({4}, false);
|
||||
t.data()[0] = true;
|
||||
t.data()[2] = true;
|
||||
REQUIRE(t.any());
|
||||
REQUIRE(!t.all());
|
||||
REQUIRE(t.data()[0] == true);
|
||||
REQUIRE(t.data()[1] == false);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// View (via Tensor accessors)
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Tensor slice axis 0 (2D)")
|
||||
{
|
||||
// [[1, 2, 3], [4, 5, 6]]
|
||||
Tensor<int> t({2, 3}, 0);
|
||||
int v = 1;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
t(i, j) = v++;
|
||||
|
||||
auto r0 = t.slice(0);
|
||||
REQUIRE(r0.size() == 3);
|
||||
REQUIRE(r0[0] == 1);
|
||||
REQUIRE(r0[1] == 2);
|
||||
REQUIRE(r0[2] == 3);
|
||||
|
||||
auto r1 = t.slice(1);
|
||||
REQUIRE(r1[0] == 4);
|
||||
REQUIRE(r1[1] == 5);
|
||||
REQUIRE(r1[2] == 6);
|
||||
|
||||
// Writing through view modifies the tensor
|
||||
r0[1] = 99;
|
||||
REQUIRE(t(0, 1) == 99);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor slice axis 1 (2D)")
|
||||
{
|
||||
// [[1, 2], [3, 4], [5, 6]]
|
||||
Tensor<int> t({3, 2}, 0);
|
||||
t(0, 0) = 1;
|
||||
t(0, 1) = 2;
|
||||
t(1, 0) = 3;
|
||||
t(1, 1) = 4;
|
||||
t(2, 0) = 5;
|
||||
t(2, 1) = 6;
|
||||
|
||||
auto c0 = t.slice(all, 0);
|
||||
REQUIRE(c0.size() == 3);
|
||||
REQUIRE(c0[0] == 1);
|
||||
REQUIRE(c0[1] == 3);
|
||||
REQUIRE(c0[2] == 5);
|
||||
|
||||
auto c1 = t.slice(all, 1);
|
||||
REQUIRE(c1[0] == 2);
|
||||
REQUIRE(c1[1] == 4);
|
||||
REQUIRE(c1[2] == 6);
|
||||
|
||||
// Write through column view
|
||||
c1[0] = 77;
|
||||
REQUIRE(t(0, 1) == 77);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor slice with range")
|
||||
{
|
||||
Tensor<int> t({6}, 0);
|
||||
t = {10, 20, 30, 40, 50, 60};
|
||||
|
||||
// range(start, end)
|
||||
auto s = t.slice(range(1, 4));
|
||||
REQUIRE(s.size() == 3);
|
||||
REQUIRE(s[0] == 20);
|
||||
REQUIRE(s[1] == 30);
|
||||
REQUIRE(s[2] == 40);
|
||||
|
||||
// range(end) from start — range(3) means [0, 3)
|
||||
auto s2 = t.slice(range(3));
|
||||
REQUIRE(s2.size() == 3);
|
||||
REQUIRE(s2[0] == 10);
|
||||
REQUIRE(s2[2] == 30);
|
||||
|
||||
// range(start, SIZE_MAX) to end
|
||||
auto s3 = t.slice(range(3, 6));
|
||||
REQUIRE(s3.size() == 3);
|
||||
REQUIRE(s3[0] == 40);
|
||||
REQUIRE(s3[2] == 60);
|
||||
|
||||
// Write through slice
|
||||
s[0] = 99;
|
||||
REQUIRE(t[1] == 99);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor flat view")
|
||||
{
|
||||
Tensor<int> t({2, 3}, 0);
|
||||
int v = 1;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
t(i, j) = v++;
|
||||
|
||||
auto f = t.flat();
|
||||
REQUIRE(f.size() == 6);
|
||||
REQUIRE(f[0] == 1);
|
||||
REQUIRE(f[5] == 6);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor slice on 3D")
|
||||
{
|
||||
// 2x3x4 tensor
|
||||
Tensor<int> t({2, 3, 4}, 0);
|
||||
int v = 0;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
for (size_t k = 0; k < 4; ++k)
|
||||
t(i, j, k) = v++;
|
||||
|
||||
// slice(1) -> fix axis 0 at 1 -> 3x4 view
|
||||
auto s = t.slice(1);
|
||||
REQUIRE(s.size() == 12);
|
||||
// t(1,0,0) = 12, t(1,0,1) = 13, ...
|
||||
REQUIRE(s(0, 0) == 12);
|
||||
REQUIRE(s(0, 1) == 13);
|
||||
REQUIRE(s(2, 3) == 23);
|
||||
|
||||
// slice(all, 2) -> fix axis 1 at 2 -> 2x4 view
|
||||
auto s2 = t.slice(all, 2);
|
||||
REQUIRE(s2.size() == 8);
|
||||
// t(0,2,0)=8, t(0,2,1)=9, t(1,2,0)=20
|
||||
REQUIRE(s2(0, 0) == 8);
|
||||
REQUIRE(s2(0, 1) == 9);
|
||||
REQUIRE(s2(1, 0) == 20);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor multi-axis slice")
|
||||
{
|
||||
// 2x3x4 tensor with sequential values
|
||||
Tensor<int> t({2, 3, 4}, 0);
|
||||
int v = 0;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
for (size_t k = 0; k < 4; ++k)
|
||||
t(i, j, k) = v++;
|
||||
|
||||
// slice(1, 2) -> fix axes 0 and 1 -> 1D view of 4 elements
|
||||
// Equivalent to numpy t[1, 2, :] -> t(1,2,0..3) = [20, 21, 22, 23]
|
||||
auto s = t.slice(1, 2);
|
||||
REQUIRE(s.size() == 4);
|
||||
REQUIRE(s[0] == 20);
|
||||
REQUIRE(s[1] == 21);
|
||||
REQUIRE(s[3] == 23);
|
||||
|
||||
// slice(all, 1, range(1, 3)) -> keep axis 0, fix axis 1, range on axis 2
|
||||
// Equivalent to numpy t[:, 1, 1:3]
|
||||
// t(0,1,1)=5, t(0,1,2)=6, t(1,1,1)=17, t(1,1,2)=18
|
||||
auto s2 = t.slice(all, 1, range(1, 3));
|
||||
REQUIRE(s2.size() == 4);
|
||||
REQUIRE(s2.ndim() == 2);
|
||||
REQUIRE(s2(0, 0) == 5);
|
||||
REQUIRE(s2(0, 1) == 6);
|
||||
REQUIRE(s2(1, 0) == 17);
|
||||
REQUIRE(s2(1, 1) == 18);
|
||||
|
||||
// slice(0, range(0, 2)) -> fix axis 0 at 0, range on axis 1
|
||||
// Equivalent to numpy t[0, 0:2, :] -> shape (2, 4)
|
||||
auto s3 = t.slice(0, range(0, 2));
|
||||
REQUIRE(s3.ndim() == 2);
|
||||
REQUIRE(s3.shape(0) == 2);
|
||||
REQUIRE(s3.shape(1) == 4);
|
||||
REQUIRE(s3(0, 0) == 0); // t(0,0,0)
|
||||
REQUIRE(s3(1, 3) == 7); // t(0,1,3)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// View assignment and arithmetic
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("View scalar assignment (fill)")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
auto r = t.slice(0);
|
||||
r = 7.0;
|
||||
REQUIRE(t(0, 0) == 7.0);
|
||||
REQUIRE(t(0, 1) == 7.0);
|
||||
REQUIRE(t(0, 2) == 7.0);
|
||||
REQUIRE(t(1, 0) == 0.0); // Other row unchanged
|
||||
}
|
||||
|
||||
TEST_CASE("View initializer_list assignment")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
auto r = t.slice(1);
|
||||
r = {10.0, 20.0, 30.0};
|
||||
REQUIRE(t(1, 0) == 10.0);
|
||||
REQUIRE(t(1, 1) == 20.0);
|
||||
REQUIRE(t(1, 2) == 30.0);
|
||||
}
|
||||
|
||||
TEST_CASE("View copy assignment (deep copy)")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
t.slice(0) = {1.0, 2.0, 3.0};
|
||||
t.slice(1) = {4.0, 5.0, 6.0};
|
||||
|
||||
// Copy row 0 into row 1
|
||||
t.slice(1) = t.slice(0);
|
||||
REQUIRE(t(1, 0) == 1.0);
|
||||
REQUIRE(t(1, 1) == 2.0);
|
||||
REQUIRE(t(1, 2) == 3.0);
|
||||
}
|
||||
|
||||
TEST_CASE("View compound operators")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
t.slice(0) = {1.0, 2.0, 3.0};
|
||||
|
||||
t.slice(0) *= 2.0;
|
||||
REQUIRE(t(0, 0) == 2.0);
|
||||
REQUIRE(t(0, 1) == 4.0);
|
||||
|
||||
t.slice(0) /= 2.0;
|
||||
REQUIRE(t(0, 0) == 1.0);
|
||||
REQUIRE(t(0, 1) == 2.0);
|
||||
}
|
||||
|
||||
TEST_CASE("View assignment from tensor")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
Tensor<double> vals({3}, 0.0);
|
||||
vals = {7.0, 8.0, 9.0};
|
||||
|
||||
t.slice(1) = vals;
|
||||
REQUIRE(t(1, 0) == 7.0);
|
||||
REQUIRE(t(1, 1) == 8.0);
|
||||
REQUIRE(t(1, 2) == 9.0);
|
||||
}
|
||||
|
||||
TEST_CASE("View compound addition from tensor")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
t.slice(0) = {1.0, 2.0, 3.0};
|
||||
Tensor<double> vals({3}, 0.0);
|
||||
vals = {10.0, 20.0, 30.0};
|
||||
|
||||
t.slice(0) += vals;
|
||||
REQUIRE(t(0, 0) == 11.0);
|
||||
REQUIRE(t(0, 1) == 22.0);
|
||||
REQUIRE(t(0, 2) == 33.0);
|
||||
}
|
||||
|
||||
TEST_CASE("View sum")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
t.slice(0) = {1.0, 2.0, 3.0};
|
||||
t.slice(1) = {4.0, 5.0, 6.0};
|
||||
|
||||
REQUIRE(t.slice(0).sum() == 6.0);
|
||||
REQUIRE(t.slice(1).sum() == 15.0);
|
||||
}
|
||||
|
||||
TEST_CASE("View iteration")
|
||||
{
|
||||
Tensor<int> t({2, 3}, 0);
|
||||
t.slice(0) = {1, 2, 3};
|
||||
|
||||
int sum = 0;
|
||||
for (auto val : t.slice(0))
|
||||
sum += val;
|
||||
REQUIRE(sum == 6);
|
||||
}
|
||||
|
||||
TEST_CASE("View sub-slice")
|
||||
{
|
||||
Tensor<int> t({6}, 0);
|
||||
t = {10, 20, 30, 40, 50, 60};
|
||||
|
||||
auto s = t.slice(range(1, 5)); // [20, 30, 40, 50]
|
||||
auto ss = s.slice(range(1, 3)); // [30, 40]
|
||||
REQUIRE(ss.size() == 2);
|
||||
REQUIRE(ss[0] == 30);
|
||||
REQUIRE(ss[1] == 40);
|
||||
}
|
||||
|
||||
TEST_CASE("Tensor from View")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
t.slice(0) = {1.0, 2.0, 3.0};
|
||||
|
||||
// Construct a new tensor from a view (copies data)
|
||||
Tensor<double> t2(t.slice(0));
|
||||
REQUIRE(t2.size() == 3);
|
||||
REQUIRE(t2[0] == 1.0);
|
||||
REQUIRE(t2[2] == 3.0);
|
||||
|
||||
// Modifying the new tensor doesn't affect the original
|
||||
t2[0] = 99.0;
|
||||
REQUIRE(t(0, 0) == 1.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Const View
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("Const tensor produces const views")
|
||||
{
|
||||
Tensor<double> t({2, 3}, 0.0);
|
||||
int v = 1;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
t(i, j) = v++;
|
||||
|
||||
const Tensor<double>& ct = t;
|
||||
auto r = ct.slice(0); // View<const double>
|
||||
REQUIRE(r[0] == 1.0);
|
||||
REQUIRE(r[2] == 3.0);
|
||||
|
||||
auto c = ct.slice(all, 1);
|
||||
REQUIRE(c[0] == 2.0);
|
||||
REQUIRE(c[1] == 5.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// StaticTensor2D
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("StaticTensor2D basics")
|
||||
{
|
||||
StaticTensor2D<double, 3, 4> t;
|
||||
REQUIRE(t.size() == 12);
|
||||
REQUIRE(t.shape()[0] == 3);
|
||||
REQUIRE(t.shape()[1] == 4);
|
||||
|
||||
// Default-initialized to zero
|
||||
REQUIRE(t(0, 0) == 0.0);
|
||||
|
||||
t(1, 2) = 42.0;
|
||||
REQUIRE(t(1, 2) == 42.0);
|
||||
// Flat data: row 1, col 2 = index 1*4 + 2 = 6
|
||||
REQUIRE(t.data()[6] == 42.0);
|
||||
}
|
||||
|
||||
TEST_CASE("StaticTensor2D fill")
|
||||
{
|
||||
StaticTensor2D<int, 2, 3> t;
|
||||
t.fill(5);
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
REQUIRE(t.data()[i] == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("StaticTensor2D iteration")
|
||||
{
|
||||
StaticTensor2D<int, 2, 3> t;
|
||||
t.fill(1);
|
||||
int sum = 0;
|
||||
for (auto val : t)
|
||||
sum += val;
|
||||
REQUIRE(sum == 6);
|
||||
}
|
||||
|
||||
TEST_CASE("StaticTensor2D slice")
|
||||
{
|
||||
StaticTensor2D<int, 3, 2> t;
|
||||
t(0, 0) = 1;
|
||||
t(0, 1) = 2;
|
||||
t(1, 0) = 3;
|
||||
t(1, 1) = 4;
|
||||
t(2, 0) = 5;
|
||||
t(2, 1) = 6;
|
||||
|
||||
// slice(1) = row 1 (fix axis 0 at 1)
|
||||
auto r1 = t.slice(1);
|
||||
REQUIRE(r1.size() == 2);
|
||||
REQUIRE(r1[0] == 3);
|
||||
REQUIRE(r1[1] == 4);
|
||||
|
||||
// slice(all, 0) = column 0 (fix axis 1 at 0)
|
||||
auto c0 = t.slice(all, 0);
|
||||
REQUIRE(c0.size() == 3);
|
||||
REQUIRE(c0[0] == 1);
|
||||
REQUIRE(c0[1] == 3);
|
||||
REQUIRE(c0[2] == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("StaticTensor2D flat view")
|
||||
{
|
||||
StaticTensor2D<double, 2, 2> t;
|
||||
t(0, 0) = 1.0;
|
||||
t(0, 1) = 2.0;
|
||||
t(1, 0) = 3.0;
|
||||
t(1, 1) = 4.0;
|
||||
|
||||
auto f = t.flat();
|
||||
REQUIRE(f.size() == 4);
|
||||
f = 0.0;
|
||||
REQUIRE(t(0, 0) == 0.0);
|
||||
REQUIRE(t(1, 1) == 0.0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Non-member functions
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("zeros")
|
||||
{
|
||||
auto t = zeros<double>({3, 4});
|
||||
REQUIRE(t.size() == 12);
|
||||
for (size_t i = 0; i < t.size(); ++i)
|
||||
REQUIRE(t[i] == 0.0);
|
||||
}
|
||||
|
||||
TEST_CASE("zeros_like")
|
||||
{
|
||||
Tensor<double> a({2, 5}, 7.0);
|
||||
auto b = zeros_like(a);
|
||||
REQUIRE(b.size() == 10);
|
||||
REQUIRE(b.shape(0) == 2);
|
||||
REQUIRE(b.shape(1) == 5);
|
||||
for (size_t i = 0; i < b.size(); ++i)
|
||||
REQUIRE(b[i] == 0.0);
|
||||
}
|
||||
|
||||
TEST_CASE("full_like")
|
||||
{
|
||||
Tensor<int> a({4}, 0);
|
||||
auto b = full_like(a, 42);
|
||||
REQUIRE(b.size() == 4);
|
||||
for (size_t i = 0; i < b.size(); ++i)
|
||||
REQUIRE(b[i] == 42);
|
||||
}
|
||||
|
||||
TEST_CASE("linspace")
|
||||
{
|
||||
auto t = linspace(0.0, 1.0, 5);
|
||||
REQUIRE(t.size() == 5);
|
||||
REQUIRE(t[0] == 0.0);
|
||||
REQUIRE(t[4] == 1.0);
|
||||
REQUIRE_THAT(t[1], Catch::Matchers::WithinRel(0.25, 1e-12));
|
||||
REQUIRE_THAT(t[2], Catch::Matchers::WithinRel(0.5, 1e-12));
|
||||
REQUIRE_THAT(t[3], Catch::Matchers::WithinRel(0.75, 1e-12));
|
||||
}
|
||||
|
||||
TEST_CASE("concatenate")
|
||||
{
|
||||
Tensor<int> a({3}, 0);
|
||||
Tensor<int> b({2}, 0);
|
||||
a = {1, 2, 3};
|
||||
b = {4, 5};
|
||||
|
||||
auto c = concatenate(a, b);
|
||||
REQUIRE(c.size() == 5);
|
||||
REQUIRE(c[0] == 1);
|
||||
REQUIRE(c[2] == 3);
|
||||
REQUIRE(c[3] == 4);
|
||||
REQUIRE(c[4] == 5);
|
||||
}
|
||||
|
||||
TEST_CASE("log")
|
||||
{
|
||||
Tensor<double> t({3}, 0.0);
|
||||
t = {1.0, std::exp(1.0), std::exp(2.0)};
|
||||
|
||||
auto r = log(t);
|
||||
REQUIRE_THAT(r[0], Catch::Matchers::WithinAbs(0.0, 1e-12));
|
||||
REQUIRE_THAT(r[1], Catch::Matchers::WithinAbs(1.0, 1e-12));
|
||||
REQUIRE_THAT(r[2], Catch::Matchers::WithinAbs(2.0, 1e-12));
|
||||
}
|
||||
|
||||
TEST_CASE("abs")
|
||||
{
|
||||
Tensor<double> t({4}, 0.0);
|
||||
t = {-3.0, -1.0, 0.0, 2.0};
|
||||
|
||||
auto r = abs(t);
|
||||
REQUIRE(r[0] == 3.0);
|
||||
REQUIRE(r[1] == 1.0);
|
||||
REQUIRE(r[2] == 0.0);
|
||||
REQUIRE(r[3] == 2.0);
|
||||
}
|
||||
|
||||
TEST_CASE("where")
|
||||
{
|
||||
Tensor<bool> cond({4}, false);
|
||||
cond.data()[0] = true;
|
||||
cond.data()[2] = true;
|
||||
|
||||
Tensor<double> vals({4}, 0.0);
|
||||
vals = {10.0, 20.0, 30.0, 40.0};
|
||||
|
||||
auto r = where(cond, vals, -1.0);
|
||||
REQUIRE(r[0] == 10.0);
|
||||
REQUIRE(r[1] == -1.0);
|
||||
REQUIRE(r[2] == 30.0);
|
||||
REQUIRE(r[3] == -1.0);
|
||||
}
|
||||
|
||||
TEST_CASE("nan_to_num")
|
||||
{
|
||||
Tensor<double> t({4}, 0.0);
|
||||
t[0] = 1.0;
|
||||
t[1] = std::nan("");
|
||||
t[2] = std::numeric_limits<double>::infinity();
|
||||
t[3] = -std::numeric_limits<double>::infinity();
|
||||
|
||||
auto r = nan_to_num(t);
|
||||
REQUIRE(r[0] == 1.0);
|
||||
REQUIRE(r[1] == 0.0); // NaN -> 0
|
||||
REQUIRE(r[2] == std::numeric_limits<double>::max()); // +inf -> max
|
||||
REQUIRE(r[3] == std::numeric_limits<double>::lowest()); // -inf -> lowest
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// is_tensor trait
|
||||
// ============================================================================
|
||||
|
||||
TEST_CASE("is_tensor trait")
|
||||
{
|
||||
REQUIRE(is_tensor<Tensor<double>>::value);
|
||||
REQUIRE(is_tensor<Tensor<int>>::value);
|
||||
REQUIRE(is_tensor<StaticTensor2D<double, 3, 3>>::value);
|
||||
REQUIRE(!is_tensor<double>::value);
|
||||
REQUIRE(!is_tensor<std::vector<double>>::value);
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/error.h"
|
||||
|
|
|
|||
1
vendor/xtensor
vendored
1
vendor/xtensor
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 3634f2ded19e0cf38208c8b86cea9e1d7c8e397d
|
||||
1
vendor/xtl
vendored
1
vendor/xtl
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit a7c1c5444dfc57f76620391af4c94785ff82c8d6
|
||||
Loading…
Add table
Add a link
Reference in a new issue