mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 05:35:49 -04:00
Merge branch 'develop' into rng-stream-changes
This commit is contained in:
commit
43804fc09d
158 changed files with 3155 additions and 2934 deletions
15
src/bank.cpp
15
src/bank.cpp
|
|
@ -1,8 +1,9 @@
|
|||
#include "openmc/bank.h"
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/simulation.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/simulation.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
|
@ -15,20 +16,20 @@ namespace openmc {
|
|||
|
||||
namespace simulation {
|
||||
|
||||
std::vector<Particle::Bank> source_bank;
|
||||
vector<SourceSite> source_bank;
|
||||
|
||||
SharedArray<Particle::Bank> surf_source_bank;
|
||||
SharedArray<SourceSite> surf_source_bank;
|
||||
|
||||
// The fission bank is allocated as a SharedArray, rather than a vector, as it will
|
||||
// be shared by all threads in the simulation. It will be allocated to a fixed
|
||||
// maximum capacity in the init_fission_bank() function. Then, Elements will be
|
||||
// added to it by using SharedArray's special thread_safe_append() function.
|
||||
SharedArray<Particle::Bank> fission_bank;
|
||||
SharedArray<SourceSite> fission_bank;
|
||||
|
||||
// Each entry in this vector corresponds to the number of progeny produced
|
||||
// this generation for the particle located at that index. This vector is
|
||||
// used to efficiently sort the fission bank after each iteration.
|
||||
std::vector<int64_t> progeny_per_particle;
|
||||
vector<int64_t> progeny_per_particle;
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
|
|
@ -79,8 +80,8 @@ void sort_fission_bank()
|
|||
// We need a scratch vector to make permutation of the fission bank into
|
||||
// sorted order easy. Under normal usage conditions, the fission bank is
|
||||
// over provisioned, so we can use that as scratch space.
|
||||
Particle::Bank* sorted_bank;
|
||||
std::vector<Particle::Bank> sorted_bank_holder;
|
||||
SourceSite* sorted_bank;
|
||||
vector<SourceSite> sorted_bank_holder;
|
||||
|
||||
// If there is not enough space, allocate a temporary vector and point to it
|
||||
if (simulation::fission_bank.size() > simulation::fission_bank.capacity() / 2) {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ void
|
|||
TranslationalPeriodicBC::handle_particle(Particle& p, const Surface& surf) const
|
||||
{
|
||||
// TODO: off-by-one on surface indices throughout this function.
|
||||
int i_particle_surf = std::abs(p.surface_) - 1;
|
||||
int i_particle_surf = std::abs(p.surface()) - 1;
|
||||
|
||||
// Figure out which of the two BC surfaces were struck then find the
|
||||
// particle's new location and surface.
|
||||
|
|
@ -121,10 +121,10 @@ TranslationalPeriodicBC::handle_particle(Particle& p, const Surface& surf) const
|
|||
int new_surface;
|
||||
if (i_particle_surf == i_surf_) {
|
||||
new_r = p.r() + translation_;
|
||||
new_surface = p.surface_ > 0 ? j_surf_ + 1 : -(j_surf_ + 1);
|
||||
new_surface = p.surface() > 0 ? j_surf_ + 1 : -(j_surf_ + 1);
|
||||
} else if (i_particle_surf == j_surf_) {
|
||||
new_r = p.r() - translation_;
|
||||
new_surface = p.surface_ > 0 ? i_surf_ + 1 : -(i_surf_ + 1);
|
||||
new_surface = p.surface() > 0 ? i_surf_ + 1 : -(i_surf_ + 1);
|
||||
} else {
|
||||
throw std::runtime_error("Called BoundaryCondition::handle_particle after "
|
||||
"hitting a surface, but that surface is not recognized by the BC.");
|
||||
|
|
@ -222,7 +222,7 @@ void
|
|||
RotationalPeriodicBC::handle_particle(Particle& p, const Surface& surf) const
|
||||
{
|
||||
// TODO: off-by-one on surface indices throughout this function.
|
||||
int i_particle_surf = std::abs(p.surface_) - 1;
|
||||
int i_particle_surf = std::abs(p.surface()) - 1;
|
||||
|
||||
// Figure out which of the two BC surfaces were struck to figure out if a
|
||||
// forward or backward rotation is required. Specify the other surface as
|
||||
|
|
@ -231,10 +231,10 @@ RotationalPeriodicBC::handle_particle(Particle& p, const Surface& surf) const
|
|||
int new_surface;
|
||||
if (i_particle_surf == i_surf_) {
|
||||
theta = angle_;
|
||||
new_surface = p.surface_ > 0 ? -(j_surf_ + 1) : j_surf_ + 1;
|
||||
new_surface = p.surface() > 0 ? -(j_surf_ + 1) : j_surf_ + 1;
|
||||
} else if (i_particle_surf == j_surf_) {
|
||||
theta = -angle_;
|
||||
new_surface = p.surface_ > 0 ? -(i_surf_ + 1) : i_surf_ + 1;
|
||||
new_surface = p.surface() > 0 ? -(i_surf_ + 1) : i_surf_ + 1;
|
||||
} else {
|
||||
throw std::runtime_error("Called BoundaryCondition::handle_particle after "
|
||||
"hitting a surface, but that surface is not recognized by the BC.");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace data {
|
|||
|
||||
xt::xtensor<double, 1> ttb_e_grid;
|
||||
xt::xtensor<double, 1> ttb_k_grid;
|
||||
std::vector<Bremsstrahlung> ttb;
|
||||
vector<Bremsstrahlung> ttb;
|
||||
|
||||
} // namespace data
|
||||
|
||||
|
|
@ -28,20 +28,22 @@ std::vector<Bremsstrahlung> ttb;
|
|||
|
||||
void thick_target_bremsstrahlung(Particle& p, double* E_lost)
|
||||
{
|
||||
if (p.material_ == MATERIAL_VOID) return;
|
||||
if (p.material() == MATERIAL_VOID)
|
||||
return;
|
||||
|
||||
int photon = static_cast<int>(Particle::Type::photon);
|
||||
if (p.E_ < settings::energy_cutoff[photon]) return;
|
||||
int photon = static_cast<int>(ParticleType::photon);
|
||||
if (p.E() < settings::energy_cutoff[photon])
|
||||
return;
|
||||
|
||||
// Get bremsstrahlung data for this material and particle type
|
||||
BremsstrahlungData* mat;
|
||||
if (p.type_ == Particle::Type::positron) {
|
||||
mat = &model::materials[p.material_]->ttb_->positron;
|
||||
if (p.type() == ParticleType::positron) {
|
||||
mat = &model::materials[p.material()]->ttb_->positron;
|
||||
} else {
|
||||
mat = &model::materials[p.material_]->ttb_->electron;
|
||||
mat = &model::materials[p.material()]->ttb_->electron;
|
||||
}
|
||||
|
||||
double e = std::log(p.E_);
|
||||
double e = std::log(p.E());
|
||||
auto n_e = data::ttb_e_grid.size();
|
||||
|
||||
// Find the lower bounding index of the incident electron energy
|
||||
|
|
@ -108,7 +110,7 @@ void thick_target_bremsstrahlung(Particle& p, double* E_lost)
|
|||
|
||||
if (w > settings::energy_cutoff[photon]) {
|
||||
// Create secondary photon
|
||||
p.create_secondary(p.wgt_, p.u(), w, Particle::Type::photon);
|
||||
p.create_secondary(p.wgt(), p.u(), w, ParticleType::photon);
|
||||
*E_lost += w;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
84
src/cell.cpp
84
src/cell.cpp
|
|
@ -33,10 +33,10 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
std::unordered_map<int32_t, int32_t> cell_map;
|
||||
std::vector<std::unique_ptr<Cell>> cells;
|
||||
vector<unique_ptr<Cell>> cells;
|
||||
|
||||
std::unordered_map<int32_t, int32_t> universe_map;
|
||||
std::vector<std::unique_ptr<Universe>> universes;
|
||||
vector<unique_ptr<Universe>> universes;
|
||||
} // namespace model
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -46,10 +46,10 @@ namespace model {
|
|||
//! operators.
|
||||
//==============================================================================
|
||||
|
||||
std::vector<int32_t>
|
||||
tokenize(const std::string region_spec) {
|
||||
vector<int32_t> tokenize(const std::string region_spec)
|
||||
{
|
||||
// Check for an empty region_spec first.
|
||||
std::vector<int32_t> tokens;
|
||||
vector<int32_t> tokens;
|
||||
if (region_spec.empty()) {
|
||||
return tokens;
|
||||
}
|
||||
|
|
@ -113,11 +113,10 @@ tokenize(const std::string region_spec) {
|
|||
//! This function uses the shunting-yard algorithm.
|
||||
//==============================================================================
|
||||
|
||||
std::vector<int32_t>
|
||||
generate_rpn(int32_t cell_id, std::vector<int32_t> infix)
|
||||
vector<int32_t> generate_rpn(int32_t cell_id, vector<int32_t> infix)
|
||||
{
|
||||
std::vector<int32_t> rpn;
|
||||
std::vector<int32_t> stack;
|
||||
vector<int32_t> rpn;
|
||||
vector<int32_t> stack;
|
||||
|
||||
for (int32_t token : infix) {
|
||||
if (token < OP_UNION) {
|
||||
|
|
@ -197,7 +196,7 @@ Universe::to_hdf5(hid_t universes_group) const
|
|||
|
||||
// Write the contained cells.
|
||||
if (cells_.size() > 0) {
|
||||
std::vector<int32_t> cell_ids;
|
||||
vector<int32_t> cell_ids;
|
||||
for (auto i_cell : cells_) cell_ids.push_back(model::cells[i_cell]->id_);
|
||||
write_dataset(group, "cells", cell_ids);
|
||||
}
|
||||
|
|
@ -333,8 +332,8 @@ CSGCell::CSGCell(pugi::xml_node cell_node)
|
|||
// universe), more than one material (distribmats), and some materials may
|
||||
// be "void".
|
||||
if (material_present) {
|
||||
std::vector<std::string> mats
|
||||
{get_node_array<std::string>(cell_node, "material", true)};
|
||||
vector<std::string> mats {
|
||||
get_node_array<std::string>(cell_node, "material", true)};
|
||||
if (mats.size() > 0) {
|
||||
material_.reserve(mats.size());
|
||||
for (std::string mat : mats) {
|
||||
|
|
@ -563,7 +562,7 @@ CSGCell::to_hdf5(hid_t cell_group) const
|
|||
// Write fill information.
|
||||
if (type_ == Fill::MATERIAL) {
|
||||
write_dataset(group, "fill_type", "material");
|
||||
std::vector<int32_t> mat_ids;
|
||||
vector<int32_t> mat_ids;
|
||||
for (auto i_mat : material_) {
|
||||
if (i_mat != MATERIAL_VOID) {
|
||||
mat_ids.push_back(model::materials[i_mat]->id_);
|
||||
|
|
@ -577,7 +576,7 @@ CSGCell::to_hdf5(hid_t cell_group) const
|
|||
write_dataset(group, "material", mat_ids);
|
||||
}
|
||||
|
||||
std::vector<double> temps;
|
||||
vector<double> temps;
|
||||
for (auto sqrtkT_val : sqrtkT_)
|
||||
temps.push_back(sqrtkT_val * sqrtkT_val / K_BOLTZMANN);
|
||||
write_dataset(group, "temperature", temps);
|
||||
|
|
@ -590,7 +589,7 @@ CSGCell::to_hdf5(hid_t cell_group) const
|
|||
}
|
||||
if (!rotation_.empty()) {
|
||||
if (rotation_.size() == 12) {
|
||||
std::array<double, 3> rot {rotation_[9], rotation_[10], rotation_[11]};
|
||||
array<double, 3> rot {rotation_[9], rotation_[10], rotation_[11]};
|
||||
write_dataset(group, "rotation", rot);
|
||||
} else {
|
||||
write_dataset(group, "rotation", rotation_);
|
||||
|
|
@ -613,8 +612,8 @@ BoundingBox CSGCell::bounding_box_simple() const {
|
|||
return bbox;
|
||||
}
|
||||
|
||||
void CSGCell::apply_demorgan(std::vector<int32_t>::iterator start,
|
||||
std::vector<int32_t>::iterator stop)
|
||||
void CSGCell::apply_demorgan(
|
||||
vector<int32_t>::iterator start, vector<int32_t>::iterator stop)
|
||||
{
|
||||
while (start < stop) {
|
||||
if (*start < OP_UNION) { *start *= -1; }
|
||||
|
|
@ -624,9 +623,9 @@ void CSGCell::apply_demorgan(std::vector<int32_t>::iterator start,
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<int32_t>::iterator
|
||||
CSGCell::find_left_parenthesis(std::vector<int32_t>::iterator start,
|
||||
const std::vector<int32_t>& rpn) {
|
||||
vector<int32_t>::iterator CSGCell::find_left_parenthesis(
|
||||
vector<int32_t>::iterator start, const vector<int32_t>& rpn)
|
||||
{
|
||||
// start search at zero
|
||||
int parenthesis_level = 0;
|
||||
auto it = start;
|
||||
|
|
@ -657,12 +656,13 @@ CSGCell::find_left_parenthesis(std::vector<int32_t>::iterator start,
|
|||
return it;
|
||||
}
|
||||
|
||||
void CSGCell::remove_complement_ops(std::vector<int32_t>& rpn) {
|
||||
void CSGCell::remove_complement_ops(vector<int32_t>& rpn)
|
||||
{
|
||||
auto it = std::find(rpn.begin(), rpn.end(), OP_COMPLEMENT);
|
||||
while (it != rpn.end()) {
|
||||
// find the opening parenthesis (if any)
|
||||
auto left = find_left_parenthesis(it, rpn);
|
||||
std::vector<int32_t> tmp(left, it+1);
|
||||
vector<int32_t> tmp(left, it + 1);
|
||||
|
||||
// apply DeMorgan's law to any surfaces/operators between these
|
||||
// positions in the RPN
|
||||
|
|
@ -674,11 +674,12 @@ void CSGCell::remove_complement_ops(std::vector<int32_t>& rpn) {
|
|||
}
|
||||
}
|
||||
|
||||
BoundingBox CSGCell::bounding_box_complex(std::vector<int32_t> rpn) {
|
||||
BoundingBox CSGCell::bounding_box_complex(vector<int32_t> rpn)
|
||||
{
|
||||
// remove complements by adjusting surface signs and operators
|
||||
remove_complement_ops(rpn);
|
||||
|
||||
std::vector<BoundingBox> stack(rpn.size());
|
||||
vector<BoundingBox> stack(rpn.size());
|
||||
int i_stack = -1;
|
||||
|
||||
for (auto& token : rpn) {
|
||||
|
|
@ -731,7 +732,7 @@ CSGCell::contains_complex(Position r, Direction u, int32_t on_surface) const
|
|||
{
|
||||
// Make a stack of booleans. We don't know how big it needs to be, but we do
|
||||
// know that rpn.size() is an upper-bound.
|
||||
std::vector<bool> stack(rpn_.size());
|
||||
vector<bool> stack(rpn_.size());
|
||||
int i_stack = -1;
|
||||
|
||||
for (int32_t token : rpn_) {
|
||||
|
|
@ -787,9 +788,9 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons
|
|||
Expects(p);
|
||||
// if we've changed direction or we're not on a surface,
|
||||
// reset the history and update last direction
|
||||
if (u != p->last_dir_ || on_surface == 0) {
|
||||
p->history_.reset();
|
||||
p->last_dir_ = u;
|
||||
if (u != p->last_dir() || on_surface == 0) {
|
||||
p->history().reset();
|
||||
p->last_dir() = u;
|
||||
}
|
||||
|
||||
moab::ErrorCode rval;
|
||||
|
|
@ -798,7 +799,7 @@ DAGCell::distance(Position r, Direction u, int32_t on_surface, Particle* p) cons
|
|||
double dist;
|
||||
double pnt[3] = {r.x, r.y, r.z};
|
||||
double dir[3] = {u.x, u.y, u.z};
|
||||
rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &p->history_);
|
||||
rval = dagmc_ptr_->ray_fire(vol, pnt, dir, hit_surf, dist, &p->history());
|
||||
MB_CHK_ERR_CONT(rval);
|
||||
int surf_idx;
|
||||
if (hit_surf != 0) {
|
||||
|
|
@ -945,8 +946,8 @@ UniversePartitioner::UniversePartitioner(const Universe& univ)
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<int32_t>&
|
||||
UniversePartitioner::get_cells(Position r, Direction u) const
|
||||
const vector<int32_t>& UniversePartitioner::get_cells(
|
||||
Position r, Direction u) const
|
||||
{
|
||||
// Perform a binary search for the partition containing the given coordinates.
|
||||
int left = 0;
|
||||
|
|
@ -998,7 +999,7 @@ void read_cells(pugi::xml_node node)
|
|||
// Loop over XML cell elements and populate the array.
|
||||
model::cells.reserve(n_cells);
|
||||
for (pugi::xml_node cell_node : node.children("cell")) {
|
||||
model::cells.push_back(std::make_unique<CSGCell>(cell_node));
|
||||
model::cells.push_back(make_unique<CSGCell>(cell_node));
|
||||
}
|
||||
|
||||
// Fill the cell map.
|
||||
|
|
@ -1017,7 +1018,7 @@ void read_cells(pugi::xml_node node)
|
|||
int32_t uid = model::cells[i]->universe_;
|
||||
auto it = model::universe_map.find(uid);
|
||||
if (it == model::universe_map.end()) {
|
||||
model::universes.push_back(std::make_unique<Universe>());
|
||||
model::universes.push_back(make_unique<Universe>());
|
||||
model::universes.back()->id_ = uid;
|
||||
model::universes.back()->cells_.push_back(i);
|
||||
model::universe_map[uid] = model::universes.size() - 1;
|
||||
|
|
@ -1175,11 +1176,10 @@ openmc_cell_set_name(int32_t index, const char* name) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<int32_t, std::vector<int32_t>>
|
||||
Cell::get_contained_cells() const {
|
||||
std::unordered_map<int32_t, std::vector<int32_t>> contained_cells;
|
||||
std::vector<ParentCell> parent_cells;
|
||||
std::unordered_map<int32_t, vector<int32_t>> Cell::get_contained_cells() const
|
||||
{
|
||||
std::unordered_map<int32_t, vector<int32_t>> contained_cells;
|
||||
vector<ParentCell> parent_cells;
|
||||
|
||||
// if this cell is filled w/ a material, it contains no other cells
|
||||
if (type_ != Fill::MATERIAL) {
|
||||
|
|
@ -1190,9 +1190,9 @@ Cell::get_contained_cells() const {
|
|||
}
|
||||
|
||||
//! Get all cells within this cell
|
||||
void
|
||||
Cell::get_contained_cells_inner(std::unordered_map<int32_t, std::vector<int32_t>>& contained_cells,
|
||||
std::vector<ParentCell>& parent_cells) const
|
||||
void Cell::get_contained_cells_inner(
|
||||
std::unordered_map<int32_t, vector<int32_t>>& contained_cells,
|
||||
vector<ParentCell>& parent_cells) const
|
||||
{
|
||||
|
||||
// filled by material, determine instance based on parent cells
|
||||
|
|
@ -1285,7 +1285,7 @@ openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end)
|
|||
if (index_start) *index_start = model::cells.size();
|
||||
if (index_end) *index_end = model::cells.size() + n - 1;
|
||||
for (int32_t i = 0; i < n; i++) {
|
||||
model::cells.push_back(std::make_unique<CSGCell>());
|
||||
model::cells.push_back(make_unique<CSGCell>());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "openmc/cmfd_solver.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef _OPENMP
|
||||
|
|
@ -9,14 +8,15 @@
|
|||
#include "xtensor/xtensor.hpp"
|
||||
|
||||
#include "openmc/bank.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/mesh.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/tallies/filter_energy.h"
|
||||
#include "openmc/tallies/filter_mesh.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -26,9 +26,9 @@ namespace cmfd {
|
|||
// Global variables
|
||||
//==============================================================================
|
||||
|
||||
std::vector<int> indptr;
|
||||
vector<int> indptr;
|
||||
|
||||
std::vector<int> indices;
|
||||
vector<int> indices;
|
||||
|
||||
int dim;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ int use_all_threads;
|
|||
|
||||
StructuredMesh* mesh;
|
||||
|
||||
std::vector<double> egrid;
|
||||
vector<double> egrid;
|
||||
|
||||
double norm;
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ xt::xtensor<double, 1> count_bank_sites(xt::xtensor<int, 1>& bins, bool* outside
|
|||
{
|
||||
// Determine shape of array for counts
|
||||
std::size_t cnt_size = cmfd::nx * cmfd::ny * cmfd::nz * cmfd::ng;
|
||||
std::vector<std::size_t> cnt_shape = {cnt_size};
|
||||
vector<std::size_t> cnt_shape = {cnt_size};
|
||||
|
||||
// Create array of zeros
|
||||
xt::xarray<double> cnt {cnt_shape, 0.0};
|
||||
|
|
@ -299,7 +299,7 @@ int cmfd_linsolver_1g(const double* A_data, const double* b, double* x,
|
|||
double err = 0.0;
|
||||
|
||||
// Copy over x vector
|
||||
std::vector<double> tmpx {x, x+cmfd::dim};
|
||||
vector<double> tmpx {x, x + cmfd::dim};
|
||||
|
||||
// Perform red/black Gauss-Seidel iterations
|
||||
for (int irb = 0; irb < 2; irb++) {
|
||||
|
|
@ -366,7 +366,7 @@ int cmfd_linsolver_2g(const double* A_data, const double* b, double* x,
|
|||
double err = 0.0;
|
||||
|
||||
// Copy over x vector
|
||||
std::vector<double> tmpx {x, x+cmfd::dim};
|
||||
vector<double> tmpx {x, x + cmfd::dim};
|
||||
|
||||
// Perform red/black Gauss-Seidel iterations
|
||||
for (int irb = 0; irb < 2; irb++) {
|
||||
|
|
@ -458,7 +458,7 @@ int cmfd_linsolver_ng(const double* A_data, const double* b, double* x,
|
|||
double err = 0.0;
|
||||
|
||||
// Copy over x vector
|
||||
std::vector<double> tmpx {x, x+cmfd::dim};
|
||||
vector<double> tmpx {x, x + cmfd::dim};
|
||||
|
||||
// Loop around matrix rows
|
||||
for (int irow = 0; irow < cmfd::dim; irow++) {
|
||||
|
|
@ -554,7 +554,7 @@ int openmc_run_linsolver(const double* A_data, const double* b, double* x,
|
|||
|
||||
void free_memory_cmfd()
|
||||
{
|
||||
// Clear std::vectors
|
||||
// Clear vectors
|
||||
cmfd::indptr.clear();
|
||||
cmfd::indices.clear();
|
||||
cmfd::egrid.clear();
|
||||
|
|
|
|||
|
|
@ -37,8 +37,7 @@ namespace openmc {
|
|||
namespace data {
|
||||
|
||||
std::map<LibraryKey, std::size_t> library_map;
|
||||
std::vector<Library> libraries;
|
||||
|
||||
vector<Library> libraries;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -182,16 +181,15 @@ void read_cross_sections_xml()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
read_ce_cross_sections(const std::vector<std::vector<double>>& nuc_temps,
|
||||
const std::vector<std::vector<double>>& thermal_temps)
|
||||
void read_ce_cross_sections(const vector<vector<double>>& nuc_temps,
|
||||
const vector<vector<double>>& thermal_temps)
|
||||
{
|
||||
std::unordered_set<std::string> already_read;
|
||||
|
||||
// Construct a vector of nuclide names because we haven't loaded nuclide data
|
||||
// yet, but we need to know the name of the i-th nuclide
|
||||
std::vector<std::string> nuclide_names(data::nuclide_map.size());
|
||||
std::vector<std::string> thermal_names(data::thermal_scatt_map.size());
|
||||
vector<std::string> nuclide_names(data::nuclide_map.size());
|
||||
vector<std::string> thermal_names(data::thermal_scatt_map.size());
|
||||
for (const auto& kv : data::nuclide_map) {
|
||||
nuclide_names[kv.second] = kv.first;
|
||||
}
|
||||
|
|
@ -238,8 +236,8 @@ read_ce_cross_sections(const std::vector<std::vector<double>>& nuc_temps,
|
|||
|
||||
// Read thermal scattering data from HDF5
|
||||
hid_t group = open_group(file_id, name.c_str());
|
||||
data::thermal_scatt.push_back(std::make_unique<ThermalScattering>(
|
||||
group, thermal_temps[i_table]));
|
||||
data::thermal_scatt.push_back(
|
||||
make_unique<ThermalScattering>(group, thermal_temps[i_table]));
|
||||
close_group(group);
|
||||
file_close(file_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ void load_dagmc_geometry()
|
|||
dagmcMetaData DMD(model::DAG, false, false);
|
||||
DMD.load_property_data();
|
||||
|
||||
std::vector<std::string> keywords {"temp"};
|
||||
vector<std::string> keywords {"temp"};
|
||||
std::map<std::string, std::string> dum;
|
||||
std::string delimiters = ":/";
|
||||
rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str());
|
||||
|
|
@ -211,7 +211,7 @@ void load_dagmc_geometry()
|
|||
// Populate the Universe vector and dict
|
||||
auto it = model::universe_map.find(dagmc_univ_id);
|
||||
if (it == model::universe_map.end()) {
|
||||
model::universes.push_back(std::make_unique<Universe>());
|
||||
model::universes.push_back(make_unique<Universe>());
|
||||
model::universes.back()->id_ = dagmc_univ_id;
|
||||
model::universes.back()->cells_.push_back(i);
|
||||
model::universe_map[dagmc_univ_id] = model::universes.size() - 1;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#include "openmc/distribution_angle.h"
|
||||
|
||||
#include <cmath> // for abs, copysign
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
|
@ -10,6 +9,7 @@
|
|||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/search.h"
|
||||
#include "openmc/vector.h" // for vector
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -24,8 +24,8 @@ AngleDistribution::AngleDistribution(hid_t group)
|
|||
int n_energy = energy_.size();
|
||||
|
||||
// Get outgoing energy distribution data
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
vector<int> offsets;
|
||||
vector<int> interp;
|
||||
hid_t dset = open_dataset(group, "mu");
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
|
|
@ -47,9 +47,9 @@ AngleDistribution::AngleDistribution(hid_t group)
|
|||
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));
|
||||
std::vector<double> x {xs.begin(), xs.end()};
|
||||
std::vector<double> p {ps.begin(), ps.end()};
|
||||
std::vector<double> c {cs.begin(), cs.end()};
|
||||
vector<double> x {xs.begin(), xs.end()};
|
||||
vector<double> p {ps.begin(), ps.end()};
|
||||
vector<double> c {cs.begin(), cs.end()};
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -78,9 +78,9 @@ ContinuousTabular::ContinuousTabular(hid_t group)
|
|||
|
||||
// Get outgoing energy distribution data
|
||||
dset = open_dataset(group, "distribution");
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
std::vector<int> n_discrete;
|
||||
vector<int> offsets;
|
||||
vector<int> interp;
|
||||
vector<int> n_discrete;
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ CylindricalIndependent::CylindricalIndependent(pugi::xml_node node)
|
|||
// If no distribution was specified, default to a single point at r=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
r_ = std::make_unique<Discrete>(x, p, 1);
|
||||
r_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read distribution for phi-coordinate
|
||||
|
|
@ -76,7 +76,7 @@ CylindricalIndependent::CylindricalIndependent(pugi::xml_node node)
|
|||
// If no distribution was specified, default to a single point at phi=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
phi_ = std::make_unique<Discrete>(x, p, 1);
|
||||
phi_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read distribution for z-coordinate
|
||||
|
|
@ -87,7 +87,7 @@ CylindricalIndependent::CylindricalIndependent(pugi::xml_node node)
|
|||
// If no distribution was specified, default to a single point at z=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
z_ = std::make_unique<Discrete>(x, p, 1);
|
||||
z_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read cylinder center coordinates
|
||||
|
|
@ -129,7 +129,7 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node)
|
|||
// If no distribution was specified, default to a single point at r=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
r_ = std::make_unique<Discrete>(x, p, 1);
|
||||
r_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read distribution for theta-coordinate
|
||||
|
|
@ -140,7 +140,7 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node)
|
|||
// If no distribution was specified, default to a single point at theta=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
theta_ = std::make_unique<Discrete>(x, p, 1);
|
||||
theta_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read distribution for phi-coordinate
|
||||
|
|
@ -151,7 +151,7 @@ SphericalIndependent::SphericalIndependent(pugi::xml_node node)
|
|||
// If no distribution was specified, default to a single point at phi=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
phi_ = std::make_unique<Discrete>(x, p, 1);
|
||||
phi_ = make_unique<Discrete>(x, p, 1);
|
||||
}
|
||||
|
||||
// Read sphere center coordinates
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "xtensor/xtensor.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/bank.h"
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/constants.h"
|
||||
|
|
@ -17,11 +18,10 @@
|
|||
#include "openmc/search.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/simulation.h"
|
||||
#include "openmc/timer.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/timer.h"
|
||||
|
||||
#include <algorithm> // for min
|
||||
#include <array>
|
||||
#include <cmath> // for sqrt, abs, pow
|
||||
#include <iterator> // for back_inserter
|
||||
#include <string>
|
||||
|
|
@ -36,8 +36,8 @@ namespace openmc {
|
|||
namespace simulation {
|
||||
|
||||
double keff_generation;
|
||||
std::array<double, 2> k_sum;
|
||||
std::vector<double> entropy;
|
||||
array<double, 2> k_sum;
|
||||
vector<double> entropy;
|
||||
xt::xtensor<double, 1> source_frac;
|
||||
|
||||
} // namespace simulation
|
||||
|
|
@ -137,7 +137,7 @@ void synchronize_bank()
|
|||
// Allocate temporary source bank -- we don't really know how many fission
|
||||
// sites were created, so overallocate by a factor of 3
|
||||
int64_t index_temp = 0;
|
||||
std::vector<Particle::Bank> temp_sites(3*simulation::work_per_rank);
|
||||
vector<SourceSite> temp_sites(3 * simulation::work_per_rank);
|
||||
|
||||
for (int64_t i = 0; i < simulation::fission_bank.size(); i++ ) {
|
||||
const auto& site = simulation::fission_bank[i];
|
||||
|
|
@ -214,7 +214,7 @@ void synchronize_bank()
|
|||
// SEND BANK SITES TO NEIGHBORS
|
||||
|
||||
int64_t index_local = 0;
|
||||
std::vector<MPI_Request> requests;
|
||||
vector<MPI_Request> requests;
|
||||
|
||||
if (start < settings::n_particles) {
|
||||
// Determine the index of the processor which has the first part of the
|
||||
|
|
@ -230,7 +230,7 @@ void synchronize_bank()
|
|||
// process
|
||||
if (neighbor != mpi::rank) {
|
||||
requests.emplace_back();
|
||||
MPI_Isend(&temp_sites[index_local], static_cast<int>(n), mpi::bank,
|
||||
MPI_Isend(&temp_sites[index_local], static_cast<int>(n), mpi::source_site,
|
||||
neighbor, mpi::rank, mpi::intracomm, &requests.back());
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +276,7 @@ void synchronize_bank()
|
|||
// asynchronous receive for the source sites
|
||||
|
||||
requests.emplace_back();
|
||||
MPI_Irecv(&simulation::source_bank[index_local], static_cast<int>(n), mpi::bank,
|
||||
MPI_Irecv(&simulation::source_bank[index_local], static_cast<int>(n), mpi::source_site,
|
||||
neighbor, neighbor, mpi::intracomm, &requests.back());
|
||||
|
||||
} else {
|
||||
|
|
@ -372,7 +372,7 @@ int openmc_get_keff(double* k_combined)
|
|||
// Copy estimates of k-effective and its variance (not variance of the mean)
|
||||
const auto& gt = simulation::global_tallies;
|
||||
|
||||
std::array<double, 3> kv {};
|
||||
array<double, 3> kv {};
|
||||
xt::xtensor<double, 2> cov = xt::zeros<double>({3, 3});
|
||||
kv[0] = gt(GlobalTally::K_COLLISION, TallyResult::SUM) / n;
|
||||
kv[1] = gt(GlobalTally::K_ABSORPTION, TallyResult::SUM) / n;
|
||||
|
|
@ -427,7 +427,7 @@ int openmc_get_keff(double* k_combined)
|
|||
|
||||
// Initialize variables
|
||||
double g = 0.0;
|
||||
std::array<double, 3> S {};
|
||||
array<double, 3> S {};
|
||||
|
||||
for (int l = 0; l < 3; ++l) {
|
||||
// Permutations of estimates
|
||||
|
|
@ -601,7 +601,7 @@ void write_eigenvalue_hdf5(hid_t group)
|
|||
write_dataset(group, "k_col_abs", simulation::k_col_abs);
|
||||
write_dataset(group, "k_col_tra", simulation::k_col_tra);
|
||||
write_dataset(group, "k_abs_tra", simulation::k_abs_tra);
|
||||
std::array<double, 2> k_combined;
|
||||
array<double, 2> k_combined;
|
||||
openmc_get_keff(k_combined.data());
|
||||
write_dataset(group, "k_combined", k_combined);
|
||||
}
|
||||
|
|
|
|||
19
src/endf.cpp
19
src/endf.cpp
|
|
@ -1,7 +1,6 @@
|
|||
#include "openmc/endf.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
#include <array>
|
||||
#include <cmath> // for log, exp
|
||||
#include <iterator> // for back_inserter
|
||||
#include <stdexcept> // for runtime_error
|
||||
|
|
@ -9,6 +8,7 @@
|
|||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/search.h"
|
||||
|
|
@ -77,21 +77,20 @@ bool is_inelastic_scatter(int mt)
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Function1D>
|
||||
read_function(hid_t group, const char* name)
|
||||
unique_ptr<Function1D> read_function(hid_t group, const char* name)
|
||||
{
|
||||
hid_t dset = open_dataset(group, name);
|
||||
std::string func_type;
|
||||
read_attribute(dset, "type", func_type);
|
||||
std::unique_ptr<Function1D> func;
|
||||
unique_ptr<Function1D> func;
|
||||
if (func_type == "Tabulated1D") {
|
||||
func = std::make_unique<Tabulated1D>(dset);
|
||||
func = make_unique<Tabulated1D>(dset);
|
||||
} else if (func_type == "Polynomial") {
|
||||
func = std::make_unique<Polynomial>(dset);
|
||||
func = make_unique<Polynomial>(dset);
|
||||
} else if (func_type == "CoherentElastic") {
|
||||
func = std::make_unique<CoherentElasticXS>(dset);
|
||||
func = make_unique<CoherentElasticXS>(dset);
|
||||
} else if (func_type == "IncoherentElastic") {
|
||||
func = std::make_unique<IncoherentElasticXS>(dset);
|
||||
func = make_unique<IncoherentElasticXS>(dset);
|
||||
} else {
|
||||
throw std::runtime_error{"Unknown function type " + func_type +
|
||||
" for dataset " + object_name(dset)};
|
||||
|
|
@ -133,7 +132,7 @@ Tabulated1D::Tabulated1D(hid_t dset)
|
|||
// Change 1-indexing to 0-indexing
|
||||
for (auto& b : nbt_) --b;
|
||||
|
||||
std::vector<int> int_temp;
|
||||
vector<int> int_temp;
|
||||
read_attribute(dset, "interpolation", int_temp);
|
||||
|
||||
// Convert vector of ints into Interpolation
|
||||
|
|
@ -245,7 +244,7 @@ double CoherentElasticXS::operator()(double E) const
|
|||
|
||||
IncoherentElasticXS::IncoherentElasticXS(hid_t dset)
|
||||
{
|
||||
std::array<double, 2> tmp;
|
||||
array<double, 2> tmp;
|
||||
read_dataset(dset, nullptr, tmp);
|
||||
bound_xs_ = tmp[0];
|
||||
debye_waller_ = tmp[1];
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ SharedArray<EventQueueItem> advance_particle_queue;
|
|||
SharedArray<EventQueueItem> surface_crossing_queue;
|
||||
SharedArray<EventQueueItem> collision_queue;
|
||||
|
||||
std::vector<Particle> particles;
|
||||
vector<Particle> particles;
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
|
|
@ -50,7 +50,8 @@ void free_event_queues(void)
|
|||
void dispatch_xs_event(int64_t buffer_idx)
|
||||
{
|
||||
Particle& p = simulation::particles[buffer_idx];
|
||||
if (p.material_ == MATERIAL_VOID || !model::materials[p.material_]->fissionable_) {
|
||||
if (p.material() == MATERIAL_VOID ||
|
||||
!model::materials[p.material()]->fissionable_) {
|
||||
simulation::calculate_nonfuel_xs_queue.thread_safe_append({p, buffer_idx});
|
||||
} else {
|
||||
simulation::calculate_fuel_xs_queue.thread_safe_append({p, buffer_idx});
|
||||
|
|
@ -109,7 +110,7 @@ void process_advance_particle_events()
|
|||
int64_t buffer_idx = simulation::advance_particle_queue[i].idx;
|
||||
Particle& p = simulation::particles[buffer_idx];
|
||||
p.event_advance();
|
||||
if (p.collision_distance_ > p.boundary_.distance) {
|
||||
if (p.collision_distance() > p.boundary().distance) {
|
||||
simulation::surface_crossing_queue.thread_safe_append({p, buffer_idx});
|
||||
} else {
|
||||
simulation::collision_queue.thread_safe_append({p, buffer_idx});
|
||||
|
|
@ -131,7 +132,7 @@ void process_surface_crossing_events()
|
|||
Particle& p = simulation::particles[buffer_idx];
|
||||
p.event_cross_surface();
|
||||
p.event_revive_from_secondary();
|
||||
if (p.alive_)
|
||||
if (p.alive())
|
||||
dispatch_xs_event(buffer_idx);
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +151,7 @@ void process_collision_events()
|
|||
Particle& p = simulation::particles[buffer_idx];
|
||||
p.event_collide();
|
||||
p.event_revive_from_secondary();
|
||||
if (p.alive_)
|
||||
if (p.alive())
|
||||
dispatch_xs_event(buffer_idx);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ int openmc_finalize()
|
|||
|
||||
// Free all MPI types
|
||||
#ifdef OPENMC_MPI
|
||||
if (mpi::bank != MPI_DATATYPE_NULL) MPI_Type_free(&mpi::bank);
|
||||
if (mpi::source_site != MPI_DATATYPE_NULL) MPI_Type_free(&mpi::source_site);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
158
src/geometry.cpp
158
src/geometry.cpp
|
|
@ -1,10 +1,9 @@
|
|||
#include "openmc/geometry.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -27,7 +26,7 @@ namespace model {
|
|||
int root_universe {-1};
|
||||
int n_coord_levels;
|
||||
|
||||
std::vector<int64_t> overlap_check_count;
|
||||
vector<int64_t> overlap_check_count;
|
||||
|
||||
} // namespace model
|
||||
|
||||
|
|
@ -37,25 +36,25 @@ std::vector<int64_t> overlap_check_count;
|
|||
|
||||
bool check_cell_overlap(Particle& p, bool error)
|
||||
{
|
||||
int n_coord = p.n_coord_;
|
||||
int n_coord = p.n_coord();
|
||||
|
||||
// Loop through each coordinate level
|
||||
for (int j = 0; j < n_coord; j++) {
|
||||
Universe& univ = *model::universes[p.coord_[j].universe];
|
||||
Universe& univ = *model::universes[p.coord(j).universe];
|
||||
|
||||
// Loop through each cell on this level
|
||||
for (auto index_cell : univ.cells_) {
|
||||
Cell& c = *model::cells[index_cell];
|
||||
if (c.contains(p.coord_[j].r, p.coord_[j].u, p.surface_)) {
|
||||
if (index_cell != p.coord_[j].cell) {
|
||||
if (c.contains(p.coord(j).r, p.coord(j).u, p.surface())) {
|
||||
if (index_cell != p.coord(j).cell) {
|
||||
if (error) {
|
||||
fatal_error(fmt::format(
|
||||
"Overlapping cells detected: {}, {} on universe {}",
|
||||
c.id_, model::cells[p.coord_[j].cell]->id_, univ.id_));
|
||||
fatal_error(
|
||||
fmt::format("Overlapping cells detected: {}, {} on universe {}",
|
||||
c.id_, model::cells[p.coord(j).cell]->id_, univ.id_));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#pragma omp atomic
|
||||
#pragma omp atomic
|
||||
++model::overlap_check_count[index_cell];
|
||||
}
|
||||
}
|
||||
|
|
@ -78,15 +77,15 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
i_cell = *it;
|
||||
|
||||
// Make sure the search cell is in the same universe.
|
||||
int i_universe = p.coord_[p.n_coord_-1].universe;
|
||||
int i_universe = p.coord(p.n_coord() - 1).universe;
|
||||
if (model::cells[i_cell]->universe_ != i_universe) continue;
|
||||
|
||||
// Check if this cell contains the particle.
|
||||
Position r {p.r_local()};
|
||||
Direction u {p.u_local()};
|
||||
auto surf = p.surface_;
|
||||
auto surf = p.surface();
|
||||
if (model::cells[i_cell]->contains(r, u, surf)) {
|
||||
p.coord_[p.n_coord_-1].cell = i_cell;
|
||||
p.coord(p.n_coord() - 1).cell = i_cell;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -102,7 +101,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
}
|
||||
|
||||
// Check successively lower coordinate levels until finding material fill
|
||||
for (;;++p.n_coord_) {
|
||||
for (;;++p.n_coord()) {
|
||||
// If we did not attempt to use neighbor lists, i_cell is still C_NONE. In
|
||||
// that case, we should now do an exhaustive search to find the right value
|
||||
// of i_cell.
|
||||
|
|
@ -112,7 +111,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
// code below this conditional, we set i_cell back to C_NONE to indicate
|
||||
// that.
|
||||
if (i_cell == C_NONE) {
|
||||
int i_universe = p.coord_[p.n_coord_-1].universe;
|
||||
int i_universe = p.coord(p.n_coord() - 1).universe;
|
||||
const auto& univ {*model::universes[i_universe]};
|
||||
const auto& cells {
|
||||
!univ.partitioner_
|
||||
|
|
@ -124,15 +123,15 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
i_cell = *it;
|
||||
|
||||
// Make sure the search cell is in the same universe.
|
||||
int i_universe = p.coord_[p.n_coord_-1].universe;
|
||||
int i_universe = p.coord(p.n_coord() - 1).universe;
|
||||
if (model::cells[i_cell]->universe_ != i_universe) continue;
|
||||
|
||||
// Check if this cell contains the particle.
|
||||
Position r {p.r_local()};
|
||||
Direction u {p.u_local()};
|
||||
auto surf = p.surface_;
|
||||
auto surf = p.surface();
|
||||
if (model::cells[i_cell]->contains(r, u, surf)) {
|
||||
p.coord_[p.n_coord_-1].cell = i_cell;
|
||||
p.coord(p.n_coord() - 1).cell = i_cell;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -143,7 +142,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
}
|
||||
|
||||
// Announce the cell that the particle is entering.
|
||||
if (found && (settings::verbosity >= 10 || p.trace_)) {
|
||||
if (found && (settings::verbosity >= 10 || p.trace())) {
|
||||
auto msg = fmt::format(" Entering cell {}", model::cells[i_cell]->id_);
|
||||
write_message(msg, 1);
|
||||
}
|
||||
|
|
@ -155,34 +154,33 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
// Find the distribcell instance number.
|
||||
int offset = 0;
|
||||
if (c.distribcell_index_ >= 0) {
|
||||
for (int i = 0; i < p.n_coord_; i++) {
|
||||
const auto& c_i {*model::cells[p.coord_[i].cell]};
|
||||
for (int i = 0; i < p.n_coord(); i++) {
|
||||
const auto& c_i {*model::cells[p.coord(i).cell]};
|
||||
if (c_i.type_ == Fill::UNIVERSE) {
|
||||
offset += c_i.offset_[c.distribcell_index_];
|
||||
} else if (c_i.type_ == Fill::LATTICE) {
|
||||
auto& lat {*model::lattices[p.coord_[i + 1].lattice]};
|
||||
int i_xyz[3] {p.coord_[i + 1].lattice_x, p.coord_[i + 1].lattice_y,
|
||||
p.coord_[i + 1].lattice_z};
|
||||
auto& lat {*model::lattices[p.coord(i + 1).lattice]};
|
||||
const auto& i_xyz {p.coord(i + 1).lattice_i};
|
||||
if (lat.are_valid_indices(i_xyz)) {
|
||||
offset += lat.offset(c.distribcell_index_, i_xyz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.cell_instance_ = offset;
|
||||
p.cell_instance() = offset;
|
||||
|
||||
// Set the material and temperature.
|
||||
p.material_last_ = p.material_;
|
||||
p.material_last() = p.material();
|
||||
if (c.material_.size() > 1) {
|
||||
p.material_ = c.material_[p.cell_instance_];
|
||||
p.material() = c.material_[p.cell_instance()];
|
||||
} else {
|
||||
p.material_ = c.material_[0];
|
||||
p.material() = c.material_[0];
|
||||
}
|
||||
p.sqrtkT_last_ = p.sqrtkT_;
|
||||
p.sqrtkT_last() = p.sqrtkT();
|
||||
if (c.sqrtkT_.size() > 1) {
|
||||
p.sqrtkT_ = c.sqrtkT_[p.cell_instance_];
|
||||
p.sqrtkT() = c.sqrtkT_[p.cell_instance()];
|
||||
} else {
|
||||
p.sqrtkT_ = c.sqrtkT_[0];
|
||||
p.sqrtkT() = c.sqrtkT_[0];
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -192,7 +190,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
//! Found a lower universe, update this coord level then search the next.
|
||||
|
||||
// Set the lower coordinate level universe.
|
||||
auto& coord {p.coord_[p.n_coord_]};
|
||||
auto& coord {p.coord(p.n_coord())};
|
||||
coord.universe = c.fill_;
|
||||
|
||||
// Set the position and direction.
|
||||
|
|
@ -214,7 +212,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
Lattice& lat {*model::lattices[c.fill_]};
|
||||
|
||||
// Set the position and direction.
|
||||
auto& coord {p.coord_[p.n_coord_]};
|
||||
auto& coord {p.coord(p.n_coord())};
|
||||
coord.r = p.r_local();
|
||||
coord.u = p.u_local();
|
||||
|
||||
|
|
@ -227,16 +225,14 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
}
|
||||
|
||||
// Determine lattice indices.
|
||||
auto i_xyz = lat.get_indices(coord.r, coord.u);
|
||||
auto& i_xyz {coord.lattice_i};
|
||||
lat.get_indices(coord.r, coord.u, i_xyz);
|
||||
|
||||
// Get local position in appropriate lattice cell
|
||||
coord.r = lat.get_local_position(coord.r, i_xyz);
|
||||
|
||||
// Set lattice indices.
|
||||
coord.lattice = c.fill_;
|
||||
coord.lattice_x = i_xyz[0];
|
||||
coord.lattice_y = i_xyz[1];
|
||||
coord.lattice_z = i_xyz[2];
|
||||
|
||||
// Set the lower coordinate level universe.
|
||||
if (lat.are_valid_indices(i_xyz)) {
|
||||
|
|
@ -247,7 +243,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
|
|||
} else {
|
||||
warning(fmt::format("Particle {} is outside lattice {} but the "
|
||||
"lattice has no defined outer universe.",
|
||||
p.id_, lat.id_));
|
||||
p.id(), lat.id_));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -265,13 +261,13 @@ bool neighbor_list_find_cell(Particle& p)
|
|||
{
|
||||
|
||||
// Reset all the deeper coordinate levels.
|
||||
for (int i = p.n_coord_; i < p.coord_.size(); i++) {
|
||||
p.coord_[i].reset();
|
||||
for (int i = p.n_coord(); i < model::n_coord_levels; i++) {
|
||||
p.coord(i).reset();
|
||||
}
|
||||
|
||||
// Get the cell this particle was in previously.
|
||||
auto coord_lvl = p.n_coord_ - 1;
|
||||
auto i_cell = p.coord_[coord_lvl].cell;
|
||||
auto coord_lvl = p.n_coord() - 1;
|
||||
auto i_cell = p.coord(coord_lvl).cell;
|
||||
Cell& c {*model::cells[i_cell]};
|
||||
|
||||
// Search for the particle in that cell's neighbor list. Return if we
|
||||
|
|
@ -285,21 +281,21 @@ bool neighbor_list_find_cell(Particle& p)
|
|||
// neighboring cell.
|
||||
found = find_cell_inner(p, nullptr);
|
||||
if (found)
|
||||
c.neighbors_.push_back(p.coord_[coord_lvl].cell);
|
||||
c.neighbors_.push_back(p.coord(coord_lvl).cell);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool exhaustive_find_cell(Particle& p)
|
||||
{
|
||||
int i_universe = p.coord_[p.n_coord_-1].universe;
|
||||
int i_universe = p.coord(p.n_coord() - 1).universe;
|
||||
if (i_universe == C_NONE) {
|
||||
p.coord_[0].universe = model::root_universe;
|
||||
p.n_coord_ = 1;
|
||||
p.coord(0).universe = model::root_universe;
|
||||
p.n_coord() = 1;
|
||||
i_universe = model::root_universe;
|
||||
}
|
||||
// Reset all the deeper coordinate levels.
|
||||
for (int i = p.n_coord_; i < p.coord_.size(); i++) {
|
||||
p.coord_[i].reset();
|
||||
for (int i = p.n_coord(); i < model::n_coord_levels; i++) {
|
||||
p.coord(i).reset();
|
||||
}
|
||||
return find_cell_inner(p, nullptr);
|
||||
}
|
||||
|
|
@ -309,53 +305,54 @@ bool exhaustive_find_cell(Particle& p)
|
|||
void
|
||||
cross_lattice(Particle& p, const BoundaryInfo& boundary)
|
||||
{
|
||||
auto& coord {p.coord_[p.n_coord_ - 1]};
|
||||
auto& coord {p.coord(p.n_coord() - 1)};
|
||||
auto& lat {*model::lattices[coord.lattice]};
|
||||
|
||||
if (settings::verbosity >= 10 || p.trace_) {
|
||||
if (settings::verbosity >= 10 || p.trace()) {
|
||||
write_message(fmt::format(
|
||||
" Crossing lattice {}. Current position ({},{},{}). r={}",
|
||||
lat.id_, coord.lattice_x, coord.lattice_y, coord.lattice_z, p.r()), 1);
|
||||
lat.id_, coord.lattice_i[0], coord.lattice_i[1], coord.lattice_i[2], p.r()), 1);
|
||||
}
|
||||
|
||||
// Set the lattice indices.
|
||||
coord.lattice_x += boundary.lattice_translation[0];
|
||||
coord.lattice_y += boundary.lattice_translation[1];
|
||||
coord.lattice_z += boundary.lattice_translation[2];
|
||||
std::array<int, 3> i_xyz {coord.lattice_x, coord.lattice_y, coord.lattice_z};
|
||||
coord.lattice_i[0] += boundary.lattice_translation[0];
|
||||
coord.lattice_i[1] += boundary.lattice_translation[1];
|
||||
coord.lattice_i[2] += boundary.lattice_translation[2];
|
||||
|
||||
// Set the new coordinate position.
|
||||
const auto& upper_coord {p.coord_[p.n_coord_ - 2]};
|
||||
const auto& upper_coord {p.coord(p.n_coord() - 2)};
|
||||
const auto& cell {model::cells[upper_coord.cell]};
|
||||
Position r = upper_coord.r;
|
||||
r -= cell->translation_;
|
||||
if (!cell->rotation_.empty()) {
|
||||
r = r.rotate(cell->rotation_);
|
||||
}
|
||||
p.r_local() = lat.get_local_position(r, i_xyz);
|
||||
p.r_local() = lat.get_local_position(r, coord.lattice_i);
|
||||
|
||||
if (!lat.are_valid_indices(i_xyz)) {
|
||||
if (!lat.are_valid_indices(coord.lattice_i)) {
|
||||
// The particle is outside the lattice. Search for it from the base coords.
|
||||
p.n_coord_ = 1;
|
||||
p.n_coord() = 1;
|
||||
bool found = exhaustive_find_cell(p);
|
||||
if (!found && p.alive_) {
|
||||
if (!found && p.alive()) {
|
||||
p.mark_as_lost(fmt::format("Could not locate particle {} after "
|
||||
"crossing a lattice boundary", p.id_));
|
||||
"crossing a lattice boundary",
|
||||
p.id()));
|
||||
}
|
||||
|
||||
} else {
|
||||
// Find cell in next lattice element.
|
||||
p.coord_[p.n_coord_-1].universe = lat[i_xyz];
|
||||
p.coord(p.n_coord() - 1).universe = lat[coord.lattice_i];
|
||||
bool found = exhaustive_find_cell(p);
|
||||
|
||||
if (!found) {
|
||||
// A particle crossing the corner of a lattice tile may not be found. In
|
||||
// this case, search for it from the base coords.
|
||||
p.n_coord_ = 1;
|
||||
p.n_coord() = 1;
|
||||
bool found = exhaustive_find_cell(p);
|
||||
if (!found && p.alive_) {
|
||||
if (!found && p.alive()) {
|
||||
p.mark_as_lost(fmt::format("Could not locate particle {} after "
|
||||
"crossing a lattice boundary", p.id_));
|
||||
"crossing a lattice boundary",
|
||||
p.id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -369,40 +366,39 @@ BoundaryInfo distance_to_boundary(Particle& p)
|
|||
double d_lat = INFINITY;
|
||||
double d_surf = INFINITY;
|
||||
int32_t level_surf_cross;
|
||||
std::array<int, 3> level_lat_trans {};
|
||||
array<int, 3> level_lat_trans {};
|
||||
|
||||
// Loop over each coordinate level.
|
||||
for (int i = 0; i < p.n_coord_; i++) {
|
||||
const auto& coord {p.coord_[i]};
|
||||
Position r {coord.r};
|
||||
Direction u {coord.u};
|
||||
for (int i = 0; i < p.n_coord(); i++) {
|
||||
const auto& coord {p.coord(i)};
|
||||
const Position& r {coord.r};
|
||||
const Direction& u {coord.u};
|
||||
Cell& c {*model::cells[coord.cell]};
|
||||
|
||||
// Find the oncoming surface in this cell and the distance to it.
|
||||
auto surface_distance = c.distance(r, u, p.surface_, &p);
|
||||
auto surface_distance = c.distance(r, u, p.surface(), &p);
|
||||
d_surf = surface_distance.first;
|
||||
level_surf_cross = surface_distance.second;
|
||||
|
||||
// Find the distance to the next lattice tile crossing.
|
||||
if (coord.lattice != C_NONE) {
|
||||
auto& lat {*model::lattices[coord.lattice]};
|
||||
std::array<int, 3> i_xyz {coord.lattice_x, coord.lattice_y, coord.lattice_z};
|
||||
//TODO: refactor so both lattice use the same position argument (which
|
||||
//also means the lat.type attribute can be removed)
|
||||
std::pair<double, std::array<int, 3>> lattice_distance;
|
||||
std::pair<double, array<int, 3>> lattice_distance;
|
||||
switch (lat.type_) {
|
||||
case LatticeType::rect:
|
||||
lattice_distance = lat.distance(r, u, i_xyz);
|
||||
lattice_distance = lat.distance(r, u, coord.lattice_i);
|
||||
break;
|
||||
case LatticeType::hex:
|
||||
auto& cell_above {model::cells[p.coord_[i-1].cell]};
|
||||
Position r_hex {p.coord_[i-1].r};
|
||||
auto& cell_above {model::cells[p.coord(i - 1).cell]};
|
||||
Position r_hex {p.coord(i - 1).r};
|
||||
r_hex -= cell_above->translation_;
|
||||
if (coord.rotated) {
|
||||
r_hex = r_hex.rotate(cell_above->rotation_);
|
||||
}
|
||||
r_hex.z = coord.r.z;
|
||||
lattice_distance = lat.distance(r_hex, u, i_xyz);
|
||||
lattice_distance = lat.distance(r_hex, u, coord.lattice_i);
|
||||
break;
|
||||
}
|
||||
d_lat = lattice_distance.first;
|
||||
|
|
@ -410,7 +406,7 @@ BoundaryInfo distance_to_boundary(Particle& p)
|
|||
|
||||
if (d_lat < 0) {
|
||||
p.mark_as_lost(fmt::format(
|
||||
"Particle {} had a negative distance to a lattice boundary", p.id_));
|
||||
"Particle {} had a negative distance to a lattice boundary", p.id()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -473,8 +469,8 @@ openmc_find_cell(const double* xyz, int32_t* index, int32_t* instance)
|
|||
return OPENMC_E_GEOMETRY;
|
||||
}
|
||||
|
||||
*index = p.coord_[p.n_coord_-1].cell;
|
||||
*instance = p.cell_instance_;
|
||||
*index = p.coord(p.n_coord() - 1).cell;
|
||||
*instance = p.cell_instance();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ partition_universes()
|
|||
if (dynamic_cast<const SurfaceZPlane*>(model::surfaces[i_surf].get())) {
|
||||
++n_zplanes;
|
||||
if (n_zplanes > 5) {
|
||||
univ->partitioner_ = std::make_unique<UniversePartitioner>(*univ);
|
||||
univ->partitioner_ = make_unique<UniversePartitioner>(*univ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -191,9 +191,8 @@ assign_temperatures()
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
get_temperatures(std::vector<std::vector<double>>& nuc_temps,
|
||||
std::vector<std::vector<double>>& thermal_temps)
|
||||
void get_temperatures(
|
||||
vector<vector<double>>& nuc_temps, vector<vector<double>>& thermal_temps)
|
||||
{
|
||||
for (const auto& cell : model::cells) {
|
||||
// Skip non-material cells.
|
||||
|
|
@ -205,7 +204,7 @@ get_temperatures(std::vector<std::vector<double>>& nuc_temps,
|
|||
if (i_material == MATERIAL_VOID) continue;
|
||||
|
||||
// Get temperature(s) of cell (rounding to nearest integer)
|
||||
std::vector<double> cell_temps;
|
||||
vector<double> cell_temps;
|
||||
if (cell->sqrtkT_.size() == 1) {
|
||||
double sqrtkT = cell->sqrtkT_[0];
|
||||
cell_temps.push_back(sqrtkT*sqrtkT / K_BOLTZMANN);
|
||||
|
|
@ -351,7 +350,7 @@ prepare_distribcell()
|
|||
// Search through universes for material cells and assign each one a
|
||||
// unique distribcell array index.
|
||||
int distribcell_index = 0;
|
||||
std::vector<int32_t> target_univ_ids;
|
||||
vector<int32_t> target_univ_ids;
|
||||
for (const auto& u : model::universes) {
|
||||
for (auto idx : u->cells_) {
|
||||
if (distribcells.find(idx) != distribcells.end()) {
|
||||
|
|
@ -495,8 +494,8 @@ distribcell_path_inner(int32_t target_cell, int32_t map, int32_t target_offset,
|
|||
// The target must be further down the geometry tree and contained in a fill
|
||||
// cell or lattice cell in this universe. Find which cell contains the
|
||||
// target.
|
||||
std::vector<std::int32_t>::const_reverse_iterator cell_it
|
||||
{search_univ.cells_.crbegin()};
|
||||
vector<std::int32_t>::const_reverse_iterator cell_it {
|
||||
search_univ.cells_.crbegin()};
|
||||
for (; cell_it != search_univ.cells_.crend(); ++cell_it) {
|
||||
Cell& c = *model::cells[*cell_it];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "openmc/hdf5_interface.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
|
@ -16,6 +15,7 @@
|
|||
#include "openmc/message_passing.h"
|
||||
#endif
|
||||
|
||||
#include "openmc/array.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -56,16 +56,15 @@ get_shape(hid_t obj_id, hsize_t* dims)
|
|||
H5Sclose(dspace);
|
||||
}
|
||||
|
||||
|
||||
std::vector<hsize_t> attribute_shape(hid_t obj_id, const char* name)
|
||||
vector<hsize_t> attribute_shape(hid_t obj_id, const char* name)
|
||||
{
|
||||
hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
|
||||
std::vector<hsize_t> shape = object_shape(attr);
|
||||
vector<hsize_t> shape = object_shape(attr);
|
||||
H5Aclose(attr);
|
||||
return shape;
|
||||
}
|
||||
|
||||
std::vector<hsize_t> object_shape(hid_t obj_id)
|
||||
vector<hsize_t> object_shape(hid_t obj_id)
|
||||
{
|
||||
// Get number of dimensions
|
||||
auto type = H5Iget_type(obj_id);
|
||||
|
|
@ -81,7 +80,7 @@ std::vector<hsize_t> object_shape(hid_t obj_id)
|
|||
int n = H5Sget_simple_extent_ndims(dspace);
|
||||
|
||||
// Get shape of array
|
||||
std::vector<hsize_t> shape(n);
|
||||
vector<hsize_t> shape(n);
|
||||
H5Sget_simple_extent_dims(dspace, shape.data(), nullptr);
|
||||
|
||||
// Free resources and return
|
||||
|
|
@ -337,8 +336,7 @@ get_groups(hid_t group_id, char* name[])
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
member_names(hid_t group_id, H5O_type_t type)
|
||||
vector<std::string> member_names(hid_t group_id, H5O_type_t type)
|
||||
{
|
||||
// Determine number of links in the group
|
||||
H5G_info_t info;
|
||||
|
|
@ -347,7 +345,7 @@ member_names(hid_t group_id, H5O_type_t type)
|
|||
// Iterate over links to get names
|
||||
H5O_info_t oinfo;
|
||||
size_t size;
|
||||
std::vector<std::string> names;
|
||||
vector<std::string> names;
|
||||
for (hsize_t i = 0; i < info.nlinks; ++i) {
|
||||
// Determine type of object (and skip non-group)
|
||||
H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo,
|
||||
|
|
@ -368,14 +366,12 @@ member_names(hid_t group_id, H5O_type_t type)
|
|||
return names;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
group_names(hid_t group_id)
|
||||
vector<std::string> group_names(hid_t group_id)
|
||||
{
|
||||
return member_names(group_id, H5O_TYPE_GROUP);
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
dataset_names(hid_t group_id)
|
||||
vector<std::string> dataset_names(hid_t group_id)
|
||||
{
|
||||
return member_names(group_id, H5O_TYPE_DATASET);
|
||||
}
|
||||
|
|
@ -492,13 +488,13 @@ template<>
|
|||
void read_dataset(hid_t dset, xt::xarray<std::complex<double>>& arr, bool indep)
|
||||
{
|
||||
// Get shape of dataset
|
||||
std::vector<hsize_t> shape = object_shape(dset);
|
||||
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;
|
||||
std::vector<std::complex<double>> buffer(size);
|
||||
vector<std::complex<double>> buffer(size);
|
||||
|
||||
// Read data from attribute
|
||||
read_complex(dset, nullptr, buffer.data(), indep);
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@
|
|||
#include <cstddef>
|
||||
#include <cstdlib> // for getenv
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
|
|
@ -19,6 +17,7 @@
|
|||
#include "openmc/geometry_aux.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/material.h"
|
||||
#include "openmc/memory.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/mgxs_interface.h"
|
||||
#include "openmc/nuclide.h"
|
||||
|
|
@ -32,6 +31,7 @@
|
|||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/thermal.h"
|
||||
#include "openmc/timer.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#ifdef LIBMESH
|
||||
#include "libmesh/libmesh.h"
|
||||
|
|
@ -74,10 +74,12 @@ if (!settings::libmesh_init && !libMesh::initialized()) {
|
|||
// pass command line args, empty MPI communicator, and number of threads.
|
||||
// Because libMesh was not initialized, we assume that OpenMC is the primary
|
||||
// application and that its main MPI comm should be used.
|
||||
settings::libmesh_init = std::make_unique<libMesh::LibMeshInit>(argc, argv, comm, n_threads);
|
||||
settings::libmesh_init =
|
||||
make_unique<libMesh::LibMeshInit>(argc, argv, comm, n_threads);
|
||||
#else
|
||||
// pass command line args, empty MPI communicator, and number of threads
|
||||
settings::libmesh_init = std::make_unique<libMesh::LibMeshInit>(argc, argv, 0, n_threads);
|
||||
settings::libmesh_init =
|
||||
make_unique<libMesh::LibMeshInit>(argc, argv, 0, n_threads);
|
||||
#endif
|
||||
|
||||
settings::libmesh_comm = &(settings::libmesh_init->comm());
|
||||
|
|
@ -132,7 +134,7 @@ void initialize_mpi(MPI_Comm intracomm)
|
|||
mpi::master = (mpi::rank == 0);
|
||||
|
||||
// Create bank datatype
|
||||
Particle::Bank b;
|
||||
SourceSite b;
|
||||
MPI_Aint disp[9];
|
||||
MPI_Get_address(&b.r, &disp[0]);
|
||||
MPI_Get_address(&b.u, &disp[1]);
|
||||
|
|
@ -149,8 +151,8 @@ void initialize_mpi(MPI_Comm intracomm)
|
|||
|
||||
int blocks[] {3, 3, 1, 1, 1, 1, 1, 1, 1};
|
||||
MPI_Datatype types[] {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_LONG, MPI_LONG};
|
||||
MPI_Type_create_struct(9, blocks, disp, types, &mpi::bank);
|
||||
MPI_Type_commit(&mpi::bank);
|
||||
MPI_Type_create_struct(9, blocks, disp, types, &mpi::source_site);
|
||||
MPI_Type_commit(&mpi::source_site);
|
||||
}
|
||||
#endif // OPENMC_MPI
|
||||
|
||||
|
|
|
|||
191
src/lattice.cpp
191
src/lattice.cpp
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
|
|
@ -12,9 +11,9 @@
|
|||
#include "openmc/geometry_aux.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/string_utils.h"
|
||||
#include "openmc/vector.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -23,7 +22,7 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
std::unordered_map<int32_t, int32_t> lattice_map;
|
||||
std::vector<std::unique_ptr<Lattice>> lattices;
|
||||
vector<unique_ptr<Lattice>> lattices;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -142,7 +141,7 @@ RectLattice::RectLattice(pugi::xml_node lat_node)
|
|||
|
||||
// Read the number of lattice cells in each dimension.
|
||||
std::string dimension_str {get_node_value(lat_node, "dimension")};
|
||||
std::vector<std::string> dimension_words {split(dimension_str)};
|
||||
vector<std::string> dimension_words {split(dimension_str)};
|
||||
if (dimension_words.size() == 2) {
|
||||
n_cells_[0] = std::stoi(dimension_words[0]);
|
||||
n_cells_[1] = std::stoi(dimension_words[1]);
|
||||
|
|
@ -159,7 +158,7 @@ RectLattice::RectLattice(pugi::xml_node lat_node)
|
|||
|
||||
// Read the lattice lower-left location.
|
||||
std::string ll_str {get_node_value(lat_node, "lower_left")};
|
||||
std::vector<std::string> ll_words {split(ll_str)};
|
||||
vector<std::string> ll_words {split(ll_str)};
|
||||
if (ll_words.size() != dimension_words.size()) {
|
||||
fatal_error("Number of entries on <lower_left> must be the same as the "
|
||||
"number of entries on <dimension>.");
|
||||
|
|
@ -170,7 +169,7 @@ RectLattice::RectLattice(pugi::xml_node lat_node)
|
|||
|
||||
// Read the lattice pitches.
|
||||
std::string pitch_str {get_node_value(lat_node, "pitch")};
|
||||
std::vector<std::string> pitch_words {split(pitch_str)};
|
||||
vector<std::string> pitch_words {split(pitch_str)};
|
||||
if (pitch_words.size() != dimension_words.size()) {
|
||||
fatal_error("Number of entries on <pitch> must be the same as the "
|
||||
"number of entries on <dimension>.");
|
||||
|
|
@ -181,20 +180,23 @@ RectLattice::RectLattice(pugi::xml_node lat_node)
|
|||
|
||||
// Read the universes and make sure the correct number was specified.
|
||||
std::string univ_str {get_node_value(lat_node, "universes")};
|
||||
std::vector<std::string> univ_words {split(univ_str)};
|
||||
if (univ_words.size() != nx*ny*nz) {
|
||||
vector<std::string> univ_words {split(univ_str)};
|
||||
if (univ_words.size() != n_cells_[0] * n_cells_[1] * n_cells_[2]) {
|
||||
fatal_error(fmt::format(
|
||||
"Expected {} universes for a rectangular lattice of size {}x{}x{} but {} "
|
||||
"were specified.", nx*ny*nz, nx, ny, nz, univ_words.size()));
|
||||
"were specified.",
|
||||
n_cells_[0] * n_cells_[1] * n_cells_[2], n_cells_[0], n_cells_[1],
|
||||
n_cells_[2], univ_words.size()));
|
||||
}
|
||||
|
||||
// Parse the universes.
|
||||
universes_.resize(nx*ny*nz, C_NONE);
|
||||
for (int iz = 0; iz < nz; iz++) {
|
||||
for (int iy = ny-1; iy > -1; iy--) {
|
||||
for (int ix = 0; ix < nx; ix++) {
|
||||
int indx1 = nx*ny*iz + nx*(ny-iy-1) + ix;
|
||||
int indx2 = nx*ny*iz + nx*iy + ix;
|
||||
universes_.resize(n_cells_[0] * n_cells_[1] * n_cells_[2], C_NONE);
|
||||
for (int iz = 0; iz < n_cells_[2]; iz++) {
|
||||
for (int iy = n_cells_[1] - 1; iy > -1; iy--) {
|
||||
for (int ix = 0; ix < n_cells_[0]; ix++) {
|
||||
int indx1 = n_cells_[0] * n_cells_[1] * iz +
|
||||
n_cells_[0] * (n_cells_[1] - iy - 1) + ix;
|
||||
int indx2 = n_cells_[0] * n_cells_[1] * iz + n_cells_[0] * iy + ix;
|
||||
universes_[indx1] = std::stoi(univ_words[indx2]);
|
||||
}
|
||||
}
|
||||
|
|
@ -203,17 +205,16 @@ RectLattice::RectLattice(pugi::xml_node lat_node)
|
|||
|
||||
//==============================================================================
|
||||
|
||||
int32_t&
|
||||
RectLattice::operator[](std::array<int, 3> i_xyz)
|
||||
int32_t const& RectLattice::operator[](array<int, 3> const& i_xyz)
|
||||
{
|
||||
int indx = nx*ny*i_xyz[2] + nx*i_xyz[1] + i_xyz[0];
|
||||
int indx =
|
||||
n_cells_[0] * n_cells_[1] * i_xyz[2] + n_cells_[0] * i_xyz[1] + i_xyz[0];
|
||||
return universes_[indx];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
bool
|
||||
RectLattice::are_valid_indices(const int i_xyz[3]) const
|
||||
bool RectLattice::are_valid_indices(array<int, 3> const& i_xyz) const
|
||||
{
|
||||
return ( (i_xyz[0] >= 0) && (i_xyz[0] < n_cells_[0])
|
||||
&& (i_xyz[1] >= 0) && (i_xyz[1] < n_cells_[1])
|
||||
|
|
@ -222,9 +223,8 @@ RectLattice::are_valid_indices(const int i_xyz[3]) const
|
|||
|
||||
//==============================================================================
|
||||
|
||||
std::pair<double, std::array<int, 3>>
|
||||
RectLattice::distance(Position r, Direction u, const std::array<int, 3>& i_xyz)
|
||||
const
|
||||
std::pair<double, array<int, 3>> RectLattice::distance(
|
||||
Position r, Direction u, const array<int, 3>& i_xyz) const
|
||||
{
|
||||
// Get short aliases to the coordinates.
|
||||
double x = r.x;
|
||||
|
|
@ -237,7 +237,7 @@ const
|
|||
|
||||
// Left and right sides
|
||||
double d {INFTY};
|
||||
std::array<int, 3> lattice_trans;
|
||||
array<int, 3> lattice_trans;
|
||||
if ((std::abs(x - x0) > FP_PRECISION) && u.x != 0) {
|
||||
d = (x0 - x) / u.x;
|
||||
if (u.x > 0) {
|
||||
|
|
@ -281,48 +281,44 @@ const
|
|||
|
||||
//==============================================================================
|
||||
|
||||
std::array<int, 3>
|
||||
RectLattice::get_indices(Position r, Direction u) const
|
||||
void RectLattice::get_indices(
|
||||
Position r, Direction u, array<int, 3>& result) const
|
||||
{
|
||||
// Determine x index, accounting for coincidence
|
||||
double ix_ {(r.x - lower_left_.x) / pitch_.x};
|
||||
long ix_close {std::lround(ix_)};
|
||||
int ix;
|
||||
if (coincident(ix_, ix_close)) {
|
||||
ix = (u.x > 0) ? ix_close : ix_close - 1;
|
||||
result[0] = (u.x > 0) ? ix_close : ix_close - 1;
|
||||
} else {
|
||||
ix = std::floor(ix_);
|
||||
result[0] = std::floor(ix_);
|
||||
}
|
||||
|
||||
// Determine y index, accounting for coincidence
|
||||
double iy_ {(r.y - lower_left_.y) / pitch_.y};
|
||||
long iy_close {std::lround(iy_)};
|
||||
int iy;
|
||||
if (coincident(iy_, iy_close)) {
|
||||
iy = (u.y > 0) ? iy_close : iy_close - 1;
|
||||
result[1] = (u.y > 0) ? iy_close : iy_close - 1;
|
||||
} else {
|
||||
iy = std::floor(iy_);
|
||||
result[1] = std::floor(iy_);
|
||||
}
|
||||
|
||||
// Determine z index, accounting for coincidence
|
||||
int iz = 0;
|
||||
result[2] = 0;
|
||||
if (is_3d_) {
|
||||
double iz_ {(r.z - lower_left_.z) / pitch_.z};
|
||||
long iz_close {std::lround(iz_)};
|
||||
if (coincident(iz_, iz_close)) {
|
||||
iz = (u.z > 0) ? iz_close : iz_close - 1;
|
||||
result[2] = (u.z > 0) ? iz_close : iz_close - 1;
|
||||
} else {
|
||||
iz = std::floor(iz_);
|
||||
result[2] = std::floor(iz_);
|
||||
}
|
||||
}
|
||||
return {ix, iy, iz};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
Position
|
||||
RectLattice::get_local_position(Position r, const std::array<int, 3> i_xyz)
|
||||
const
|
||||
Position RectLattice::get_local_position(
|
||||
Position r, const array<int, 3>& i_xyz) const
|
||||
{
|
||||
r.x -= (lower_left_.x + (i_xyz[0] + 0.5)*pitch_.x);
|
||||
r.y -= (lower_left_.y + (i_xyz[1] + 0.5)*pitch_.y);
|
||||
|
|
@ -334,10 +330,11 @@ const
|
|||
|
||||
//==============================================================================
|
||||
|
||||
int32_t&
|
||||
RectLattice::offset(int map, const int i_xyz[3])
|
||||
int32_t& RectLattice::offset(int map, array<int, 3> const& i_xyz)
|
||||
{
|
||||
return offsets_[nx*ny*nz*map + nx*ny*i_xyz[2] + nx*i_xyz[1] + i_xyz[0]];
|
||||
return offsets_[n_cells_[0] * n_cells_[1] * n_cells_[2] * map +
|
||||
n_cells_[0] * n_cells_[1] * i_xyz[2] +
|
||||
n_cells_[0] * i_xyz[1] + i_xyz[0]];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -345,7 +342,7 @@ RectLattice::offset(int map, const int i_xyz[3])
|
|||
int32_t
|
||||
RectLattice::offset(int map, int indx) const
|
||||
{
|
||||
return offsets_[nx*ny*nz*map + indx];
|
||||
return offsets_[n_cells_[0] * n_cells_[1] * n_cells_[2] * map + indx];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -353,9 +350,9 @@ RectLattice::offset(int map, int indx) const
|
|||
std::string
|
||||
RectLattice::index_to_string(int indx) const
|
||||
{
|
||||
int iz {indx / (nx * ny)};
|
||||
int iy {(indx - nx * ny * iz) / nx};
|
||||
int ix {indx - nx * ny * iz - nx * iy};
|
||||
int iz {indx / (n_cells_[0] * n_cells_[1])};
|
||||
int iy {(indx - n_cells_[0] * n_cells_[1] * iz) / n_cells_[0]};
|
||||
int ix {indx - n_cells_[0] * n_cells_[1] * iz - n_cells_[0] * iy};
|
||||
std::string out {std::to_string(ix)};
|
||||
out += ',';
|
||||
out += std::to_string(iy);
|
||||
|
|
@ -378,11 +375,11 @@ RectLattice::to_hdf5_inner(hid_t lat_group) const
|
|||
write_dataset(lat_group, "lower_left", lower_left_);
|
||||
write_dataset(lat_group, "dimension", n_cells_);
|
||||
} else {
|
||||
std::array<double, 2> pitch_short {{pitch_[0], pitch_[1]}};
|
||||
array<double, 2> pitch_short {{pitch_[0], pitch_[1]}};
|
||||
write_dataset(lat_group, "pitch", pitch_short);
|
||||
std::array<double, 2> ll_short {{lower_left_[0], lower_left_[1]}};
|
||||
array<double, 2> ll_short {{lower_left_[0], lower_left_[1]}};
|
||||
write_dataset(lat_group, "lower_left", ll_short);
|
||||
std::array<int, 2> nc_short {{n_cells_[0], n_cells_[1]}};
|
||||
array<int, 2> nc_short {{n_cells_[0], n_cells_[1]}};
|
||||
write_dataset(lat_group, "dimension", nc_short);
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +389,7 @@ RectLattice::to_hdf5_inner(hid_t lat_group) const
|
|||
hsize_t nx {static_cast<hsize_t>(n_cells_[0])};
|
||||
hsize_t ny {static_cast<hsize_t>(n_cells_[1])};
|
||||
hsize_t nz {static_cast<hsize_t>(n_cells_[2])};
|
||||
std::vector<int> out(nx*ny*nz);
|
||||
vector<int> out(nx * ny * nz);
|
||||
|
||||
for (int m = 0; m < nz; m++) {
|
||||
for (int k = 0; k < ny; k++) {
|
||||
|
|
@ -410,7 +407,7 @@ RectLattice::to_hdf5_inner(hid_t lat_group) const
|
|||
} else {
|
||||
hsize_t nx {static_cast<hsize_t>(n_cells_[0])};
|
||||
hsize_t ny {static_cast<hsize_t>(n_cells_[1])};
|
||||
std::vector<int> out(nx*ny);
|
||||
vector<int> out(nx * ny);
|
||||
|
||||
for (int k = 0; k < ny; k++) {
|
||||
for (int j = 0; j < nx; j++) {
|
||||
|
|
@ -461,7 +458,7 @@ HexLattice::HexLattice(pugi::xml_node lat_node)
|
|||
|
||||
// Read the lattice center.
|
||||
std::string center_str {get_node_value(lat_node, "center")};
|
||||
std::vector<std::string> center_words {split(center_str)};
|
||||
vector<std::string> center_words {split(center_str)};
|
||||
if (is_3d_ && (center_words.size() != 3)) {
|
||||
fatal_error("A hexagonal lattice with <n_axial> must have <center> "
|
||||
"specified by 3 numbers.");
|
||||
|
|
@ -475,7 +472,7 @@ HexLattice::HexLattice(pugi::xml_node lat_node)
|
|||
|
||||
// Read the lattice pitches.
|
||||
std::string pitch_str {get_node_value(lat_node, "pitch")};
|
||||
std::vector<std::string> pitch_words {split(pitch_str)};
|
||||
vector<std::string> pitch_words {split(pitch_str)};
|
||||
if (is_3d_ && (pitch_words.size() != 2)) {
|
||||
fatal_error("A hexagonal lattice with <n_axial> must have <pitch> "
|
||||
"specified by 2 numbers.");
|
||||
|
|
@ -489,7 +486,7 @@ HexLattice::HexLattice(pugi::xml_node lat_node)
|
|||
// Read the universes and make sure the correct number was specified.
|
||||
int n_univ = (3*n_rings_*n_rings_ - 3*n_rings_ + 1) * n_axial_;
|
||||
std::string univ_str {get_node_value(lat_node, "universes")};
|
||||
std::vector<std::string> univ_words {split(univ_str)};
|
||||
vector<std::string> univ_words {split(univ_str)};
|
||||
if (univ_words.size() != n_univ) {
|
||||
fatal_error(fmt::format(
|
||||
"Expected {} universes for a hexagonal lattice with {} rings and {} "
|
||||
|
|
@ -516,8 +513,7 @@ HexLattice::HexLattice(pugi::xml_node lat_node)
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
HexLattice::fill_lattice_x(const std::vector<std::string>& univ_words)
|
||||
void HexLattice::fill_lattice_x(const vector<std::string>& univ_words)
|
||||
{
|
||||
int input_index = 0;
|
||||
for (int m = 0; m < n_axial_; m++) {
|
||||
|
|
@ -569,8 +565,7 @@ HexLattice::fill_lattice_x(const std::vector<std::string>& univ_words)
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
HexLattice::fill_lattice_y(const std::vector<std::string>& univ_words)
|
||||
void HexLattice::fill_lattice_y(const vector<std::string>& univ_words)
|
||||
{
|
||||
int input_index = 0;
|
||||
for (int m = 0; m < n_axial_; m++) {
|
||||
|
|
@ -657,8 +652,7 @@ HexLattice::fill_lattice_y(const std::vector<std::string>& univ_words)
|
|||
|
||||
//==============================================================================
|
||||
|
||||
int32_t&
|
||||
HexLattice::operator[](std::array<int, 3> i_xyz)
|
||||
int32_t const& HexLattice::operator[](array<int, 3> const& i_xyz)
|
||||
{
|
||||
int indx = (2*n_rings_-1)*(2*n_rings_-1) * i_xyz[2]
|
||||
+ (2*n_rings_-1) * i_xyz[1]
|
||||
|
|
@ -676,8 +670,7 @@ ReverseLatticeIter HexLattice::rbegin()
|
|||
|
||||
//==============================================================================
|
||||
|
||||
bool
|
||||
HexLattice::are_valid_indices(const int i_xyz[3]) const
|
||||
bool HexLattice::are_valid_indices(array<int, 3> const& i_xyz) const
|
||||
{
|
||||
// Check if (x, alpha, z) indices are valid, accounting for number of rings
|
||||
return ((i_xyz[0] >= 0) && (i_xyz[1] >= 0) && (i_xyz[2] >= 0)
|
||||
|
|
@ -689,9 +682,8 @@ HexLattice::are_valid_indices(const int i_xyz[3]) const
|
|||
|
||||
//==============================================================================
|
||||
|
||||
std::pair<double, std::array<int, 3>>
|
||||
HexLattice::distance(Position r, Direction u, const std::array<int, 3>& i_xyz)
|
||||
const
|
||||
std::pair<double, array<int, 3>> HexLattice::distance(
|
||||
Position r, Direction u, const array<int, 3>& i_xyz) const
|
||||
{
|
||||
// Short description of the direction vectors used here. The beta, gamma, and
|
||||
// delta vectors point towards the flat sides of each hexagonal tile.
|
||||
|
|
@ -729,14 +721,14 @@ const
|
|||
|
||||
// beta direction
|
||||
double d {INFTY};
|
||||
std::array<int, 3> lattice_trans;
|
||||
array<int, 3> lattice_trans;
|
||||
double edge = -copysign(0.5*pitch_[0], beta_dir); // Oncoming edge
|
||||
Position r_t;
|
||||
if (beta_dir > 0) {
|
||||
const std::array<int, 3> i_xyz_t {i_xyz[0]+1, i_xyz[1], i_xyz[2]};
|
||||
const array<int, 3> i_xyz_t {i_xyz[0] + 1, i_xyz[1], i_xyz[2]};
|
||||
r_t = get_local_position(r, i_xyz_t);
|
||||
} else {
|
||||
const std::array<int, 3> i_xyz_t {i_xyz[0]-1, i_xyz[1], i_xyz[2]};
|
||||
const array<int, 3> i_xyz_t {i_xyz[0] - 1, i_xyz[1], i_xyz[2]};
|
||||
r_t = get_local_position(r, i_xyz_t);
|
||||
}
|
||||
double beta;
|
||||
|
|
@ -757,10 +749,10 @@ const
|
|||
// gamma direction
|
||||
edge = -copysign(0.5*pitch_[0], gamma_dir);
|
||||
if (gamma_dir > 0) {
|
||||
const std::array<int, 3> i_xyz_t {i_xyz[0]+1, i_xyz[1]-1, i_xyz[2]};
|
||||
const array<int, 3> i_xyz_t {i_xyz[0] + 1, i_xyz[1] - 1, i_xyz[2]};
|
||||
r_t = get_local_position(r, i_xyz_t);
|
||||
} else {
|
||||
const std::array<int, 3> i_xyz_t {i_xyz[0]-1, i_xyz[1]+1, i_xyz[2]};
|
||||
const array<int, 3> i_xyz_t {i_xyz[0] - 1, i_xyz[1] + 1, i_xyz[2]};
|
||||
r_t = get_local_position(r, i_xyz_t);
|
||||
}
|
||||
double gamma;
|
||||
|
|
@ -784,10 +776,10 @@ const
|
|||
// delta direction
|
||||
edge = -copysign(0.5*pitch_[0], delta_dir);
|
||||
if (delta_dir > 0) {
|
||||
const std::array<int, 3> i_xyz_t {i_xyz[0], i_xyz[1]+1, i_xyz[2]};
|
||||
const array<int, 3> i_xyz_t {i_xyz[0], i_xyz[1] + 1, i_xyz[2]};
|
||||
r_t = get_local_position(r, i_xyz_t);
|
||||
} else {
|
||||
const std::array<int, 3> i_xyz_t {i_xyz[0], i_xyz[1]-1, i_xyz[2]};
|
||||
const array<int, 3> i_xyz_t {i_xyz[0], i_xyz[1] - 1, i_xyz[2]};
|
||||
r_t = get_local_position(r, i_xyz_t);
|
||||
}
|
||||
double delta;
|
||||
|
|
@ -831,44 +823,43 @@ const
|
|||
|
||||
//==============================================================================
|
||||
|
||||
std::array<int, 3>
|
||||
HexLattice::get_indices(Position r, Direction u) const
|
||||
void HexLattice::get_indices(
|
||||
Position r, Direction u, array<int, 3>& result) const
|
||||
{
|
||||
// Offset the xyz by the lattice center.
|
||||
Position r_o {r.x - center_.x, r.y - center_.y, r.z};
|
||||
if (is_3d_) {r_o.z -= center_.z;}
|
||||
|
||||
// Index the z direction, accounting for coincidence
|
||||
int iz = 0;
|
||||
result[2] = 0;
|
||||
if (is_3d_) {
|
||||
double iz_ {r_o.z / pitch_[1] + 0.5 * n_axial_};
|
||||
long iz_close {std::lround(iz_)};
|
||||
if (coincident(iz_, iz_close)) {
|
||||
iz = (u.z > 0) ? iz_close : iz_close - 1;
|
||||
result[2] = (u.z > 0) ? iz_close : iz_close - 1;
|
||||
} else {
|
||||
iz = std::floor(iz_);
|
||||
result[2] = std::floor(iz_);
|
||||
}
|
||||
}
|
||||
|
||||
int i1, i2;
|
||||
if (orientation_ == Orientation::y) {
|
||||
// Convert coordinates into skewed bases. The (x, alpha) basis is used to
|
||||
// find the index of the global coordinates to within 4 cells.
|
||||
double alpha = r_o.y - r_o.x / std::sqrt(3.0);
|
||||
i1 = std::floor(r_o.x / (0.5*std::sqrt(3.0) * pitch_[0]));
|
||||
i2 = std::floor(alpha / pitch_[0]);
|
||||
result[0] = std::floor(r_o.x / (0.5 * std::sqrt(3.0) * pitch_[0]));
|
||||
result[1] = std::floor(alpha / pitch_[0]);
|
||||
} else {
|
||||
// Convert coordinates into skewed bases. The (alpha, y) basis is used to
|
||||
// find the index of the global coordinates to within 4 cells.
|
||||
double alpha = r_o.y - r_o.x * std::sqrt(3.0);
|
||||
i1 = std::floor(-alpha / (std::sqrt(3.0) * pitch_[0]));
|
||||
i2 = std::floor(r_o.y / (0.5*std::sqrt(3.0) * pitch_[0]));
|
||||
result[0] = std::floor(-alpha / (std::sqrt(3.0) * pitch_[0]));
|
||||
result[1] = std::floor(r_o.y / (0.5 * std::sqrt(3.0) * pitch_[0]));
|
||||
}
|
||||
|
||||
// Add offset to indices (the center cell is (i1, i2) = (0, 0) but
|
||||
// the array is offset so that the indices never go below 0).
|
||||
i1 += n_rings_-1;
|
||||
i2 += n_rings_-1;
|
||||
result[0] += n_rings_ - 1;
|
||||
result[1] += n_rings_ - 1;
|
||||
|
||||
// Calculate the (squared) distance between the particle and the centers of
|
||||
// the four possible cells. Regular hexagonal tiles form a Voronoi
|
||||
|
|
@ -887,14 +878,14 @@ HexLattice::get_indices(Position r, Direction u) const
|
|||
// is kept (i.e. the cell with the lowest dot product as the vectors will be
|
||||
// completely opposed if the particle is moving directly toward the center of
|
||||
// the cell).
|
||||
int i1_chg {};
|
||||
int i2_chg {};
|
||||
int i1_chg;
|
||||
int i2_chg;
|
||||
double d_min {INFTY};
|
||||
double dp_min {INFTY};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
// get local coordinates
|
||||
const std::array<int, 3> i_xyz {i1 + j, i2 + i, 0};
|
||||
const array<int, 3> i_xyz {result[0] + j, result[1] + i, 0};
|
||||
Position r_t = get_local_position(r, i_xyz);
|
||||
// calculate distance
|
||||
double d = r_t.x*r_t.x + r_t.y*r_t.y;
|
||||
|
|
@ -921,17 +912,14 @@ HexLattice::get_indices(Position r, Direction u) const
|
|||
}
|
||||
|
||||
// update outgoing indices
|
||||
i1 += i1_chg;
|
||||
i2 += i2_chg;
|
||||
|
||||
return {i1, i2, iz};
|
||||
result[0] += i1_chg;
|
||||
result[1] += i2_chg;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
Position
|
||||
HexLattice::get_local_position(Position r, const std::array<int, 3> i_xyz)
|
||||
const
|
||||
Position HexLattice::get_local_position(
|
||||
Position r, const array<int, 3>& i_xyz) const
|
||||
{
|
||||
if (orientation_ == Orientation::y) {
|
||||
// x_l = x_g - (center + pitch_x*cos(30)*index_x)
|
||||
|
|
@ -966,14 +954,13 @@ HexLattice::is_valid_index(int indx) const
|
|||
int iz = indx / (nx * ny);
|
||||
int iy = (indx - nx*ny*iz) / nx;
|
||||
int ix = indx - nx*ny*iz - nx*iy;
|
||||
int i_xyz[3] {ix, iy, iz};
|
||||
array<int, 3> i_xyz {ix, iy, iz};
|
||||
return are_valid_indices(i_xyz);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
int32_t&
|
||||
HexLattice::offset(int map, const int i_xyz[3])
|
||||
int32_t& HexLattice::offset(int map, array<int, 3> const& i_xyz)
|
||||
{
|
||||
int nx {2*n_rings_ - 1};
|
||||
int ny {2*n_rings_ - 1};
|
||||
|
|
@ -1028,9 +1015,9 @@ HexLattice::to_hdf5_inner(hid_t lat_group) const
|
|||
write_dataset(lat_group, "pitch", pitch_);
|
||||
write_dataset(lat_group, "center", center_);
|
||||
} else {
|
||||
std::array<double, 1> pitch_short {{pitch_[0]}};
|
||||
array<double, 1> pitch_short {{pitch_[0]}};
|
||||
write_dataset(lat_group, "pitch", pitch_short);
|
||||
std::array<double, 2> center_short {{center_[0], center_[1]}};
|
||||
array<double, 2> center_short {{center_[0], center_[1]}};
|
||||
write_dataset(lat_group, "center", center_short);
|
||||
}
|
||||
|
||||
|
|
@ -1038,7 +1025,7 @@ HexLattice::to_hdf5_inner(hid_t lat_group) const
|
|||
hsize_t nx {static_cast<hsize_t>(2*n_rings_ - 1)};
|
||||
hsize_t ny {static_cast<hsize_t>(2*n_rings_ - 1)};
|
||||
hsize_t nz {static_cast<hsize_t>(n_axial_)};
|
||||
std::vector<int> out(nx*ny*nz);
|
||||
vector<int> out(nx * ny * nz);
|
||||
|
||||
for (int m = 0; m < nz; m++) {
|
||||
for (int k = 0; k < ny; k++) {
|
||||
|
|
@ -1068,10 +1055,10 @@ HexLattice::to_hdf5_inner(hid_t lat_group) const
|
|||
void read_lattices(pugi::xml_node node)
|
||||
{
|
||||
for (pugi::xml_node lat_node : node.children("lattice")) {
|
||||
model::lattices.push_back(std::make_unique<RectLattice>(lat_node));
|
||||
model::lattices.push_back(make_unique<RectLattice>(lat_node));
|
||||
}
|
||||
for (pugi::xml_node lat_node : node.children("hex_lattice")) {
|
||||
model::lattices.push_back(std::make_unique<HexLattice>(lat_node));
|
||||
model::lattices.push_back(make_unique<HexLattice>(lat_node));
|
||||
}
|
||||
|
||||
// Fill the lattice map.
|
||||
|
|
|
|||
102
src/material.cpp
102
src/material.cpp
|
|
@ -39,7 +39,7 @@ namespace openmc {
|
|||
namespace model {
|
||||
|
||||
std::unordered_map<int32_t, int32_t> material_map;
|
||||
std::vector<std::unique_ptr<Material>> materials;
|
||||
vector<unique_ptr<Material>> materials;
|
||||
|
||||
} // namespace model
|
||||
|
||||
|
|
@ -127,8 +127,8 @@ Material::Material(pugi::xml_node node)
|
|||
auto node_macros = node.children("macroscopic");
|
||||
int num_macros = std::distance(node_macros.begin(), node_macros.end());
|
||||
|
||||
std::vector<std::string> names;
|
||||
std::vector<double> densities;
|
||||
vector<std::string> names;
|
||||
vector<double> densities;
|
||||
if (settings::run_CE && num_macros > 0) {
|
||||
fatal_error("Macroscopic can not be used in continuous-energy mode.");
|
||||
} else if (num_macros > 1) {
|
||||
|
|
@ -194,7 +194,7 @@ Material::Material(pugi::xml_node node)
|
|||
// =======================================================================
|
||||
// READ AND PARSE <isotropic> element
|
||||
|
||||
std::vector<std::string> iso_lab;
|
||||
vector<std::string> iso_lab;
|
||||
if (check_for_node(node, "isotropic")) {
|
||||
iso_lab = get_node_array<std::string>(node, "isotropic");
|
||||
}
|
||||
|
|
@ -295,7 +295,7 @@ Material::Material(pugi::xml_node node)
|
|||
if (settings::run_CE) {
|
||||
// Loop over <sab> elements
|
||||
|
||||
std::vector<std::string> sab_names;
|
||||
vector<std::string> sab_names;
|
||||
for (auto node_sab : node.children("sab")) {
|
||||
// Determine name of thermal scattering table
|
||||
if (!check_for_node(node_sab, "name")) {
|
||||
|
|
@ -413,7 +413,7 @@ void Material::normalize_density()
|
|||
|
||||
void Material::init_thermal()
|
||||
{
|
||||
std::vector<ThermalTable> tables;
|
||||
vector<ThermalTable> tables;
|
||||
|
||||
std::unordered_set<int> already_checked;
|
||||
for (const auto& table : thermal_tables_) {
|
||||
|
|
@ -481,8 +481,8 @@ void Material::collision_stopping_power(double* s_col, bool positron)
|
|||
|
||||
// Oscillator strength and square of the binding energy for each oscillator
|
||||
// in material
|
||||
std::vector<double> f;
|
||||
std::vector<double> e_b_sq;
|
||||
vector<double> f;
|
||||
vector<double> e_b_sq;
|
||||
|
||||
for (int i = 0; i < element_.size(); ++i) {
|
||||
const auto& elm = *data::elements[element_[i]];
|
||||
|
|
@ -565,7 +565,7 @@ void Material::collision_stopping_power(double* s_col, bool positron)
|
|||
void Material::init_bremsstrahlung()
|
||||
{
|
||||
// Create new object
|
||||
ttb_ = std::make_unique<Bremsstrahlung>();
|
||||
ttb_ = make_unique<Bremsstrahlung>();
|
||||
|
||||
// Get the size of the energy grids
|
||||
auto n_k = data::ttb_k_grid.size();
|
||||
|
|
@ -748,14 +748,14 @@ void Material::init_nuclide_index()
|
|||
void Material::calculate_xs(Particle& p) const
|
||||
{
|
||||
// Set all material macroscopic cross sections to zero
|
||||
p.macro_xs_.total = 0.0;
|
||||
p.macro_xs_.absorption = 0.0;
|
||||
p.macro_xs_.fission = 0.0;
|
||||
p.macro_xs_.nu_fission = 0.0;
|
||||
p.macro_xs().total = 0.0;
|
||||
p.macro_xs().absorption = 0.0;
|
||||
p.macro_xs().fission = 0.0;
|
||||
p.macro_xs().nu_fission = 0.0;
|
||||
|
||||
if (p.type_ == Particle::Type::neutron) {
|
||||
if (p.type() == ParticleType::neutron) {
|
||||
this->calculate_neutron_xs(p);
|
||||
} else if (p.type_ == Particle::Type::photon) {
|
||||
} else if (p.type() == ParticleType::photon) {
|
||||
this->calculate_photon_xs(p);
|
||||
}
|
||||
}
|
||||
|
|
@ -763,8 +763,9 @@ void Material::calculate_xs(Particle& p) const
|
|||
void Material::calculate_neutron_xs(Particle& p) const
|
||||
{
|
||||
// Find energy index on energy grid
|
||||
int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
int i_grid = std::log(p.E_/data::energy_min[neutron])/simulation::log_spacing;
|
||||
int neutron = static_cast<int>(ParticleType::neutron);
|
||||
int i_grid =
|
||||
std::log(p.E() / data::energy_min[neutron]) / simulation::log_spacing;
|
||||
|
||||
// Determine if this material has S(a,b) tables
|
||||
bool check_sab = (thermal_tables_.size() > 0);
|
||||
|
|
@ -791,7 +792,8 @@ void Material::calculate_neutron_xs(Particle& p) const
|
|||
|
||||
// If particle energy is greater than the highest energy for the
|
||||
// S(a,b) table, then don't use the S(a,b) table
|
||||
if (p.E_ > data::thermal_scatt[i_sab]->energy_max_) i_sab = C_NONE;
|
||||
if (p.E() > data::thermal_scatt[i_sab]->energy_max_)
|
||||
i_sab = C_NONE;
|
||||
|
||||
// Increment position in thermal_tables_
|
||||
++j;
|
||||
|
|
@ -808,11 +810,9 @@ void Material::calculate_neutron_xs(Particle& p) const
|
|||
int i_nuclide = nuclide_[i];
|
||||
|
||||
// Calculate microscopic cross section for this nuclide
|
||||
const auto& micro {p.neutron_xs_[i_nuclide]};
|
||||
if (p.E_ != micro.last_E
|
||||
|| p.sqrtkT_ != micro.last_sqrtkT
|
||||
|| i_sab != micro.index_sab
|
||||
|| sab_frac != micro.sab_frac) {
|
||||
const auto& micro {p.neutron_xs(i_nuclide)};
|
||||
if (p.E() != micro.last_E || p.sqrtkT() != micro.last_sqrtkT ||
|
||||
i_sab != micro.index_sab || sab_frac != micro.sab_frac) {
|
||||
data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, p);
|
||||
}
|
||||
|
||||
|
|
@ -823,19 +823,19 @@ void Material::calculate_neutron_xs(Particle& p) const
|
|||
double atom_density = atom_density_(i);
|
||||
|
||||
// Add contributions to cross sections
|
||||
p.macro_xs_.total += atom_density * micro.total;
|
||||
p.macro_xs_.absorption += atom_density * micro.absorption;
|
||||
p.macro_xs_.fission += atom_density * micro.fission;
|
||||
p.macro_xs_.nu_fission += atom_density * micro.nu_fission;
|
||||
p.macro_xs().total += atom_density * micro.total;
|
||||
p.macro_xs().absorption += atom_density * micro.absorption;
|
||||
p.macro_xs().fission += atom_density * micro.fission;
|
||||
p.macro_xs().nu_fission += atom_density * micro.nu_fission;
|
||||
}
|
||||
}
|
||||
|
||||
void Material::calculate_photon_xs(Particle& p) const
|
||||
{
|
||||
p.macro_xs_.coherent = 0.0;
|
||||
p.macro_xs_.incoherent = 0.0;
|
||||
p.macro_xs_.photoelectric = 0.0;
|
||||
p.macro_xs_.pair_production = 0.0;
|
||||
p.macro_xs().coherent = 0.0;
|
||||
p.macro_xs().incoherent = 0.0;
|
||||
p.macro_xs().photoelectric = 0.0;
|
||||
p.macro_xs().pair_production = 0.0;
|
||||
|
||||
// Add contribution from each nuclide in material
|
||||
for (int i = 0; i < nuclide_.size(); ++i) {
|
||||
|
|
@ -846,8 +846,8 @@ void Material::calculate_photon_xs(Particle& p) const
|
|||
int i_element = element_[i];
|
||||
|
||||
// Calculate microscopic cross section for this nuclide
|
||||
const auto& micro {p.photon_xs_[i_element]};
|
||||
if (p.E_ != micro.last_E) {
|
||||
const auto& micro {p.photon_xs(i_element)};
|
||||
if (p.E() != micro.last_E) {
|
||||
data::elements[i_element]->calculate_xs(p);
|
||||
}
|
||||
|
||||
|
|
@ -858,11 +858,11 @@ void Material::calculate_photon_xs(Particle& p) const
|
|||
double atom_density = atom_density_(i);
|
||||
|
||||
// Add contributions to material macroscopic cross sections
|
||||
p.macro_xs_.total += atom_density * micro.total;
|
||||
p.macro_xs_.coherent += atom_density * micro.coherent;
|
||||
p.macro_xs_.incoherent += atom_density * micro.incoherent;
|
||||
p.macro_xs_.photoelectric += atom_density * micro.photoelectric;
|
||||
p.macro_xs_.pair_production += atom_density * micro.pair_production;
|
||||
p.macro_xs().total += atom_density * micro.total;
|
||||
p.macro_xs().coherent += atom_density * micro.coherent;
|
||||
p.macro_xs().incoherent += atom_density * micro.incoherent;
|
||||
p.macro_xs().photoelectric += atom_density * micro.photoelectric;
|
||||
p.macro_xs().pair_production += atom_density * micro.pair_production;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -936,8 +936,8 @@ void Material::set_density(double density, gsl::cstring_span units)
|
|||
}
|
||||
}
|
||||
|
||||
void Material::set_densities(const std::vector<std::string>& name,
|
||||
const std::vector<double>& density)
|
||||
void Material::set_densities(
|
||||
const vector<std::string>& name, const vector<double>& density)
|
||||
{
|
||||
auto n = name.size();
|
||||
Expects(n > 0);
|
||||
|
|
@ -1010,9 +1010,9 @@ void Material::to_hdf5(hid_t group) const
|
|||
write_dataset(material_group, "atom_density", density_);
|
||||
|
||||
// Copy nuclide/macro name for each nuclide to vector
|
||||
std::vector<std::string> nuc_names;
|
||||
std::vector<std::string> macro_names;
|
||||
std::vector<double> nuc_densities;
|
||||
vector<std::string> nuc_names;
|
||||
vector<std::string> macro_names;
|
||||
vector<double> nuc_densities;
|
||||
if (settings::run_CE) {
|
||||
for (int i = 0; i < nuclide_.size(); ++i) {
|
||||
int i_nuc = nuclide_[i];
|
||||
|
|
@ -1043,7 +1043,7 @@ void Material::to_hdf5(hid_t group) const
|
|||
}
|
||||
|
||||
if (!thermal_tables_.empty()) {
|
||||
std::vector<std::string> sab_names;
|
||||
vector<std::string> sab_names;
|
||||
for (const auto& table : thermal_tables_) {
|
||||
sab_names.push_back(data::thermal_scatt[table.index_table]->name_);
|
||||
}
|
||||
|
|
@ -1099,9 +1099,9 @@ void Material::add_nuclide(const std::string& name, double density)
|
|||
// Non-method functions
|
||||
//==============================================================================
|
||||
|
||||
double sternheimer_adjustment(const std::vector<double>& f, const
|
||||
std::vector<double>& e_b_sq, double e_p_sq, double n_conduction, double
|
||||
log_I, double tol, int max_iter)
|
||||
double sternheimer_adjustment(const vector<double>& f,
|
||||
const vector<double>& e_b_sq, double e_p_sq, double n_conduction,
|
||||
double log_I, double tol, int max_iter)
|
||||
{
|
||||
// Get the total number of oscillators
|
||||
int n = f.size();
|
||||
|
|
@ -1144,8 +1144,8 @@ double sternheimer_adjustment(const std::vector<double>& f, const
|
|||
return rho;
|
||||
}
|
||||
|
||||
double density_effect(const std::vector<double>& f, const std::vector<double>&
|
||||
e_b_sq, double e_p_sq, double n_conduction, double rho, double E, double tol,
|
||||
double density_effect(const vector<double>& f, const vector<double>& e_b_sq,
|
||||
double e_p_sq, double n_conduction, double rho, double E, double tol,
|
||||
int max_iter)
|
||||
{
|
||||
// Get the total number of oscillators
|
||||
|
|
@ -1245,7 +1245,7 @@ void read_materials_xml()
|
|||
// Loop over XML material elements and populate the array.
|
||||
pugi::xml_node root = doc.document_element();
|
||||
for (pugi::xml_node material_node : root.children("material")) {
|
||||
model::materials.push_back(std::make_unique<Material>(material_node));
|
||||
model::materials.push_back(make_unique<Material>(material_node));
|
||||
}
|
||||
model::materials.shrink_to_fit();
|
||||
}
|
||||
|
|
@ -1475,7 +1475,7 @@ openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end)
|
|||
if (index_start) *index_start = model::materials.size();
|
||||
if (index_end) *index_end = model::materials.size() + n - 1;
|
||||
for (int32_t i = 0; i < n; i++) {
|
||||
model::materials.push_back(std::make_unique<Material>());
|
||||
model::materials.push_back(make_unique<Material>());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -540,8 +540,8 @@ void calc_zn(int n, double rho, double phi, double zn[]) {
|
|||
double sin_phi = std::sin(phi);
|
||||
double cos_phi = std::cos(phi);
|
||||
|
||||
std::vector<double> sin_phi_vec(n + 1); // Sin[n * phi]
|
||||
std::vector<double> cos_phi_vec(n + 1); // Cos[n * phi]
|
||||
vector<double> sin_phi_vec(n + 1); // Sin[n * phi]
|
||||
vector<double> cos_phi_vec(n + 1); // Cos[n * phi]
|
||||
sin_phi_vec[0] = 1.0;
|
||||
cos_phi_vec[0] = 1.0;
|
||||
sin_phi_vec[1] = 2.0 * cos_phi;
|
||||
|
|
@ -559,7 +559,7 @@ void calc_zn(int n, double rho, double phi, double zn[]) {
|
|||
// ===========================================================================
|
||||
// Calculate R_pq(rho)
|
||||
// Matrix forms of the coefficients which are easier to work with
|
||||
std::vector<std::vector<double>> zn_mat(n + 1, std::vector<double>(n + 1));
|
||||
vector<vector<double>> zn_mat(n + 1, vector<double>(n + 1));
|
||||
|
||||
// Fill the main diagonal first (Eq 3.9 in Chong)
|
||||
for (int p = 0; p <= n; p++) {
|
||||
|
|
@ -674,7 +674,7 @@ Direction rotate_angle(Direction u, double mu, const double* phi, uint64_t* seed
|
|||
|
||||
void spline(int n, const double x[], const double y[], double z[])
|
||||
{
|
||||
std::vector<double> c_new(n-1);
|
||||
vector<double> c_new(n - 1);
|
||||
|
||||
// Set natural boundary conditions
|
||||
c_new[0] = 0.0;
|
||||
|
|
|
|||
162
src/mesh.cpp
162
src/mesh.cpp
|
|
@ -2,7 +2,6 @@
|
|||
#include <algorithm> // for copy, equal, min, min_element
|
||||
#include <cstddef> // for size_t
|
||||
#include <cmath> // for ceil
|
||||
#include <memory> // for allocator
|
||||
#include <string>
|
||||
#include <gsl/gsl>
|
||||
|
||||
|
|
@ -25,11 +24,12 @@
|
|||
#include "openmc/error.h"
|
||||
#include "openmc/file_utils.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/memory.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/search.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/tallies/filter.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
|
||||
#ifdef LIBMESH
|
||||
|
|
@ -53,13 +53,13 @@ const bool LIBMESH_ENABLED = false;
|
|||
namespace model {
|
||||
|
||||
std::unordered_map<int32_t, int32_t> mesh_map;
|
||||
std::vector<std::unique_ptr<Mesh>> meshes;
|
||||
vector<unique_ptr<Mesh>> meshes;
|
||||
|
||||
} // namespace model
|
||||
|
||||
#ifdef LIBMESH
|
||||
namespace settings {
|
||||
std::unique_ptr<libMesh::LibMeshInit> libmesh_init;
|
||||
unique_ptr<libMesh::LibMeshInit> libmesh_init;
|
||||
const libMesh::Parallel::Communicator* libmesh_comm {nullptr};
|
||||
}
|
||||
#endif
|
||||
|
|
@ -143,7 +143,7 @@ Mesh::set_id(int32_t id) {
|
|||
|
||||
std::string
|
||||
StructuredMesh::bin_label(int bin) const {
|
||||
std::vector<int> ijk(n_dimension_);
|
||||
vector<int> ijk(n_dimension_);
|
||||
get_indices_from_bin(bin, ijk.data());
|
||||
|
||||
if (n_dimension_ > 2) {
|
||||
|
|
@ -192,7 +192,7 @@ UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) {
|
|||
void
|
||||
UnstructuredMesh::surface_bins_crossed(Position r0,
|
||||
Position r1,
|
||||
std::vector<int>& bins) const {
|
||||
vector<int>& bins) const {
|
||||
fatal_error("Unstructured mesh surface tallies are not implemented.");
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ UnstructuredMesh::to_hdf5(hid_t group) const
|
|||
write_dataset(mesh_group, "filename", filename_);
|
||||
write_dataset(mesh_group, "library", this->library());
|
||||
// write volume of each element
|
||||
std::vector<double> tet_vols;
|
||||
vector<double> tet_vols;
|
||||
xt::xtensor<double, 2> centroids({static_cast<size_t>(this->n_bins()), 3});
|
||||
for (int i = 0; i < this->n_bins(); i++) {
|
||||
tet_vols.emplace_back(this->volume(i));
|
||||
|
|
@ -264,7 +264,7 @@ void StructuredMesh::get_indices_from_bin(int bin, int* ijk) const
|
|||
int StructuredMesh::get_bin(Position r) const
|
||||
{
|
||||
// Determine indices
|
||||
std::vector<int> ijk(n_dimension_);
|
||||
vector<int> ijk(n_dimension_);
|
||||
bool in_mesh;
|
||||
get_indices(r, ijk.data(), &in_mesh);
|
||||
if (!in_mesh) return -1;
|
||||
|
|
@ -283,14 +283,12 @@ int StructuredMesh::n_surface_bins() const
|
|||
return 4 * n_dimension_ * n_bins();
|
||||
}
|
||||
|
||||
xt::xtensor<double, 1>
|
||||
StructuredMesh::count_sites(const Particle::Bank* bank,
|
||||
int64_t length,
|
||||
bool* outside) const
|
||||
xt::xtensor<double, 1> StructuredMesh::count_sites(
|
||||
const SourceSite* bank, int64_t length, bool* outside) const
|
||||
{
|
||||
// Determine shape of array for counts
|
||||
std::size_t m = this->n_bins();
|
||||
std::vector<std::size_t> shape = {m};
|
||||
vector<std::size_t> shape = {m};
|
||||
|
||||
// Create array of zeros
|
||||
xt::xarray<double> cnt {shape, 0.0};
|
||||
|
|
@ -585,8 +583,8 @@ bool StructuredMesh::intersects_3d(Position& r0, Position r1, int* ijk) const
|
|||
void StructuredMesh::bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins,
|
||||
std::vector<double>& lengths) const
|
||||
vector<int>& bins,
|
||||
vector<double>& lengths) const
|
||||
{
|
||||
// ========================================================================
|
||||
// Determine where the track intersects the mesh and if it intersects at all.
|
||||
|
|
@ -602,7 +600,7 @@ void StructuredMesh::bins_crossed(Position r0,
|
|||
Position r = r1 - TINY_BIT*u;
|
||||
|
||||
// Determine the mesh indices for the starting and ending coords. Here, we
|
||||
// use arrays for ijk0 and ijk1 instead of std::vector because we obtain a
|
||||
// use arrays for ijk0 and ijk1 instead of vector because we obtain a
|
||||
// small performance improvement by forcing this data to live on the stack,
|
||||
// rather than on the heap. We know the maximum length is 3, and by
|
||||
// ensuring that all loops are only indexed up to n_dimension, we will not
|
||||
|
|
@ -800,11 +798,11 @@ void
|
|||
RegularMesh::surface_bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins) const
|
||||
vector<int>& bins) const
|
||||
{
|
||||
// Determine indices for starting and ending location.
|
||||
int n = n_dimension_;
|
||||
std::vector<int> ijk0(n), ijk1(n);
|
||||
vector<int> ijk0(n), ijk1(n);
|
||||
bool start_in_mesh;
|
||||
get_indices(r0, ijk0.data(), &start_in_mesh);
|
||||
bool end_in_mesh;
|
||||
|
|
@ -813,7 +811,7 @@ RegularMesh::surface_bins_crossed(Position r0,
|
|||
// Check if the track intersects any part of the mesh.
|
||||
if (!start_in_mesh) {
|
||||
Position r0_copy = r0;
|
||||
std::vector<int> ijk0_copy(ijk0);
|
||||
vector<int> ijk0_copy(ijk0);
|
||||
if (!intersects(r0_copy, r1, ijk0_copy.data())) return;
|
||||
}
|
||||
|
||||
|
|
@ -940,11 +938,11 @@ RegularMesh::surface_bins_crossed(Position r0,
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<std::vector<double>, std::vector<double>>
|
||||
RegularMesh::plot(Position plot_ll, Position plot_ur) const
|
||||
std::pair<vector<double>, vector<double>> RegularMesh::plot(
|
||||
Position plot_ll, Position plot_ur) const
|
||||
{
|
||||
// Figure out which axes lie in the plane of the plot.
|
||||
std::array<int, 2> axes {-1, -1};
|
||||
array<int, 2> axes {-1, -1};
|
||||
if (plot_ur.z == plot_ll.z) {
|
||||
axes[0] = 0;
|
||||
if (n_dimension_ > 1) axes[1] = 1;
|
||||
|
|
@ -959,7 +957,7 @@ RegularMesh::plot(Position plot_ll, Position plot_ur) const
|
|||
}
|
||||
|
||||
// Get the coordinates of the mesh lines along both of the axes.
|
||||
std::array<std::vector<double>, 2> axis_lines;
|
||||
array<vector<double>, 2> axis_lines;
|
||||
for (int i_ax = 0; i_ax < 2; ++i_ax) {
|
||||
int axis = axes[i_ax];
|
||||
if (axis == -1) continue;
|
||||
|
|
@ -989,14 +987,12 @@ void RegularMesh::to_hdf5(hid_t group) const
|
|||
close_group(mesh_group);
|
||||
}
|
||||
|
||||
xt::xtensor<double, 1>
|
||||
RegularMesh::count_sites(const Particle::Bank* bank,
|
||||
int64_t length,
|
||||
bool* outside) const
|
||||
xt::xtensor<double, 1> RegularMesh::count_sites(
|
||||
const SourceSite* bank, int64_t length, bool* outside) const
|
||||
{
|
||||
// Determine shape of array for counts
|
||||
std::size_t m = this->n_bins();
|
||||
std::vector<std::size_t> shape = {m};
|
||||
vector<std::size_t> shape = {m};
|
||||
|
||||
// Create array of zeros
|
||||
xt::xarray<double> cnt {shape, 0.0};
|
||||
|
|
@ -1104,7 +1100,7 @@ int RectilinearMesh::set_grid()
|
|||
void RectilinearMesh::surface_bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins) const
|
||||
vector<int>& bins) const
|
||||
{
|
||||
// Determine indices for starting and ending location.
|
||||
int ijk0[3], ijk1[3];
|
||||
|
|
@ -1268,11 +1264,11 @@ int RectilinearMesh::get_index_in_direction(double r, int i) const
|
|||
return lower_bound_index(grid_[i].begin(), grid_[i].end(), r) + 1;
|
||||
}
|
||||
|
||||
std::pair<std::vector<double>, std::vector<double>>
|
||||
RectilinearMesh::plot(Position plot_ll, Position plot_ur) const
|
||||
std::pair<vector<double>, vector<double>> RectilinearMesh::plot(
|
||||
Position plot_ll, Position plot_ur) const
|
||||
{
|
||||
// Figure out which axes lie in the plane of the plot.
|
||||
std::array<int, 2> axes {-1, -1};
|
||||
array<int, 2> axes {-1, -1};
|
||||
if (plot_ur.z == plot_ll.z) {
|
||||
axes = {0, 1};
|
||||
} else if (plot_ur.y == plot_ll.y) {
|
||||
|
|
@ -1284,10 +1280,10 @@ RectilinearMesh::plot(Position plot_ll, Position plot_ur) const
|
|||
}
|
||||
|
||||
// Get the coordinates of the mesh lines along both of the axes.
|
||||
std::array<std::vector<double>, 2> axis_lines;
|
||||
array<vector<double>, 2> axis_lines;
|
||||
for (int i_ax = 0; i_ax < 2; ++i_ax) {
|
||||
int axis = axes[i_ax];
|
||||
std::vector<double>& lines {axis_lines[i_ax]};
|
||||
vector<double>& lines {axis_lines[i_ax]};
|
||||
|
||||
for (auto coord : grid_[axis]) {
|
||||
if (coord >= plot_ll[axis] && coord <= plot_ur[axis])
|
||||
|
|
@ -1370,9 +1366,9 @@ openmc_extend_meshes(int32_t n, const char* type, int32_t* index_start,
|
|||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (std::strcmp(type, "regular") == 0) {
|
||||
model::meshes.push_back(std::make_unique<RegularMesh>());
|
||||
model::meshes.push_back(make_unique<RegularMesh>());
|
||||
} else if (std::strcmp(type, "rectilinear") == 0) {
|
||||
model::meshes.push_back(std::make_unique<RectilinearMesh>());
|
||||
model::meshes.push_back(make_unique<RectilinearMesh>());
|
||||
} else {
|
||||
throw std::runtime_error{"Unknown mesh type: " + std::string(type)};
|
||||
}
|
||||
|
|
@ -1393,14 +1389,14 @@ extern "C" int openmc_add_unstructured_mesh(const char filename[],
|
|||
|
||||
#ifdef DAGMC
|
||||
if (lib_name == "moab") {
|
||||
model::meshes.push_back(std::move(std::make_unique<MOABMesh>(mesh_file)));
|
||||
model::meshes.push_back(std::move(make_unique<MOABMesh>(mesh_file)));
|
||||
valid_lib = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LIBMESH
|
||||
if (lib_name == "libmesh") {
|
||||
model::meshes.push_back(std::move(std::make_unique<LibMesh>(mesh_file)));
|
||||
model::meshes.push_back(std::move(make_unique<LibMesh>(mesh_file)));
|
||||
valid_lib = true;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1470,7 +1466,7 @@ openmc_regular_mesh_set_dimension(int32_t index, int n, const int* dims)
|
|||
RegularMesh* mesh = dynamic_cast<RegularMesh*>(model::meshes[index].get());
|
||||
|
||||
// Copy dimension
|
||||
std::vector<std::size_t> shape = {static_cast<std::size_t>(n)};
|
||||
vector<std::size_t> shape = {static_cast<std::size_t>(n)};
|
||||
mesh->shape_ = xt::adapt(dims, n, xt::no_ownership(), shape);
|
||||
mesh->n_dimension_ = mesh->shape_.size();
|
||||
return 0;
|
||||
|
|
@ -1504,7 +1500,7 @@ openmc_regular_mesh_set_params(int32_t index, int n, const double* ll,
|
|||
if (int err = check_mesh_type<RegularMesh>(index)) return err;
|
||||
RegularMesh* m = dynamic_cast<RegularMesh*>(model::meshes[index].get());
|
||||
|
||||
std::vector<std::size_t> shape = {static_cast<std::size_t>(n)};
|
||||
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);
|
||||
|
|
@ -1587,7 +1583,7 @@ MOABMesh::MOABMesh(const std::string& filename) {
|
|||
|
||||
void MOABMesh::initialize() {
|
||||
// create MOAB instance
|
||||
mbi_ = std::make_unique<moab::Core>();
|
||||
mbi_ = make_unique<moab::Core>();
|
||||
// load unstructured mesh file
|
||||
moab::ErrorCode rval = mbi_->load_file(filename_.c_str());
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
|
|
@ -1647,7 +1643,7 @@ MOABMesh::build_kdtree(const moab::Range& all_tets)
|
|||
all_tets_and_tris.merge(all_tris);
|
||||
|
||||
// create a kd-tree instance
|
||||
kdtree_ = std::make_unique<moab::AdaptiveKDTree>(mbi_.get());
|
||||
kdtree_ = make_unique<moab::AdaptiveKDTree>(mbi_.get());
|
||||
|
||||
// build the tree
|
||||
rval = kdtree_->build_tree(all_tets_and_tris, &kdtree_root_);
|
||||
|
|
@ -1657,15 +1653,13 @@ MOABMesh::build_kdtree(const moab::Range& all_tets)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MOABMesh::intersect_track(const moab::CartVect& start,
|
||||
const moab::CartVect& dir,
|
||||
double track_len,
|
||||
std::vector<double>& hits) const {
|
||||
void MOABMesh::intersect_track(const moab::CartVect& start,
|
||||
const moab::CartVect& dir, double track_len, vector<double>& hits) const
|
||||
{
|
||||
hits.clear();
|
||||
|
||||
moab::ErrorCode rval;
|
||||
std::vector<moab::EntityHandle> tris;
|
||||
vector<moab::EntityHandle> tris;
|
||||
// get all intersections with triangles in the tet mesh
|
||||
// (distances are relative to the start point, not the previous intersection)
|
||||
rval = kdtree_->ray_intersect_triangles(kdtree_root_,
|
||||
|
|
@ -1685,15 +1679,14 @@ MOABMesh::intersect_track(const moab::CartVect& start,
|
|||
|
||||
// sorts by first component of std::pair by default
|
||||
std::sort(hits.begin(), hits.end());
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MOABMesh::bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins,
|
||||
std::vector<double>& lengths) const
|
||||
vector<int>& bins,
|
||||
vector<double>& lengths) const
|
||||
{
|
||||
moab::CartVect start(r0.x, r0.y, r0.z);
|
||||
moab::CartVect end(r1.x, r1.y, r1.z);
|
||||
|
|
@ -1706,7 +1699,7 @@ MOABMesh::bins_crossed(Position r0,
|
|||
start -= TINY_BIT * dir;
|
||||
end += TINY_BIT * dir;
|
||||
|
||||
std::vector<double> hits;
|
||||
vector<double> hits;
|
||||
intersect_track(start, dir, track_len, hits);
|
||||
|
||||
bins.clear();
|
||||
|
|
@ -1805,7 +1798,7 @@ std::string MOABMesh::library() const
|
|||
|
||||
double MOABMesh::tet_volume(moab::EntityHandle tet) const
|
||||
{
|
||||
std::vector<moab::EntityHandle> conn;
|
||||
vector<moab::EntityHandle> conn;
|
||||
moab::ErrorCode rval = mbi_->get_connectivity(&tet, 1, conn);
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
fatal_error("Failed to get tet connectivity");
|
||||
|
|
@ -1820,10 +1813,8 @@ double MOABMesh::tet_volume(moab::EntityHandle tet) const
|
|||
return 1.0 / 6.0 * (((p[1] - p[0]) * (p[2] - p[0])) % (p[3] - p[0]));
|
||||
}
|
||||
|
||||
void MOABMesh::surface_bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins) const
|
||||
void MOABMesh::surface_bins_crossed(
|
||||
Position r0, Position r1, const Direction& u, vector<int>& bins) const
|
||||
{
|
||||
|
||||
// TODO: Implement triangle crossings here
|
||||
|
|
@ -1850,7 +1841,7 @@ MOABMesh::compute_barycentric_data(const moab::Range& tets) {
|
|||
// compute the barycentric data for each tet element
|
||||
// and store it as a 3x3 matrix
|
||||
for (auto& tet : tets) {
|
||||
std::vector<moab::EntityHandle> verts;
|
||||
vector<moab::EntityHandle> verts;
|
||||
rval = mbi_->get_connectivity(&tet, 1, verts);
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
fatal_error("Failed to get connectivity of tet on umesh: " + filename_);
|
||||
|
|
@ -1878,7 +1869,7 @@ MOABMesh::point_in_tet(const moab::CartVect& r,
|
|||
moab::ErrorCode rval;
|
||||
|
||||
// get tet vertices
|
||||
std::vector<moab::EntityHandle> verts;
|
||||
vector<moab::EntityHandle> verts;
|
||||
rval = mbi_->get_connectivity(&tet, 1, verts);
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
warning("Failed to get vertices of tet in umesh: " + filename_);
|
||||
|
|
@ -1930,8 +1921,8 @@ int MOABMesh::get_index_from_bin(int bin) const
|
|||
return bin;
|
||||
}
|
||||
|
||||
std::pair<std::vector<double>, std::vector<double>>
|
||||
MOABMesh::plot(Position plot_ll, Position plot_ur) const
|
||||
std::pair<vector<double>, vector<double>> MOABMesh::plot(
|
||||
Position plot_ll, Position plot_ur) const
|
||||
{
|
||||
// TODO: Implement mesh lines
|
||||
return {};
|
||||
|
|
@ -1982,7 +1973,7 @@ MOABMesh::centroid(int bin) const
|
|||
auto tet = this->get_ent_handle_from_bin(bin);
|
||||
|
||||
// look up the tet connectivity
|
||||
std::vector<moab::EntityHandle> conn;
|
||||
vector<moab::EntityHandle> conn;
|
||||
rval = mbi_->get_connectivity(&tet, 1, conn);
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
warning("Failed to get connectivity of a mesh element.");
|
||||
|
|
@ -1990,7 +1981,7 @@ MOABMesh::centroid(int bin) const
|
|||
}
|
||||
|
||||
// get the coordinates
|
||||
std::vector<moab::CartVect> coords(conn.size());
|
||||
vector<moab::CartVect> coords(conn.size());
|
||||
rval = mbi_->get_coords(conn.data(), conn.size(), coords[0].array());
|
||||
if (rval != moab::MB_SUCCESS) {
|
||||
warning("Failed to get the coordinates of a mesh element.");
|
||||
|
|
@ -2089,10 +2080,8 @@ void MOABMesh::remove_scores()
|
|||
tag_names_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
MOABMesh::set_score_data(const std::string& score,
|
||||
const std::vector<double>& values,
|
||||
const std::vector<double>& std_dev)
|
||||
void MOABMesh::set_score_data(const std::string& score,
|
||||
const vector<double>& values, const vector<double>& std_dev)
|
||||
{
|
||||
auto score_tags = this->get_score_tags(score);
|
||||
|
||||
|
|
@ -2157,7 +2146,7 @@ void LibMesh::initialize()
|
|||
// assuming that unstructured meshes used in OpenMC are 3D
|
||||
n_dimension_ = 3;
|
||||
|
||||
m_ = std::make_unique<libMesh::Mesh>(*settings::libmesh_comm, n_dimension_);
|
||||
m_ = make_unique<libMesh::Mesh>(*settings::libmesh_comm, n_dimension_);
|
||||
m_->read(filename_);
|
||||
m_->prepare_for_use();
|
||||
|
||||
|
|
@ -2169,7 +2158,7 @@ void LibMesh::initialize()
|
|||
// create an equation system for storing values
|
||||
eq_system_name_ = fmt::format("mesh_{}_system", id_);
|
||||
|
||||
equation_systems_ = std::make_unique<libMesh::EquationSystems>(*m_);
|
||||
equation_systems_ = make_unique<libMesh::EquationSystems>(*m_);
|
||||
libMesh::ExplicitSystem& eq_sys =
|
||||
equation_systems_->add_system<libMesh::ExplicitSystem>(eq_system_name_);
|
||||
|
||||
|
|
@ -2209,11 +2198,8 @@ int LibMesh::n_bins() const
|
|||
return m_->n_elem();
|
||||
}
|
||||
|
||||
void
|
||||
LibMesh::surface_bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins) const
|
||||
void LibMesh::surface_bins_crossed(
|
||||
Position r0, Position r1, const Direction& u, vector<int>& bins) const
|
||||
{
|
||||
// TODO: Implement triangle crossings here
|
||||
throw std::runtime_error{"Unstructured mesh surface tallies are not implemented."};
|
||||
|
|
@ -2263,10 +2249,8 @@ LibMesh::remove_scores()
|
|||
variable_map_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
LibMesh::set_score_data(const std::string& var_name,
|
||||
const std::vector<double>& values,
|
||||
const std::vector<double>& std_dev)
|
||||
void LibMesh::set_score_data(const std::string& var_name,
|
||||
const vector<double>& values, const vector<double>& std_dev)
|
||||
{
|
||||
auto& eqn_sys = equation_systems_->get_system(eq_system_name_);
|
||||
|
||||
|
|
@ -2285,13 +2269,13 @@ LibMesh::set_score_data(const std::string& var_name,
|
|||
auto bin = get_bin_from_element(*it);
|
||||
|
||||
// set value
|
||||
std::vector<libMesh::dof_id_type> value_dof_indices;
|
||||
vector<libMesh::dof_id_type> value_dof_indices;
|
||||
dof_map.dof_indices(*it, value_dof_indices, value_num);
|
||||
Ensures(value_dof_indices.size() == 1);
|
||||
eqn_sys.solution->set(value_dof_indices[0], values.at(bin));
|
||||
|
||||
// set std dev
|
||||
std::vector<libMesh::dof_id_type> std_dev_dof_indices;
|
||||
vector<libMesh::dof_id_type> std_dev_dof_indices;
|
||||
dof_map.dof_indices(*it, std_dev_dof_indices, std_dev_num);
|
||||
Ensures(std_dev_dof_indices.size() == 1);
|
||||
eqn_sys.solution->set(std_dev_dof_indices[0], std_dev.at(bin));
|
||||
|
|
@ -2310,8 +2294,8 @@ void
|
|||
LibMesh::bins_crossed(Position r0,
|
||||
Position r1,
|
||||
const Direction& u,
|
||||
std::vector<int>& bins,
|
||||
std::vector<double>& lengths) const
|
||||
vector<int>& bins,
|
||||
vector<double>& lengths) const
|
||||
{
|
||||
// TODO: Implement triangle crossings here
|
||||
fatal_error("Tracklength tallies on libMesh instances are not implemented.");
|
||||
|
|
@ -2348,8 +2332,8 @@ LibMesh::get_bin_from_element(const libMesh::Elem* elem) const
|
|||
return bin;
|
||||
}
|
||||
|
||||
std::pair<std::vector<double>, std::vector<double>>
|
||||
LibMesh::plot(Position plot_ll, Position plot_ur) const
|
||||
std::pair<vector<double>, vector<double>> LibMesh::plot(
|
||||
Position plot_ll, Position plot_ur) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
|
@ -2389,16 +2373,16 @@ void read_meshes(pugi::xml_node root)
|
|||
|
||||
// Read mesh and add to vector
|
||||
if (mesh_type == "regular") {
|
||||
model::meshes.push_back(std::make_unique<RegularMesh>(node));
|
||||
model::meshes.push_back(make_unique<RegularMesh>(node));
|
||||
} else if (mesh_type == "rectilinear") {
|
||||
model::meshes.push_back(std::make_unique<RectilinearMesh>(node));
|
||||
model::meshes.push_back(make_unique<RectilinearMesh>(node));
|
||||
#ifdef DAGMC
|
||||
} else if (mesh_type == "unstructured" && mesh_lib == "moab") {
|
||||
model::meshes.push_back(std::make_unique<MOABMesh>(node));
|
||||
model::meshes.push_back(make_unique<MOABMesh>(node));
|
||||
#endif
|
||||
#ifdef LIBMESH
|
||||
} else if (mesh_type == "unstructured" && mesh_lib == "libmesh") {
|
||||
model::meshes.push_back(std::make_unique<LibMesh>(node));
|
||||
model::meshes.push_back(make_unique<LibMesh>(node));
|
||||
#endif
|
||||
} else if (mesh_type == "unstructured") {
|
||||
fatal_error("Unstructured mesh support is not enabled or the mesh library is invalid.");
|
||||
|
|
@ -2420,7 +2404,7 @@ void meshes_to_hdf5(hid_t group)
|
|||
|
||||
if (n_meshes > 0) {
|
||||
// Write IDs of meshes
|
||||
std::vector<int> ids;
|
||||
vector<int> ids;
|
||||
for (const auto& m : model::meshes) {
|
||||
m->to_hdf5(meshes_group);
|
||||
ids.push_back(m->id_);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ bool master {true};
|
|||
|
||||
#ifdef OPENMC_MPI
|
||||
MPI_Comm intracomm {MPI_COMM_NULL};
|
||||
MPI_Datatype bank {MPI_DATATYPE_NULL};
|
||||
MPI_Datatype source_site {MPI_DATATYPE_NULL};
|
||||
#endif
|
||||
|
||||
extern "C" bool openmc_master() { return mpi::master; }
|
||||
|
|
|
|||
73
src/mgxs.cpp
73
src/mgxs.cpp
|
|
@ -29,11 +29,10 @@ namespace openmc {
|
|||
// Mgxs base-class methods
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
Mgxs::init(const std::string& in_name, double in_awr,
|
||||
const std::vector<double>& in_kTs, bool in_fissionable,
|
||||
AngleDistributionType in_scatter_format, bool in_is_isotropic,
|
||||
const std::vector<double>& in_polar, const std::vector<double>& in_azimuthal)
|
||||
void Mgxs::init(const std::string& in_name, double in_awr,
|
||||
const vector<double>& in_kTs, bool in_fissionable,
|
||||
AngleDistributionType in_scatter_format, bool in_is_isotropic,
|
||||
const vector<double>& in_polar, const vector<double>& in_azimuthal)
|
||||
{
|
||||
// Set the metadata
|
||||
name = in_name;
|
||||
|
|
@ -56,14 +55,13 @@ Mgxs::init(const std::string& in_name, double in_awr,
|
|||
int n_threads = 1;
|
||||
#endif
|
||||
cache.resize(n_threads);
|
||||
// std::vector.resize() will value-initialize the members of cache[:]
|
||||
// vector.resize() will value-initialize the members of cache[:]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
Mgxs::metadata_from_hdf5(hid_t xs_id, const std::vector<double>& temperature,
|
||||
std::vector<int>& temps_to_read, int& order_dim)
|
||||
void Mgxs::metadata_from_hdf5(hid_t xs_id, const vector<double>& temperature,
|
||||
vector<int>& temps_to_read, int& order_dim)
|
||||
{
|
||||
// get name
|
||||
char char_name[MAX_WORD_LEN];
|
||||
|
|
@ -88,7 +86,7 @@ Mgxs::metadata_from_hdf5(hid_t xs_id, const std::vector<double>& temperature,
|
|||
dset_names[i] = new char[151];
|
||||
}
|
||||
get_datasets(kT_group, dset_names);
|
||||
std::vector<size_t> shape = {num_temps};
|
||||
vector<size_t> shape = {num_temps};
|
||||
xt::xarray<double> available_temps(shape);
|
||||
for (int i = 0; i < num_temps; i++) {
|
||||
read_double(kT_group, dset_names[i], &available_temps[i], true);
|
||||
|
|
@ -160,7 +158,7 @@ Mgxs::metadata_from_hdf5(hid_t xs_id, const std::vector<double>& temperature,
|
|||
|
||||
// Get the library's temperatures
|
||||
int n_temperature = temps_to_read.size();
|
||||
std::vector<double> in_kTs(n_temperature);
|
||||
vector<double> in_kTs(n_temperature);
|
||||
for (int i = 0; i < n_temperature; i++) {
|
||||
std::string temp_str(std::to_string(temps_to_read[i]) + "K");
|
||||
|
||||
|
|
@ -254,12 +252,12 @@ Mgxs::metadata_from_hdf5(hid_t xs_id, const std::vector<double>& temperature,
|
|||
}
|
||||
|
||||
// Set the angular bins to use equally-spaced bins
|
||||
std::vector<double> in_polar(in_n_pol);
|
||||
vector<double> in_polar(in_n_pol);
|
||||
double dangle = PI / in_n_pol;
|
||||
for (int p = 0; p < in_n_pol; p++) {
|
||||
in_polar[p] = (p + 0.5) * dangle;
|
||||
}
|
||||
std::vector<double> in_azimuthal(in_n_azi);
|
||||
vector<double> in_azimuthal(in_n_azi);
|
||||
dangle = 2. * PI / in_n_azi;
|
||||
for (int a = 0; a < in_n_azi; a++) {
|
||||
in_azimuthal[a] = (a + 0.5) * dangle - PI;
|
||||
|
|
@ -273,14 +271,13 @@ Mgxs::metadata_from_hdf5(hid_t xs_id, const std::vector<double>& temperature,
|
|||
|
||||
//==============================================================================
|
||||
|
||||
Mgxs::Mgxs(hid_t xs_id, const std::vector<double>& temperature,
|
||||
int num_group, int num_delay) :
|
||||
num_groups(num_group),
|
||||
num_delayed_groups(num_delay)
|
||||
Mgxs::Mgxs(
|
||||
hid_t xs_id, const vector<double>& temperature, int num_group, int num_delay)
|
||||
: num_groups(num_group), num_delayed_groups(num_delay)
|
||||
{
|
||||
// Call generic data gathering routine (will populate the metadata)
|
||||
int order_data;
|
||||
std::vector<int> temps_to_read;
|
||||
vector<int> temps_to_read;
|
||||
metadata_from_hdf5(xs_id, temperature, temps_to_read, order_data);
|
||||
|
||||
// Set number of energy and delayed groups
|
||||
|
|
@ -309,11 +306,10 @@ Mgxs::Mgxs(hid_t xs_id, const std::vector<double>& temperature,
|
|||
|
||||
//==============================================================================
|
||||
|
||||
Mgxs::Mgxs(const std::string& in_name, const std::vector<double>& mat_kTs,
|
||||
const std::vector<Mgxs*>& micros, const std::vector<double>& atom_densities,
|
||||
int num_group, int num_delay) :
|
||||
num_groups(num_group),
|
||||
num_delayed_groups(num_delay)
|
||||
Mgxs::Mgxs(const std::string& in_name, const vector<double>& mat_kTs,
|
||||
const vector<Mgxs*>& micros, const vector<double>& atom_densities,
|
||||
int num_group, int num_delay)
|
||||
: num_groups(num_group), num_delayed_groups(num_delay)
|
||||
{
|
||||
// Get the minimum data needed to initialize:
|
||||
// Dont need awr, but lets just initialize it anyways
|
||||
|
|
@ -328,8 +324,8 @@ Mgxs::Mgxs(const std::string& in_name, const std::vector<double>& mat_kTs,
|
|||
// to be true later
|
||||
AngleDistributionType in_scatter_format = micros[0]->scatter_format;
|
||||
bool in_is_isotropic = micros[0]->is_isotropic;
|
||||
std::vector<double> in_polar = micros[0]->polar;
|
||||
std::vector<double> in_azimuthal = micros[0]->azimuthal;
|
||||
vector<double> in_polar = micros[0]->polar;
|
||||
vector<double> in_azimuthal = micros[0]->azimuthal;
|
||||
|
||||
init(in_name, in_awr, mat_kTs, in_fissionable, in_scatter_format,
|
||||
in_is_isotropic, in_polar, in_azimuthal);
|
||||
|
|
@ -344,8 +340,8 @@ Mgxs::Mgxs(const std::string& in_name, const std::vector<double>& mat_kTs,
|
|||
|
||||
// Create the list of temperature indices and interpolation factors for
|
||||
// each microscopic data at the material temperature
|
||||
std::vector<int> micro_t(micros.size(), 0);
|
||||
std::vector<double> micro_t_interp(micros.size(), 0.);
|
||||
vector<int> micro_t(micros.size(), 0);
|
||||
vector<double> micro_t_interp(micros.size(), 0.);
|
||||
for (int m = 0; m < micros.size(); m++) {
|
||||
switch(settings::temperature_method) {
|
||||
case TemperatureMethod::NEAREST:
|
||||
|
|
@ -383,9 +379,9 @@ Mgxs::Mgxs(const std::string& in_name, const std::vector<double>& mat_kTs,
|
|||
// a different nuclide. Mathematically this just means the temperature
|
||||
// interpolant is included in the number density.
|
||||
// These interpolants are contained within interpolant.
|
||||
std::vector<double> interpolant; // the interpolant for the Mgxs
|
||||
std::vector<int> temp_indices; // the temperature index for each Mgxs
|
||||
std::vector<Mgxs*> mgxs_to_combine; // The Mgxs to combine
|
||||
vector<double> interpolant; // the interpolant for the Mgxs
|
||||
vector<int> temp_indices; // the temperature index for each Mgxs
|
||||
vector<Mgxs*> mgxs_to_combine; // The Mgxs to combine
|
||||
// Now go through and build the above vectors so that we can use them to
|
||||
// combine the data. We will step through each microscopic data and
|
||||
// add in its lower and upper temperature points
|
||||
|
|
@ -419,12 +415,11 @@ Mgxs::Mgxs(const std::string& in_name, const std::vector<double>& mat_kTs,
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
Mgxs::combine(const std::vector<Mgxs*>& micros, const std::vector<double>& scalars,
|
||||
const std::vector<int>& micro_ts, int this_t)
|
||||
void Mgxs::combine(const vector<Mgxs*>& micros, const vector<double>& scalars,
|
||||
const vector<int>& micro_ts, int this_t)
|
||||
{
|
||||
// Build the vector of pointers to the xs objects within micros
|
||||
std::vector<XsData*> those_xs(micros.size());
|
||||
vector<XsData*> those_xs(micros.size());
|
||||
for (int i = 0; i < micros.size(); i++) {
|
||||
those_xs[i] = &(micros[i]->xs[micro_ts[i]]);
|
||||
}
|
||||
|
|
@ -627,13 +622,13 @@ Mgxs::calculate_xs(Particle& p)
|
|||
#else
|
||||
int tid = 0;
|
||||
#endif
|
||||
set_temperature_index(p.sqrtkT_);
|
||||
set_temperature_index(p.sqrtkT());
|
||||
set_angle_index(p.u_local());
|
||||
XsData* xs_t = &xs[cache[tid].t];
|
||||
p.macro_xs_.total = xs_t->total(cache[tid].a, p.g_);
|
||||
p.macro_xs_.absorption = xs_t->absorption(cache[tid].a, p.g_);
|
||||
p.macro_xs_.nu_fission =
|
||||
fissionable ? xs_t->nu_fission(cache[tid].a, p.g_) : 0.;
|
||||
p.macro_xs().total = xs_t->total(cache[tid].a, p.g());
|
||||
p.macro_xs().absorption = xs_t->absorption(cache[tid].a, p.g());
|
||||
p.macro_xs().nu_fission =
|
||||
fissionable ? xs_t->nu_fission(cache[tid].a, p.g()) : 0.;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ namespace data {
|
|||
}
|
||||
|
||||
MgxsInterface::MgxsInterface(const std::string& path_cross_sections,
|
||||
const std::vector<std::string> xs_to_read,
|
||||
const std::vector<std::vector<double>> xs_temps)
|
||||
const vector<std::string> xs_to_read, const vector<vector<double>> xs_temps)
|
||||
{
|
||||
read_header(path_cross_sections);
|
||||
set_nuclides_and_temperatures(xs_to_read, xs_temps);
|
||||
|
|
@ -38,8 +37,7 @@ MgxsInterface::MgxsInterface(const std::string& path_cross_sections,
|
|||
}
|
||||
|
||||
void MgxsInterface::set_nuclides_and_temperatures(
|
||||
std::vector<std::string> xs_to_read,
|
||||
std::vector<std::vector<double>> xs_temps)
|
||||
vector<std::string> xs_to_read, vector<vector<double>> xs_temps)
|
||||
{
|
||||
// Check to remove all duplicates
|
||||
xs_to_read_ = xs_to_read;
|
||||
|
|
@ -76,7 +74,7 @@ void MgxsInterface::init()
|
|||
|
||||
// Read revision number for the MGXS Library file and make sure it matches
|
||||
// with the current version
|
||||
std::array<int, 2> array;
|
||||
array<int, 2> array;
|
||||
read_attribute(file_id, "version", array);
|
||||
if (array != VERSION_MGXS_LIBRARY) {
|
||||
fatal_error("MGXS Library file version does not match current version "
|
||||
|
|
@ -95,9 +93,8 @@ void MgxsInterface::init()
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
MgxsInterface::add_mgxs(hid_t file_id, const std::string& name,
|
||||
const std::vector<double>& temperature)
|
||||
void MgxsInterface::add_mgxs(
|
||||
hid_t file_id, const std::string& name, const vector<double>& temperature)
|
||||
{
|
||||
write_message(5, "Loading {} data...", name);
|
||||
|
||||
|
|
@ -129,12 +126,12 @@ void MgxsInterface::create_macro_xs()
|
|||
if (kTs[i].size() > 0) {
|
||||
// Convert atom_densities to a vector
|
||||
auto& mat {model::materials[i]};
|
||||
std::vector<double> atom_densities(mat->atom_density_.begin(),
|
||||
mat->atom_density_.end());
|
||||
vector<double> atom_densities(
|
||||
mat->atom_density_.begin(), mat->atom_density_.end());
|
||||
|
||||
// Build array of pointers to nuclides's Mgxs objects needed for this
|
||||
// material
|
||||
std::vector<Mgxs*> mgxs_ptr;
|
||||
vector<Mgxs*> mgxs_ptr;
|
||||
for (int i_nuclide : mat->nuclide_) {
|
||||
mgxs_ptr.push_back(&nuclides_[i_nuclide]);
|
||||
}
|
||||
|
|
@ -150,9 +147,9 @@ void MgxsInterface::create_macro_xs()
|
|||
|
||||
//==============================================================================
|
||||
|
||||
std::vector<std::vector<double>> MgxsInterface::get_mat_kTs()
|
||||
vector<vector<double>> MgxsInterface::get_mat_kTs()
|
||||
{
|
||||
std::vector<std::vector<double>> kTs(model::materials.size());
|
||||
vector<vector<double>> kTs(model::materials.size());
|
||||
|
||||
for (const auto& cell : model::cells) {
|
||||
// Skip non-material cells
|
||||
|
|
@ -230,7 +227,7 @@ void MgxsInterface::read_header(const std::string& path_cross_sections)
|
|||
void put_mgxs_header_data_to_globals()
|
||||
{
|
||||
// Get the minimum and maximum energies
|
||||
int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
int neutron = static_cast<int>(ParticleType::neutron);
|
||||
data::energy_min[neutron] = data::mg.energy_bins_.back();
|
||||
data::energy_max[neutron] = data::mg.energy_bins_.front();
|
||||
|
||||
|
|
@ -248,12 +245,12 @@ void put_mgxs_header_data_to_globals()
|
|||
void set_mg_interface_nuclides_and_temps()
|
||||
{
|
||||
// Get temperatures from global data
|
||||
std::vector<std::vector<double>> nuc_temps(data::nuclide_map.size());
|
||||
std::vector<std::vector<double>> dummy;
|
||||
vector<vector<double>> nuc_temps(data::nuclide_map.size());
|
||||
vector<vector<double>> dummy;
|
||||
get_temperatures(nuc_temps, dummy);
|
||||
|
||||
// Build vector of nuclide names which are to be read
|
||||
std::vector<std::string> nuclide_names(data::nuclide_map.size());
|
||||
vector<std::string> nuclide_names(data::nuclide_map.size());
|
||||
for (const auto& kv : data::nuclide_map) {
|
||||
nuclide_names[kv.second] = kv.first;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ namespace openmc {
|
|||
//==============================================================================
|
||||
|
||||
namespace data {
|
||||
std::array<double, 2> energy_min {0.0, 0.0};
|
||||
std::array<double, 2> energy_max {INFTY, INFTY};
|
||||
array<double, 2> energy_min {0.0, 0.0};
|
||||
array<double, 2> energy_max {INFTY, INFTY};
|
||||
double temperature_min {INFTY};
|
||||
double temperature_max {0.0};
|
||||
std::unordered_map<std::string, int> nuclide_map;
|
||||
std::vector<std::unique_ptr<Nuclide>> nuclides;
|
||||
vector<unique_ptr<Nuclide>> nuclides;
|
||||
} // namespace data
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -48,7 +48,7 @@ int Nuclide::XS_FISSION {2};
|
|||
int Nuclide::XS_NU_FISSION {3};
|
||||
int Nuclide::XS_PHOTON_PROD {4};
|
||||
|
||||
Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature)
|
||||
Nuclide::Nuclide(hid_t group, const vector<double>& temperature)
|
||||
{
|
||||
// Set index of nuclide in global vector
|
||||
index_ = data::nuclides.size();
|
||||
|
|
@ -65,7 +65,7 @@ Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature)
|
|||
// Determine temperatures available
|
||||
hid_t kT_group = open_group(group, "kTs");
|
||||
auto dset_names = dataset_names(kT_group);
|
||||
std::vector<double> temps_available;
|
||||
vector<double> temps_available;
|
||||
for (const auto& name : dset_names) {
|
||||
double T;
|
||||
read_dataset(kT_group, name.c_str(), T);
|
||||
|
|
@ -86,7 +86,7 @@ Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature)
|
|||
// temperature range was given (indicated by T_max > 0), in which case all
|
||||
// temperatures in the range are loaded irrespective of what temperatures
|
||||
// actually appear in the model
|
||||
std::vector<int> temps_to_read;
|
||||
vector<int> temps_to_read;
|
||||
int n = temperature.size();
|
||||
double T_min = n > 0 ? settings::temperature_range[0] : 0.0;
|
||||
double T_max = n > 0 ? settings::temperature_range[1] : INFTY;
|
||||
|
|
@ -200,7 +200,7 @@ Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature)
|
|||
for (auto name : group_names(rxs_group)) {
|
||||
if (starts_with(name, "reaction_")) {
|
||||
hid_t rx_group = open_group(rxs_group, name.c_str());
|
||||
reactions_.push_back(std::make_unique<Reaction>(rx_group, temps_to_read));
|
||||
reactions_.push_back(make_unique<Reaction>(rx_group, temps_to_read));
|
||||
|
||||
// Check for 0K elastic scattering
|
||||
const auto& rx = reactions_.back();
|
||||
|
|
@ -310,7 +310,7 @@ void Nuclide::create_derived(const Function1D* prompt_photons, const Function1D*
|
|||
{
|
||||
for (const auto& grid : grid_) {
|
||||
// Allocate and initialize cross section
|
||||
std::array<size_t, 2> shape {grid.energy.size(), 5};
|
||||
array<size_t, 2> shape {grid.energy.size(), 5};
|
||||
xs_.emplace_back(shape, 0.0);
|
||||
}
|
||||
|
||||
|
|
@ -327,7 +327,7 @@ void Nuclide::create_derived(const Function1D* prompt_photons, const Function1D*
|
|||
auto xs = xt::adapt(rx->xs_[t].value);
|
||||
|
||||
for (const auto& p : rx->products_) {
|
||||
if (p.particle_ == Particle::Type::photon) {
|
||||
if (p.particle_ == ParticleType::photon) {
|
||||
auto pprod = xt::view(xs_[t], xt::range(j, j+n), XS_PHOTON_PROD);
|
||||
for (int k = 0; k < n; ++k) {
|
||||
double E = grid_[t].energy[k+j];
|
||||
|
|
@ -445,7 +445,7 @@ void Nuclide::create_derived(const Function1D* prompt_photons, const Function1D*
|
|||
|
||||
void Nuclide::init_grid()
|
||||
{
|
||||
int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
int neutron = static_cast<int>(ParticleType::neutron);
|
||||
double E_min = data::energy_min[neutron];
|
||||
double E_max = data::energy_max[neutron];
|
||||
int M = settings::n_log_bins;
|
||||
|
|
@ -494,7 +494,8 @@ double Nuclide::nu(double E, EmissionMode mode, int group) const
|
|||
for (int i = 1; i < rx->products_.size(); ++i) {
|
||||
// Skip any non-neutron products
|
||||
const auto& product = rx->products_[i];
|
||||
if (product.particle_ != Particle::Type::neutron) continue;
|
||||
if (product.particle_ != ParticleType::neutron)
|
||||
continue;
|
||||
|
||||
// Evaluate yield
|
||||
if (product.emission_mode_ == EmissionMode::delayed) {
|
||||
|
|
@ -519,7 +520,7 @@ double Nuclide::nu(double E, EmissionMode mode, int group) const
|
|||
void Nuclide::calculate_elastic_xs(Particle& p) const
|
||||
{
|
||||
// Get temperature index, grid index, and interpolation factor
|
||||
auto& micro {p.neutron_xs_[index_]};
|
||||
auto& micro {p.neutron_xs(index_)};
|
||||
int i_temp = micro.index_temp;
|
||||
int i_grid = micro.index_grid;
|
||||
double f = micro.interp_factor;
|
||||
|
|
@ -555,7 +556,7 @@ double Nuclide::elastic_xs_0K(double E) const
|
|||
|
||||
void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle& p)
|
||||
{
|
||||
auto& micro {p.neutron_xs_[index_]};
|
||||
auto& micro {p.neutron_xs(index_)};
|
||||
|
||||
// Initialize cached cross sections to zero
|
||||
micro.elastic = CACHE_INVALID;
|
||||
|
|
@ -565,21 +566,21 @@ void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle
|
|||
// Check to see if there is multipole data present at this energy
|
||||
bool use_mp = false;
|
||||
if (multipole_) {
|
||||
use_mp = (p.E_ >= multipole_->E_min_ && p.E_ <= multipole_->E_max_);
|
||||
use_mp = (p.E() >= multipole_->E_min_ && p.E() <= multipole_->E_max_);
|
||||
}
|
||||
|
||||
// Evaluate multipole or interpolate
|
||||
if (use_mp) {
|
||||
// Call multipole kernel
|
||||
double sig_s, sig_a, sig_f;
|
||||
std::tie(sig_s, sig_a, sig_f) = multipole_->evaluate(p.E_, p.sqrtkT_);
|
||||
std::tie(sig_s, sig_a, sig_f) = multipole_->evaluate(p.E(), p.sqrtkT());
|
||||
|
||||
micro.total = sig_s + sig_a;
|
||||
micro.elastic = sig_s;
|
||||
micro.absorption = sig_a;
|
||||
micro.fission = sig_f;
|
||||
micro.nu_fission = fissionable_ ?
|
||||
sig_f * this->nu(p.E_, EmissionMode::total) : 0.0;
|
||||
micro.nu_fission =
|
||||
fissionable_ ? sig_f * this->nu(p.E(), EmissionMode::total) : 0.0;
|
||||
|
||||
if (simulation::need_depletion_rx) {
|
||||
// Only non-zero reaction is (n,gamma)
|
||||
|
|
@ -607,7 +608,7 @@ void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle
|
|||
|
||||
} else {
|
||||
// Find the appropriate temperature index.
|
||||
double kT = p.sqrtkT_*p.sqrtkT_;
|
||||
double kT = p.sqrtkT() * p.sqrtkT();
|
||||
double f;
|
||||
int i_temp = -1;
|
||||
switch (settings::temperature_method) {
|
||||
|
|
@ -644,9 +645,9 @@ void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle
|
|||
const auto& xs {xs_[i_temp]};
|
||||
|
||||
int i_grid;
|
||||
if (p.E_ < grid.energy.front()) {
|
||||
if (p.E() < grid.energy.front()) {
|
||||
i_grid = 0;
|
||||
} else if (p.E_ > grid.energy.back()) {
|
||||
} else if (p.E() > grid.energy.back()) {
|
||||
i_grid = grid.energy.size() - 2;
|
||||
} else {
|
||||
// Determine bounding indices based on which equal log-spaced
|
||||
|
|
@ -655,15 +656,16 @@ void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle
|
|||
int i_high = grid.grid_index[i_log_union + 1] + 1;
|
||||
|
||||
// Perform binary search over reduced range
|
||||
i_grid = i_low + lower_bound_index(&grid.energy[i_low], &grid.energy[i_high], p.E_);
|
||||
i_grid = i_low + lower_bound_index(
|
||||
&grid.energy[i_low], &grid.energy[i_high], p.E());
|
||||
}
|
||||
|
||||
// check for rare case where two energy points are the same
|
||||
if (grid.energy[i_grid] == grid.energy[i_grid + 1]) ++i_grid;
|
||||
|
||||
// calculate interpolation factor
|
||||
f = (p.E_ - grid.energy[i_grid]) /
|
||||
(grid.energy[i_grid + 1]- grid.energy[i_grid]);
|
||||
f = (p.E() - grid.energy[i_grid]) /
|
||||
(grid.energy[i_grid + 1] - grid.energy[i_grid]);
|
||||
|
||||
micro.index_temp = i_temp;
|
||||
micro.index_grid = i_grid;
|
||||
|
|
@ -750,19 +752,19 @@ void Nuclide::calculate_xs(int i_sab, int i_log_union, double sab_frac, Particle
|
|||
// probability tables, we need to determine cross sections from the table
|
||||
if (settings::urr_ptables_on && urr_present_ && !use_mp) {
|
||||
int n = urr_data_[micro.index_temp].n_energy_;
|
||||
if ((p.E_ > urr_data_[micro.index_temp].energy_(0)) &&
|
||||
(p.E_ < urr_data_[micro.index_temp].energy_(n-1))) {
|
||||
if ((p.E() > urr_data_[micro.index_temp].energy_(0)) &&
|
||||
(p.E() < urr_data_[micro.index_temp].energy_(n - 1))) {
|
||||
this->calculate_urr_xs(micro.index_temp, p);
|
||||
}
|
||||
}
|
||||
|
||||
micro.last_E = p.E_;
|
||||
micro.last_sqrtkT = p.sqrtkT_;
|
||||
micro.last_E = p.E();
|
||||
micro.last_sqrtkT = p.sqrtkT();
|
||||
}
|
||||
|
||||
void Nuclide::calculate_sab_xs(int i_sab, double sab_frac, Particle& p)
|
||||
{
|
||||
auto& micro {p.neutron_xs_[index_]};
|
||||
auto& micro {p.neutron_xs(index_)};
|
||||
|
||||
// Set flag that S(a,b) treatment should be used for scattering
|
||||
micro.index_sab = i_sab;
|
||||
|
|
@ -771,7 +773,8 @@ void Nuclide::calculate_sab_xs(int i_sab, double sab_frac, Particle& p)
|
|||
int i_temp;
|
||||
double elastic;
|
||||
double inelastic;
|
||||
data::thermal_scatt[i_sab]->calculate_xs(p.E_, p.sqrtkT_, &i_temp, &elastic, &inelastic, p.current_seed());
|
||||
data::thermal_scatt[i_sab]->calculate_xs(
|
||||
p.E(), p.sqrtkT(), &i_temp, &elastic, &inelastic, p.current_seed());
|
||||
|
||||
// Store the S(a,b) cross sections.
|
||||
micro.thermal = sab_frac * (elastic + inelastic);
|
||||
|
|
@ -791,7 +794,7 @@ void Nuclide::calculate_sab_xs(int i_sab, double sab_frac, Particle& p)
|
|||
|
||||
void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const
|
||||
{
|
||||
auto& micro = p.neutron_xs_[index_];
|
||||
auto& micro = p.neutron_xs(index_);
|
||||
micro.use_ptable = true;
|
||||
|
||||
// Create a shorthand for the URR data
|
||||
|
|
@ -799,17 +802,19 @@ void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const
|
|||
|
||||
// Determine the energy table
|
||||
int i_energy = 0;
|
||||
while (p.E_ >= urr.energy_(i_energy + 1)) {++i_energy;};
|
||||
while (p.E() >= urr.energy_(i_energy + 1)) {
|
||||
++i_energy;
|
||||
};
|
||||
|
||||
// Sample the probability table using the cumulative distribution
|
||||
|
||||
// Random nmbers for the xs calculation are sampled from a separate stream.
|
||||
// Random numbers for the xs calculation are sampled from a separate stream.
|
||||
// This guarantees the randomness and, at the same time, makes sure we
|
||||
// reuse random numbers for the same nuclide at different temperatures,
|
||||
// therefore preserving correlation of temperature in probability tables.
|
||||
p.stream_ = STREAM_URR_PTABLE;
|
||||
p.stream() = STREAM_URR_PTABLE;
|
||||
double r = future_prn(static_cast<int64_t>(index_), *p.current_seed());
|
||||
p.stream_ = STREAM_TRACKING;
|
||||
p.stream() = STREAM_TRACKING;
|
||||
|
||||
int i_low = 0;
|
||||
while (urr.prob_(i_energy, URRTableParam::CUM_PROB, i_low) <= r) {++i_low;};
|
||||
|
|
@ -825,8 +830,8 @@ void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const
|
|||
double f;
|
||||
if (urr.interp_ == Interpolation::lin_lin) {
|
||||
// Determine the interpolation factor on the table
|
||||
f = (p.E_ - urr.energy_(i_energy)) /
|
||||
(urr.energy_(i_energy + 1) - urr.energy_(i_energy));
|
||||
f = (p.E() - urr.energy_(i_energy)) /
|
||||
(urr.energy_(i_energy + 1) - urr.energy_(i_energy));
|
||||
|
||||
elastic = (1. - f) * urr.prob_(i_energy, URRTableParam::ELASTIC, i_low) +
|
||||
f * urr.prob_(i_energy + 1, URRTableParam::ELASTIC, i_up);
|
||||
|
|
@ -836,8 +841,8 @@ void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const
|
|||
f * urr.prob_(i_energy + 1, URRTableParam::N_GAMMA, i_up);
|
||||
} else if (urr.interp_ == Interpolation::log_log) {
|
||||
// Determine interpolation factor on the table
|
||||
f = std::log(p.E_ / urr.energy_(i_energy)) /
|
||||
std::log(urr.energy_(i_energy + 1) / urr.energy_(i_energy));
|
||||
f = std::log(p.E() / urr.energy_(i_energy)) /
|
||||
std::log(urr.energy_(i_energy + 1) / urr.energy_(i_energy));
|
||||
|
||||
// Calculate the elastic cross section/factor
|
||||
if ((urr.prob_(i_energy, URRTableParam::ELASTIC, i_low) > 0.) &&
|
||||
|
|
@ -914,7 +919,7 @@ void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const
|
|||
|
||||
// Determine nu-fission cross-section
|
||||
if (fissionable_) {
|
||||
micro.nu_fission = nu(p.E_, EmissionMode::total) * micro.fission;
|
||||
micro.nu_fission = nu(p.E(), EmissionMode::total) * micro.fission;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -992,7 +997,7 @@ double Nuclide::collapse_rate(int MT, double temperature, gsl::span<const double
|
|||
void check_data_version(hid_t file_id)
|
||||
{
|
||||
if (attribute_exists(file_id, "version")) {
|
||||
std::vector<int> version;
|
||||
vector<int> version;
|
||||
read_attribute(file_id, "version", version);
|
||||
if (version[0] != HDF5_VERSION[0]) {
|
||||
fatal_error("HDF5 data format uses version " + std::to_string(version[0])
|
||||
|
|
@ -1039,8 +1044,8 @@ extern "C" int openmc_load_nuclide(const char* name, const double* temps, int n)
|
|||
|
||||
// Read nuclide data from HDF5
|
||||
hid_t group = open_group(file_id, name);
|
||||
std::vector<double> temperature{temps, temps + n};
|
||||
data::nuclides.push_back(std::make_unique<Nuclide>(group, temperature));
|
||||
vector<double> temperature {temps, temps + n};
|
||||
data::nuclides.push_back(make_unique<Nuclide>(group, temperature));
|
||||
|
||||
close_group(group);
|
||||
file_close(file_id);
|
||||
|
|
@ -1072,7 +1077,7 @@ extern "C" int openmc_load_nuclide(const char* name, const double* temps, int n)
|
|||
|
||||
// Read element data from HDF5
|
||||
hid_t group = open_group(file_id, element.c_str());
|
||||
data::elements.push_back(std::make_unique<PhotonInteraction>(group));
|
||||
data::elements.push_back(make_unique<PhotonInteraction>(group));
|
||||
|
||||
close_group(group);
|
||||
file_close(file_id);
|
||||
|
|
|
|||
|
|
@ -146,62 +146,62 @@ std::string time_stamp()
|
|||
void print_particle(Particle& p)
|
||||
{
|
||||
// Display particle type and ID.
|
||||
switch (p.type_) {
|
||||
case Particle::Type::neutron:
|
||||
fmt::print("Neutron ");
|
||||
break;
|
||||
case Particle::Type::photon:
|
||||
fmt::print("Photon ");
|
||||
break;
|
||||
case Particle::Type::electron:
|
||||
fmt::print("Electron ");
|
||||
break;
|
||||
case Particle::Type::positron:
|
||||
fmt::print("Positron ");
|
||||
break;
|
||||
default:
|
||||
fmt::print("Unknown Particle ");
|
||||
switch (p.type()) {
|
||||
case ParticleType::neutron:
|
||||
fmt::print("Neutron ");
|
||||
break;
|
||||
case ParticleType::photon:
|
||||
fmt::print("Photon ");
|
||||
break;
|
||||
case ParticleType::electron:
|
||||
fmt::print("Electron ");
|
||||
break;
|
||||
case ParticleType::positron:
|
||||
fmt::print("Positron ");
|
||||
break;
|
||||
default:
|
||||
fmt::print("Unknown Particle ");
|
||||
}
|
||||
fmt::print("{}\n", p.id_);
|
||||
fmt::print("{}\n", p.id());
|
||||
|
||||
// Display particle geometry hierarchy.
|
||||
for (auto i = 0; i < p.n_coord_; i++) {
|
||||
for (auto i = 0; i < p.n_coord(); i++) {
|
||||
fmt::print(" Level {}\n", i);
|
||||
|
||||
if (p.coord_[i].cell != C_NONE) {
|
||||
const Cell& c {*model::cells[p.coord_[i].cell]};
|
||||
if (p.coord(i).cell != C_NONE) {
|
||||
const Cell& c {*model::cells[p.coord(i).cell]};
|
||||
fmt::print(" Cell = {}\n", c.id_);
|
||||
}
|
||||
|
||||
if (p.coord_[i].universe != C_NONE) {
|
||||
const Universe& u {*model::universes[p.coord_[i].universe]};
|
||||
if (p.coord(i).universe != C_NONE) {
|
||||
const Universe& u {*model::universes[p.coord(i).universe]};
|
||||
fmt::print(" Universe = {}\n", u.id_);
|
||||
}
|
||||
|
||||
if (p.coord_[i].lattice != C_NONE) {
|
||||
const Lattice& lat {*model::lattices[p.coord_[i].lattice]};
|
||||
if (p.coord(i).lattice != C_NONE) {
|
||||
const Lattice& lat {*model::lattices[p.coord(i).lattice]};
|
||||
fmt::print(" Lattice = {}\n", lat.id_);
|
||||
fmt::print(" Lattice position = ({},{},{})\n", p.coord_[i].lattice_x,
|
||||
p.coord_[i].lattice_y, p.coord_[i].lattice_z);
|
||||
fmt::print(" Lattice position = ({},{},{})\n", p.coord(i).lattice_i[0],
|
||||
p.coord(i).lattice_i[1], p.coord(i).lattice_i[2]);
|
||||
}
|
||||
|
||||
fmt::print(" r = {}\n", p.coord_[i].r);
|
||||
fmt::print(" u = {}\n", p.coord_[i].u);
|
||||
fmt::print(" r = {}\n", p.coord(i).r);
|
||||
fmt::print(" u = {}\n", p.coord(i).u);
|
||||
}
|
||||
|
||||
// Display miscellaneous info.
|
||||
if (p.surface_ != 0) {
|
||||
if (p.surface() != 0) {
|
||||
// Surfaces identifiers are >= 1, but indices are >= 0 so we need -1
|
||||
const Surface& surf {*model::surfaces[std::abs(p.surface_)-1]};
|
||||
fmt::print(" Surface = {}\n", (p.surface_ > 0) ? surf.id_ : -surf.id_);
|
||||
const Surface& surf {*model::surfaces[std::abs(p.surface()) - 1]};
|
||||
fmt::print(" Surface = {}\n", (p.surface() > 0) ? surf.id_ : -surf.id_);
|
||||
}
|
||||
fmt::print(" Weight = {}\n", p.wgt_);
|
||||
fmt::print(" Weight = {}\n", p.wgt());
|
||||
if (settings::run_CE) {
|
||||
fmt::print(" Energy = {}\n", p.E_);
|
||||
fmt::print(" Energy = {}\n", p.E());
|
||||
} else {
|
||||
fmt::print(" Energy Group = {}\n", p.g_);
|
||||
fmt::print(" Energy Group = {}\n", p.g());
|
||||
}
|
||||
fmt::print(" Delayed Group = {}\n\n", p.delayed_group_);
|
||||
fmt::print(" Delayed Group = {}\n\n", p.delayed_group());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -269,17 +269,16 @@ void
|
|||
print_overlap_check()
|
||||
{
|
||||
#ifdef OPENMC_MPI
|
||||
std::vector<int64_t> temp(model::overlap_check_count);
|
||||
MPI_Reduce(temp.data(), model::overlap_check_count.data(),
|
||||
model::overlap_check_count.size(), MPI_INT64_T,
|
||||
MPI_SUM, 0, mpi::intracomm);
|
||||
#endif
|
||||
vector<int64_t> temp(model::overlap_check_count);
|
||||
MPI_Reduce(temp.data(), model::overlap_check_count.data(),
|
||||
model::overlap_check_count.size(), MPI_INT64_T, MPI_SUM, 0, mpi::intracomm);
|
||||
#endif
|
||||
|
||||
if (mpi::master) {
|
||||
header("cell overlap check summary", 1);
|
||||
fmt::print(" Cell ID No. Overlap Checks\n");
|
||||
|
||||
std::vector<int32_t> sparse_cell_ids;
|
||||
vector<int32_t> sparse_cell_ids;
|
||||
for (int i = 0; i < model::cells.size(); i++) {
|
||||
fmt::print(" {:8} {:17}\n", model::cells[i]->id_, model::overlap_check_count[i]);
|
||||
if (model::overlap_check_count[i] < 10) {
|
||||
|
|
@ -606,7 +605,7 @@ write_tallies()
|
|||
}
|
||||
|
||||
// Initialize Filter Matches Object
|
||||
std::vector<FilterMatch> filter_matches;
|
||||
vector<FilterMatch> filter_matches;
|
||||
// Allocate space for tally filter matches
|
||||
filter_matches.resize(model::tally_filters.size());
|
||||
|
||||
|
|
|
|||
450
src/particle.cpp
450
src/particle.cpp
|
|
@ -29,167 +29,120 @@
|
|||
#include "openmc/tallies/tally_scoring.h"
|
||||
#include "openmc/track_output.h"
|
||||
|
||||
#ifdef DAGMC
|
||||
#include "DagMC.hpp"
|
||||
#endif
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// LocalCoord implementation
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
LocalCoord::rotate(const std::vector<double>& rotation)
|
||||
void Particle::create_secondary(
|
||||
double wgt, Direction u, double E, ParticleType type)
|
||||
{
|
||||
this->r = this->r.rotate(rotation);
|
||||
this->u = this->u.rotate(rotation);
|
||||
this->rotated = true;
|
||||
}
|
||||
secondary_bank().emplace_back();
|
||||
|
||||
void
|
||||
LocalCoord::reset()
|
||||
{
|
||||
cell = C_NONE;
|
||||
universe = C_NONE;
|
||||
lattice = C_NONE;
|
||||
lattice_x = 0;
|
||||
lattice_y = 0;
|
||||
lattice_z = 0;
|
||||
rotated = false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Particle implementation
|
||||
//==============================================================================
|
||||
|
||||
Particle::Particle()
|
||||
{
|
||||
// Create and clear coordinate levels
|
||||
coord_.resize(model::n_coord_levels);
|
||||
cell_last_.resize(model::n_coord_levels);
|
||||
clear();
|
||||
|
||||
for (int& n : n_delayed_bank_) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
// Create microscopic cross section caches
|
||||
neutron_xs_.resize(data::nuclides.size());
|
||||
photon_xs_.resize(data::elements.size());
|
||||
}
|
||||
|
||||
void
|
||||
Particle::clear()
|
||||
{
|
||||
// Reset any coordinate levels
|
||||
for (auto& level : coord_) level.reset();
|
||||
n_coord_ = 1;
|
||||
}
|
||||
|
||||
void
|
||||
Particle::create_secondary(double wgt, Direction u, double E, Type type)
|
||||
{
|
||||
secondary_bank_.emplace_back();
|
||||
|
||||
auto& bank {secondary_bank_.back()};
|
||||
auto& bank {secondary_bank().back()};
|
||||
bank.particle = type;
|
||||
bank.wgt = wgt;
|
||||
bank.r = this->r();
|
||||
bank.r = r();
|
||||
bank.u = u;
|
||||
bank.E = settings::run_CE ? E : g_;
|
||||
bank.E = settings::run_CE ? E : g();
|
||||
|
||||
n_bank_second_ += 1;
|
||||
n_bank_second() += 1;
|
||||
}
|
||||
|
||||
void
|
||||
Particle::from_source(const Bank* src)
|
||||
void Particle::from_source(const SourceSite* src)
|
||||
{
|
||||
// Reset some attributes
|
||||
this->clear();
|
||||
alive_ = true;
|
||||
surface_ = 0;
|
||||
cell_born_ = C_NONE;
|
||||
material_ = C_NONE;
|
||||
n_collision_ = 0;
|
||||
fission_ = false;
|
||||
std::fill(flux_derivs_.begin(), flux_derivs_.end(), 0.0);
|
||||
clear();
|
||||
alive() = true;
|
||||
surface() = 0;
|
||||
cell_born() = C_NONE;
|
||||
material() = C_NONE;
|
||||
n_collision() = 0;
|
||||
fission() = false;
|
||||
zero_flux_derivs();
|
||||
|
||||
// Copy attributes from source bank site
|
||||
type_ = src->particle;
|
||||
wgt_ = src->wgt;
|
||||
wgt_last_ = src->wgt;
|
||||
this->r() = src->r;
|
||||
this->u() = src->u;
|
||||
r_last_current_ = src->r;
|
||||
r_last_ = src->r;
|
||||
u_last_ = src->u;
|
||||
type() = src->particle;
|
||||
wgt() = src->wgt;
|
||||
wgt_last() = src->wgt;
|
||||
r() = src->r;
|
||||
u() = src->u;
|
||||
r_last_current() = src->r;
|
||||
r_last() = src->r;
|
||||
u_last() = src->u;
|
||||
if (settings::run_CE) {
|
||||
E_ = src->E;
|
||||
g_ = 0;
|
||||
E() = src->E;
|
||||
g() = 0;
|
||||
} else {
|
||||
g_ = static_cast<int>(src->E);
|
||||
g_last_ = static_cast<int>(src->E);
|
||||
E_ = data::mg.energy_bin_avg_[g_];
|
||||
g() = static_cast<int>(src->E);
|
||||
g_last() = static_cast<int>(src->E);
|
||||
E() = data::mg.energy_bin_avg_[g()];
|
||||
}
|
||||
E_last_ = E_;
|
||||
E_last() = E();
|
||||
}
|
||||
|
||||
void
|
||||
Particle::event_calculate_xs()
|
||||
{
|
||||
// Set the random number stream
|
||||
stream_ = STREAM_TRACKING;
|
||||
stream() = STREAM_TRACKING;
|
||||
|
||||
// Store pre-collision particle properties
|
||||
wgt_last_ = wgt_;
|
||||
E_last_ = E_;
|
||||
u_last_ = this->u();
|
||||
r_last_ = this->r();
|
||||
wgt_last() = wgt();
|
||||
E_last() = E();
|
||||
u_last() = u();
|
||||
r_last() = r();
|
||||
|
||||
// Reset event variables
|
||||
event_ = TallyEvent::KILL;
|
||||
event_nuclide_ = NUCLIDE_NONE;
|
||||
event_mt_ = REACTION_NONE;
|
||||
event() = TallyEvent::KILL;
|
||||
event_nuclide() = NUCLIDE_NONE;
|
||||
event_mt() = REACTION_NONE;
|
||||
|
||||
// If the cell hasn't been determined based on the particle's location,
|
||||
// initiate a search for the current cell. This generally happens at the
|
||||
// beginning of the history and again for any secondary particles
|
||||
if (coord_[n_coord_ - 1].cell == C_NONE) {
|
||||
if (coord(n_coord() - 1).cell == C_NONE) {
|
||||
if (!exhaustive_find_cell(*this)) {
|
||||
this->mark_as_lost("Could not find the cell containing particle "
|
||||
+ std::to_string(id_));
|
||||
mark_as_lost(
|
||||
"Could not find the cell containing particle " + std::to_string(id()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Set birth cell attribute
|
||||
if (cell_born_ == C_NONE) cell_born_ = coord_[n_coord_ - 1].cell;
|
||||
if (cell_born() == C_NONE)
|
||||
cell_born() = coord(n_coord() - 1).cell;
|
||||
}
|
||||
|
||||
// Write particle track.
|
||||
if (write_track_) write_particle_track(*this);
|
||||
if (write_track())
|
||||
write_particle_track(*this);
|
||||
|
||||
if (settings::check_overlaps) check_cell_overlap(*this);
|
||||
|
||||
// Calculate microscopic and macroscopic cross sections
|
||||
if (material_ != MATERIAL_VOID) {
|
||||
if (material() != MATERIAL_VOID) {
|
||||
if (settings::run_CE) {
|
||||
if (material_ != material_last_ || sqrtkT_ != sqrtkT_last_) {
|
||||
if (material() != material_last() || sqrtkT() != sqrtkT_last()) {
|
||||
// If the material is the same as the last material and the
|
||||
// temperature hasn't changed, we don't need to lookup cross
|
||||
// sections again.
|
||||
model::materials[material_]->calculate_xs(*this);
|
||||
model::materials[material()]->calculate_xs(*this);
|
||||
}
|
||||
} else {
|
||||
// Get the MG data; unlike the CE case above, we have to re-calculate
|
||||
// cross sections for every collision since the cross sections may
|
||||
// be angle-dependent
|
||||
data::mg.macro_xs_[material_].calculate_xs(*this);
|
||||
data::mg.macro_xs_[material()].calculate_xs(*this);
|
||||
|
||||
// Update the particle's group while we know we are multi-group
|
||||
g_last_ = g_;
|
||||
g_last() = g();
|
||||
}
|
||||
} else {
|
||||
macro_xs_.total = 0.0;
|
||||
macro_xs_.absorption = 0.0;
|
||||
macro_xs_.fission = 0.0;
|
||||
macro_xs_.nu_fission = 0.0;
|
||||
macro_xs().total = 0.0;
|
||||
macro_xs().absorption = 0.0;
|
||||
macro_xs().fission = 0.0;
|
||||
macro_xs().nu_fission = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,24 +150,23 @@ void
|
|||
Particle::event_advance()
|
||||
{
|
||||
// Find the distance to the nearest boundary
|
||||
boundary_ = distance_to_boundary(*this);
|
||||
boundary() = distance_to_boundary(*this);
|
||||
|
||||
// Sample a distance to collision
|
||||
if (type_ == Particle::Type::electron ||
|
||||
type_ == Particle::Type::positron) {
|
||||
collision_distance_ = 0.0;
|
||||
} else if (macro_xs_.total == 0.0) {
|
||||
collision_distance_ = INFINITY;
|
||||
if (type() == ParticleType::electron || type() == ParticleType::positron) {
|
||||
collision_distance() = 0.0;
|
||||
} else if (macro_xs().total == 0.0) {
|
||||
collision_distance() = INFINITY;
|
||||
} else {
|
||||
collision_distance_ = -std::log(prn(this->current_seed())) / macro_xs_.total;
|
||||
collision_distance() = -std::log(prn(current_seed())) / macro_xs().total;
|
||||
}
|
||||
|
||||
// Select smaller of the two distances
|
||||
double distance = std::min(boundary_.distance, collision_distance_);
|
||||
double distance = std::min(boundary().distance, collision_distance());
|
||||
|
||||
// Advance particle
|
||||
for (int j = 0; j < n_coord_; ++j) {
|
||||
coord_[j].r += distance * coord_[j].u;
|
||||
for (int j = 0; j < n_coord(); ++j) {
|
||||
coord(j).r += distance * coord(j).u;
|
||||
}
|
||||
|
||||
// Score track-length tallies
|
||||
|
|
@ -224,8 +176,8 @@ Particle::event_advance()
|
|||
|
||||
// Score track-length estimate of k-eff
|
||||
if (settings::run_mode == RunMode::EIGENVALUE &&
|
||||
type_ == Particle::Type::neutron) {
|
||||
keff_tally_tracklength_ += wgt_ * distance * macro_xs_.nu_fission;
|
||||
type() == ParticleType::neutron) {
|
||||
keff_tally_tracklength() += wgt() * distance * macro_xs().nu_fission;
|
||||
}
|
||||
|
||||
// Score flux derivative accumulators for differential tallies.
|
||||
|
|
@ -238,25 +190,25 @@ void
|
|||
Particle::event_cross_surface()
|
||||
{
|
||||
// Set surface that particle is on and adjust coordinate levels
|
||||
surface_ = boundary_.surface_index;
|
||||
n_coord_ = boundary_.coord_level;
|
||||
surface() = boundary().surface_index;
|
||||
n_coord() = boundary().coord_level;
|
||||
|
||||
// Saving previous cell data
|
||||
for (int j = 0; j < n_coord_; ++j) {
|
||||
cell_last_[j] = coord_[j].cell;
|
||||
for (int j = 0; j < n_coord(); ++j) {
|
||||
cell_last(j) = coord(j).cell;
|
||||
}
|
||||
n_coord_last_ = n_coord_;
|
||||
n_coord_last() = n_coord();
|
||||
|
||||
if (boundary_.lattice_translation[0] != 0 ||
|
||||
boundary_.lattice_translation[1] != 0 ||
|
||||
boundary_.lattice_translation[2] != 0) {
|
||||
if (boundary().lattice_translation[0] != 0 ||
|
||||
boundary().lattice_translation[1] != 0 ||
|
||||
boundary().lattice_translation[2] != 0) {
|
||||
// Particle crosses lattice boundary
|
||||
cross_lattice(*this, boundary_);
|
||||
event_ = TallyEvent::LATTICE;
|
||||
cross_lattice(*this, boundary());
|
||||
event() = TallyEvent::LATTICE;
|
||||
} else {
|
||||
// Particle crosses surface
|
||||
this->cross_surface();
|
||||
event_ = TallyEvent::SURFACE;
|
||||
cross_surface();
|
||||
event() = TallyEvent::SURFACE;
|
||||
}
|
||||
// Score cell to cell partial currents
|
||||
if (!model::active_surface_tallies.empty()) {
|
||||
|
|
@ -269,9 +221,8 @@ Particle::event_collide()
|
|||
{
|
||||
// Score collision estimate of keff
|
||||
if (settings::run_mode == RunMode::EIGENVALUE &&
|
||||
type_ == Particle::Type::neutron) {
|
||||
keff_tally_collision_ += wgt_ * macro_xs_.nu_fission
|
||||
/ macro_xs_.total;
|
||||
type() == ParticleType::neutron) {
|
||||
keff_tally_collision() += wgt() * macro_xs().nu_fission / macro_xs().total;
|
||||
}
|
||||
|
||||
// Score surface current tallies -- this has to be done before the collision
|
||||
|
|
@ -282,7 +233,7 @@ Particle::event_collide()
|
|||
score_surface_tally(*this, model::active_meshsurf_tallies);
|
||||
|
||||
// Clear surface component
|
||||
surface_ = 0;
|
||||
surface() = 0;
|
||||
|
||||
if (settings::run_CE) {
|
||||
collision(*this);
|
||||
|
|
@ -303,32 +254,32 @@ Particle::event_collide()
|
|||
}
|
||||
|
||||
// Reset banked weight during collision
|
||||
n_bank_ = 0;
|
||||
n_bank_second_ = 0;
|
||||
wgt_bank_ = 0.0;
|
||||
for (int& v : n_delayed_bank_) v = 0;
|
||||
n_bank() = 0;
|
||||
n_bank_second() = 0;
|
||||
wgt_bank() = 0.0;
|
||||
zero_delayed_bank();
|
||||
|
||||
// Reset fission logical
|
||||
fission_ = false;
|
||||
fission() = false;
|
||||
|
||||
// Save coordinates for tallying purposes
|
||||
r_last_current_ = this->r();
|
||||
r_last_current() = r();
|
||||
|
||||
// Set last material to none since cross sections will need to be
|
||||
// re-evaluated
|
||||
material_last_ = C_NONE;
|
||||
material_last() = C_NONE;
|
||||
|
||||
// Set all directions to base level -- right now, after a collision, only
|
||||
// the base level directions are changed
|
||||
for (int j = 0; j < n_coord_ - 1; ++j) {
|
||||
if (coord_[j + 1].rotated) {
|
||||
for (int j = 0; j < n_coord() - 1; ++j) {
|
||||
if (coord(j + 1).rotated) {
|
||||
// If next level is rotated, apply rotation matrix
|
||||
const auto& m {model::cells[coord_[j].cell]->rotation_};
|
||||
const auto& u {coord_[j].u};
|
||||
coord_[j + 1].u = u.rotate(m);
|
||||
const auto& m {model::cells[coord(j).cell]->rotation_};
|
||||
const auto& u {coord(j).u};
|
||||
coord(j + 1).u = u.rotate(m);
|
||||
} else {
|
||||
// Otherwise, copy this level's direction
|
||||
coord_[j+1].u = coord_[j].u;
|
||||
coord(j + 1).u = coord(j).u;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,24 +291,26 @@ void
|
|||
Particle::event_revive_from_secondary()
|
||||
{
|
||||
// If particle has too many events, display warning and kill it
|
||||
++n_event_;
|
||||
if (n_event_ == MAX_EVENTS) {
|
||||
warning("Particle " + std::to_string(id_) +
|
||||
" underwent maximum number of events.");
|
||||
alive_ = false;
|
||||
++n_event();
|
||||
if (n_event() == MAX_EVENTS) {
|
||||
warning("Particle " + std::to_string(id()) +
|
||||
" underwent maximum number of events.");
|
||||
alive() = false;
|
||||
}
|
||||
|
||||
// Check for secondary particles if this particle is dead
|
||||
if (!alive_) {
|
||||
if (!alive()) {
|
||||
// If no secondary particles, break out of event loop
|
||||
if (secondary_bank_.empty()) return;
|
||||
if (secondary_bank().empty())
|
||||
return;
|
||||
|
||||
this->from_source(&secondary_bank_.back());
|
||||
secondary_bank_.pop_back();
|
||||
n_event_ = 0;
|
||||
from_source(&secondary_bank().back());
|
||||
secondary_bank().pop_back();
|
||||
n_event() = 0;
|
||||
|
||||
// Enter new particle in particle track file
|
||||
if (write_track_) add_particle_track(*this);
|
||||
if (write_track())
|
||||
add_particle_track(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -365,36 +318,37 @@ void
|
|||
Particle::event_death()
|
||||
{
|
||||
#ifdef DAGMC
|
||||
if (settings::dagmc) history_.reset();
|
||||
#endif
|
||||
if (settings::dagmc)
|
||||
history().reset();
|
||||
#endif
|
||||
|
||||
// Finish particle track output.
|
||||
if (write_track_) {
|
||||
if (write_track()) {
|
||||
write_particle_track(*this);
|
||||
finalize_particle_track(*this);
|
||||
}
|
||||
|
||||
// Contribute tally reduction variables to global accumulator
|
||||
#pragma omp atomic
|
||||
global_tally_absorption += keff_tally_absorption_;
|
||||
#pragma omp atomic
|
||||
global_tally_collision += keff_tally_collision_;
|
||||
#pragma omp atomic
|
||||
global_tally_tracklength += keff_tally_tracklength_;
|
||||
#pragma omp atomic
|
||||
global_tally_leakage += keff_tally_leakage_;
|
||||
global_tally_absorption += keff_tally_absorption();
|
||||
#pragma omp atomic
|
||||
global_tally_collision += keff_tally_collision();
|
||||
#pragma omp atomic
|
||||
global_tally_tracklength += keff_tally_tracklength();
|
||||
#pragma omp atomic
|
||||
global_tally_leakage += keff_tally_leakage();
|
||||
|
||||
// Reset particle tallies once accumulated
|
||||
keff_tally_absorption_ = 0.0;
|
||||
keff_tally_collision_ = 0.0;
|
||||
keff_tally_tracklength_ = 0.0;
|
||||
keff_tally_leakage_ = 0.0;
|
||||
keff_tally_absorption() = 0.0;
|
||||
keff_tally_collision() = 0.0;
|
||||
keff_tally_tracklength() = 0.0;
|
||||
keff_tally_leakage() = 0.0;
|
||||
|
||||
// Record the number of progeny created by this particle.
|
||||
// This data will be used to efficiently sort the fission bank.
|
||||
if (settings::run_mode == RunMode::EIGENVALUE) {
|
||||
int64_t offset = id_ - 1 - simulation::work_index[mpi::rank];
|
||||
simulation::progeny_per_particle[offset] = n_progeny_;
|
||||
int64_t offset = id() - 1 - simulation::work_index[mpi::rank];
|
||||
simulation::progeny_per_particle[offset] = n_progeny();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -402,24 +356,24 @@ Particle::event_death()
|
|||
void
|
||||
Particle::cross_surface()
|
||||
{
|
||||
int i_surface = std::abs(surface_);
|
||||
int i_surface = std::abs(surface());
|
||||
// TODO: off-by-one
|
||||
const auto& surf {model::surfaces[i_surface - 1].get()};
|
||||
if (settings::verbosity >= 10 || trace_) {
|
||||
if (settings::verbosity >= 10 || trace()) {
|
||||
write_message(1, " Crossing surface {}", surf->id_);
|
||||
}
|
||||
|
||||
if (surf->surf_source_ && simulation::current_batch == settings::n_batches) {
|
||||
Particle::Bank site;
|
||||
site.r = this->r();
|
||||
site.u = this->u();
|
||||
site.E = this->E_;
|
||||
site.wgt = this->wgt_;
|
||||
site.delayed_group = this->delayed_group_;
|
||||
SourceSite site;
|
||||
site.r = r();
|
||||
site.u = u();
|
||||
site.E = E();
|
||||
site.wgt = wgt();
|
||||
site.delayed_group = delayed_group();
|
||||
site.surf_id = surf->id_;
|
||||
site.particle = this->type_;
|
||||
site.parent_id = this->id_;
|
||||
site.progeny_id = this->n_progeny_;
|
||||
site.particle = type();
|
||||
site.parent_id = id();
|
||||
site.progeny_id = n_progeny();
|
||||
int64_t idx = simulation::surf_source_bank.thread_safe_append(site);
|
||||
}
|
||||
|
||||
|
|
@ -434,18 +388,19 @@ Particle::cross_surface()
|
|||
|
||||
#ifdef DAGMC
|
||||
if (settings::dagmc) {
|
||||
auto cellp = dynamic_cast<DAGCell*>(model::cells[cell_last_[0]].get());
|
||||
auto cellp = dynamic_cast<DAGCell*>(model::cells[cell_last(0)].get());
|
||||
// TODO: off-by-one
|
||||
auto surfp = dynamic_cast<DAGSurface*>(model::surfaces[std::abs(surface_) - 1].get());
|
||||
auto surfp =
|
||||
dynamic_cast<DAGSurface*>(model::surfaces[std::abs(surface()) - 1].get());
|
||||
int32_t i_cell = next_cell(cellp, surfp) - 1;
|
||||
// save material and temp
|
||||
material_last_ = material_;
|
||||
sqrtkT_last_ = sqrtkT_;
|
||||
material_last() = material();
|
||||
sqrtkT_last() = sqrtkT();
|
||||
// set new cell value
|
||||
coord_[0].cell = i_cell;
|
||||
cell_instance_ = 0;
|
||||
material_ = model::cells[i_cell]->material_[0];
|
||||
sqrtkT_ = model::cells[i_cell]->sqrtkT_[0];
|
||||
coord(0).cell = i_cell;
|
||||
cell_instance() = 0;
|
||||
material() = model::cells[i_cell]->material_[0];
|
||||
sqrtkT() = model::cells[i_cell]->sqrtkT_[0];
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -457,8 +412,8 @@ Particle::cross_surface()
|
|||
// COULDN'T FIND PARTICLE IN NEIGHBORING CELLS, SEARCH ALL CELLS
|
||||
|
||||
// Remove lower coordinate levels and assignment of surface
|
||||
surface_ = 0;
|
||||
n_coord_ = 1;
|
||||
surface() = 0;
|
||||
n_coord() = 1;
|
||||
bool found = exhaustive_find_cell(*this);
|
||||
|
||||
if (settings::run_mode != RunMode::PLOTTING && (!found)) {
|
||||
|
|
@ -467,16 +422,16 @@ Particle::cross_surface()
|
|||
// the particle is really traveling tangent to a surface, if we move it
|
||||
// forward a tiny bit it should fix the problem.
|
||||
|
||||
n_coord_ = 1;
|
||||
this->r() += TINY_BIT * this->u();
|
||||
n_coord() = 1;
|
||||
r() += TINY_BIT * u();
|
||||
|
||||
// Couldn't find next cell anywhere! This probably means there is an actual
|
||||
// undefined region in the geometry.
|
||||
|
||||
if (!exhaustive_find_cell(*this)) {
|
||||
this->mark_as_lost("After particle " + std::to_string(id_) +
|
||||
" crossed surface " + std::to_string(surf->id_) +
|
||||
" it could not be located in any cell and it did not leak.");
|
||||
mark_as_lost("After particle " + std::to_string(id()) +
|
||||
" crossed surface " + std::to_string(surf->id_) +
|
||||
" it could not be located in any cell and it did not leak.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -486,7 +441,7 @@ void
|
|||
Particle::cross_vacuum_bc(const Surface& surf)
|
||||
{
|
||||
// Kill the particle
|
||||
alive_ = false;
|
||||
alive() = false;
|
||||
|
||||
// Score any surface current tallies -- note that the particle is moved
|
||||
// forward slightly so that if the mesh boundary is on the surface, it is
|
||||
|
|
@ -496,15 +451,15 @@ Particle::cross_vacuum_bc(const Surface& surf)
|
|||
// TODO: Find a better solution to score surface currents than
|
||||
// physically moving the particle forward slightly
|
||||
|
||||
this->r() += TINY_BIT * this->u();
|
||||
r() += TINY_BIT * u();
|
||||
score_surface_tally(*this, model::active_meshsurf_tallies);
|
||||
}
|
||||
|
||||
// Score to global leakage tally
|
||||
keff_tally_leakage_ += wgt_;
|
||||
keff_tally_leakage() += wgt();
|
||||
|
||||
// Display message
|
||||
if (settings::verbosity >= 10 || trace_) {
|
||||
if (settings::verbosity >= 10 || trace()) {
|
||||
write_message(1, " Leaked out of surface {}", surf.id_);
|
||||
}
|
||||
}
|
||||
|
|
@ -513,9 +468,9 @@ void
|
|||
Particle::cross_reflective_bc(const Surface& surf, Direction new_u)
|
||||
{
|
||||
// Do not handle reflective boundary conditions on lower universes
|
||||
if (n_coord_ != 1) {
|
||||
this->mark_as_lost("Cannot reflect particle " + std::to_string(id_) +
|
||||
" off surface in a lower universe.");
|
||||
if (n_coord() != 1) {
|
||||
mark_as_lost("Cannot reflect particle " + std::to_string(id()) +
|
||||
" off surface in a lower universe.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -532,36 +487,36 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u)
|
|||
|
||||
if (!model::active_meshsurf_tallies.empty()) {
|
||||
Position r {this->r()};
|
||||
this->r() -= TINY_BIT * this->u();
|
||||
this->r() -= TINY_BIT * u();
|
||||
score_surface_tally(*this, model::active_meshsurf_tallies);
|
||||
this->r() = r;
|
||||
}
|
||||
|
||||
// Set the new particle direction
|
||||
this->u() = new_u;
|
||||
u() = new_u;
|
||||
|
||||
// Reassign particle's cell and surface
|
||||
coord_[0].cell = cell_last_[n_coord_last_ - 1];
|
||||
surface_ = -surface_;
|
||||
coord(0).cell = cell_last(n_coord_last() - 1);
|
||||
surface() = -surface();
|
||||
|
||||
// If a reflective surface is coincident with a lattice or universe
|
||||
// boundary, it is necessary to redetermine the particle's coordinates in
|
||||
// the lower universes.
|
||||
// (unless we're using a dagmc model, which has exactly one universe)
|
||||
if (!settings::dagmc) {
|
||||
n_coord_ = 1;
|
||||
n_coord() = 1;
|
||||
if (!neighbor_list_find_cell(*this)) {
|
||||
this->mark_as_lost("Couldn't find particle after reflecting from surface "
|
||||
+ std::to_string(surf.id_) + ".");
|
||||
mark_as_lost("Couldn't find particle after reflecting from surface " +
|
||||
std::to_string(surf.id_) + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Set previous coordinate going slightly past surface crossing
|
||||
r_last_current_ = this->r() + TINY_BIT*this->u();
|
||||
r_last_current() = r() + TINY_BIT * u();
|
||||
|
||||
// Diagnostic message
|
||||
if (settings::verbosity >= 10 || trace_) {
|
||||
if (settings::verbosity >= 10 || trace()) {
|
||||
write_message(1, " Reflected from surface {}", surf.id_);
|
||||
}
|
||||
}
|
||||
|
|
@ -571,8 +526,9 @@ Particle::cross_periodic_bc(const Surface& surf, Position new_r,
|
|||
Direction new_u, int new_surface)
|
||||
{
|
||||
// Do not handle periodic boundary conditions on lower universes
|
||||
if (n_coord_ != 1) {
|
||||
this->mark_as_lost("Cannot transfer particle " + std::to_string(id_) +
|
||||
if (n_coord() != 1) {
|
||||
mark_as_lost(
|
||||
"Cannot transfer particle " + std::to_string(id()) +
|
||||
" across surface in a lower universe. Boundary conditions must be "
|
||||
"applied to root universe.");
|
||||
return;
|
||||
|
|
@ -583,7 +539,7 @@ Particle::cross_periodic_bc(const Surface& surf, Position new_r,
|
|||
// case the surface crossing is coincident with a mesh boundary
|
||||
if (!model::active_meshsurf_tallies.empty()) {
|
||||
Position r {this->r()};
|
||||
this->r() -= TINY_BIT * this->u();
|
||||
this->r() -= TINY_BIT * u();
|
||||
score_surface_tally(*this, model::active_meshsurf_tallies);
|
||||
this->r() = r;
|
||||
}
|
||||
|
|
@ -593,23 +549,25 @@ Particle::cross_periodic_bc(const Surface& surf, Position new_r,
|
|||
u() = new_u;
|
||||
|
||||
// Reassign particle's surface
|
||||
surface_ = new_surface;
|
||||
surface() = new_surface;
|
||||
|
||||
// Figure out what cell particle is in now
|
||||
n_coord_ = 1;
|
||||
n_coord() = 1;
|
||||
|
||||
if (!neighbor_list_find_cell(*this)) {
|
||||
this->mark_as_lost("Couldn't find particle after hitting periodic "
|
||||
"boundary on surface " + std::to_string(surf.id_) + ". The normal vector "
|
||||
"of one periodic surface may need to be reversed.");
|
||||
mark_as_lost("Couldn't find particle after hitting periodic "
|
||||
"boundary on surface " +
|
||||
std::to_string(surf.id_) +
|
||||
". The normal vector "
|
||||
"of one periodic surface may need to be reversed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set previous coordinate going slightly past surface crossing
|
||||
r_last_current_ = this->r() + TINY_BIT*this->u();
|
||||
r_last_current() = r() + TINY_BIT * u();
|
||||
|
||||
// Diagnostic message
|
||||
if (settings::verbosity >= 10 || trace_) {
|
||||
if (settings::verbosity >= 10 || trace()) {
|
||||
write_message(1, " Hit periodic boundary on surface {}", surf.id_);
|
||||
}
|
||||
}
|
||||
|
|
@ -622,8 +580,8 @@ Particle::mark_as_lost(const char* message)
|
|||
write_restart();
|
||||
|
||||
// Increment number of lost particles
|
||||
alive_ = false;
|
||||
#pragma omp atomic
|
||||
alive() = false;
|
||||
#pragma omp atomic
|
||||
simulation::n_lost_particles += 1;
|
||||
|
||||
// Count the total number of simulated particles (on this processor)
|
||||
|
|
@ -646,9 +604,9 @@ Particle::write_restart() const
|
|||
|
||||
// Set up file name
|
||||
auto filename = fmt::format("{}particle_{}_{}.h5", settings::path_output,
|
||||
simulation::current_batch, id_);
|
||||
simulation::current_batch, id());
|
||||
|
||||
#pragma omp critical (WriteParticleRestart)
|
||||
#pragma omp critical (WriteParticleRestart)
|
||||
{
|
||||
// Create file
|
||||
hid_t file_id = file_open(filename, 'w');
|
||||
|
|
@ -679,10 +637,10 @@ Particle::write_restart() const
|
|||
default:
|
||||
break;
|
||||
}
|
||||
write_dataset(file_id, "id", id_);
|
||||
write_dataset(file_id, "type", static_cast<int>(type_));
|
||||
write_dataset(file_id, "id", id());
|
||||
write_dataset(file_id, "type", static_cast<int>(type()));
|
||||
|
||||
int64_t i = current_work_;
|
||||
int64_t i = current_work();
|
||||
if (settings::run_mode == RunMode::EIGENVALUE) {
|
||||
//take source data from primary bank for eigenvalue simulation
|
||||
write_dataset(file_id, "weight", simulation::source_bank[i-1].wgt);
|
||||
|
|
@ -707,31 +665,31 @@ Particle::write_restart() const
|
|||
} // #pragma omp critical
|
||||
}
|
||||
|
||||
std::string particle_type_to_str(Particle::Type type)
|
||||
std::string particle_type_to_str(ParticleType type)
|
||||
{
|
||||
switch (type) {
|
||||
case Particle::Type::neutron:
|
||||
return "neutron";
|
||||
case Particle::Type::photon:
|
||||
return "photon";
|
||||
case Particle::Type::electron:
|
||||
return "electron";
|
||||
case Particle::Type::positron:
|
||||
return "positron";
|
||||
case ParticleType::neutron:
|
||||
return "neutron";
|
||||
case ParticleType::photon:
|
||||
return "photon";
|
||||
case ParticleType::electron:
|
||||
return "electron";
|
||||
case ParticleType::positron:
|
||||
return "positron";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
Particle::Type str_to_particle_type(std::string str)
|
||||
ParticleType str_to_particle_type(std::string str)
|
||||
{
|
||||
if (str == "neutron") {
|
||||
return Particle::Type::neutron;
|
||||
return ParticleType::neutron;
|
||||
} else if (str == "photon") {
|
||||
return Particle::Type::photon;
|
||||
return ParticleType::photon;
|
||||
} else if (str == "electron") {
|
||||
return Particle::Type::electron;
|
||||
return ParticleType::electron;
|
||||
} else if (str == "positron") {
|
||||
return Particle::Type::positron;
|
||||
return ParticleType::positron;
|
||||
} else {
|
||||
throw std::invalid_argument{fmt::format("Invalid particle name: {}", str)};
|
||||
}
|
||||
|
|
|
|||
56
src/particle_data.cpp
Normal file
56
src/particle_data.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "openmc/particle_data.h"
|
||||
|
||||
#include "openmc/geometry.h"
|
||||
#include "openmc/nuclide.h"
|
||||
#include "openmc/photon.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/tallies/derivative.h"
|
||||
#include "openmc/tallies/filter.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
void LocalCoord::rotate(const vector<double>& rotation)
|
||||
{
|
||||
r = r.rotate(rotation);
|
||||
u = u.rotate(rotation);
|
||||
rotated = true;
|
||||
}
|
||||
|
||||
void LocalCoord::reset()
|
||||
{
|
||||
cell = C_NONE;
|
||||
universe = C_NONE;
|
||||
lattice = C_NONE;
|
||||
lattice_i[0] = 0;
|
||||
lattice_i[1] = 0;
|
||||
lattice_i[2] = 0;
|
||||
rotated = false;
|
||||
}
|
||||
|
||||
ParticleData::ParticleData()
|
||||
{
|
||||
// Create and clear coordinate levels
|
||||
coord_.resize(model::n_coord_levels);
|
||||
cell_last_.resize(model::n_coord_levels);
|
||||
clear();
|
||||
|
||||
zero_delayed_bank();
|
||||
|
||||
// Every particle starts with no accumulated flux derivative. Note that in
|
||||
// event mode, we construct the particle once up front, so have to run this
|
||||
// even if the current batch is inactive.
|
||||
if (!model::active_tallies.empty() || settings::event_based) {
|
||||
flux_derivs_.resize(model::tally_derivs.size());
|
||||
zero_flux_derivs();
|
||||
}
|
||||
|
||||
// Allocate space for tally filter matches
|
||||
filter_matches_.resize(model::tally_filters.size());
|
||||
|
||||
// Create microscopic cross section caches
|
||||
neutron_xs_.resize(data::nuclides.size());
|
||||
photon_xs_.resize(data::elements.size());
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "openmc/particle_restart.h"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/mgxs_interface.h"
|
||||
|
|
@ -15,7 +16,6 @@
|
|||
#include "openmc/track_output.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -41,28 +41,28 @@ void read_particle_restart(Particle& p, RunMode& previous_run_mode)
|
|||
} else if (mode == "fixed source") {
|
||||
previous_run_mode = RunMode::FIXED_SOURCE;
|
||||
}
|
||||
read_dataset(file_id, "id", p.id_);
|
||||
read_dataset(file_id, "id", p.id());
|
||||
int type;
|
||||
read_dataset(file_id, "type", type);
|
||||
p.type_ = static_cast<Particle::Type>(type);
|
||||
read_dataset(file_id, "weight", p.wgt_);
|
||||
read_dataset(file_id, "energy", p.E_);
|
||||
p.type() = static_cast<ParticleType>(type);
|
||||
read_dataset(file_id, "weight", p.wgt());
|
||||
read_dataset(file_id, "energy", p.E());
|
||||
read_dataset(file_id, "xyz", p.r());
|
||||
read_dataset(file_id, "uvw", p.u());
|
||||
|
||||
// Set energy group and average energy in multi-group mode
|
||||
if (!settings::run_CE) {
|
||||
p.g_ = p.E_;
|
||||
p.E_ = data::mg.energy_bin_avg_[p.g_];
|
||||
p.g() = p.E();
|
||||
p.E() = data::mg.energy_bin_avg_[p.g()];
|
||||
}
|
||||
|
||||
// Set particle last attributes
|
||||
p.wgt_last_ = p.wgt_;
|
||||
p.r_last_current_ = p.r();
|
||||
p.r_last_ = p.r();
|
||||
p.u_last_ = p.u();
|
||||
p.E_last_ = p.E_;
|
||||
p.g_last_ = p.g_;
|
||||
p.wgt_last() = p.wgt();
|
||||
p.r_last_current() = p.r();
|
||||
p.r_last() = p.r();
|
||||
p.u_last() = p.u();
|
||||
p.E_last() = p.E();
|
||||
p.g_last() = p.g();
|
||||
|
||||
// Close hdf5 file
|
||||
file_close(file_id);
|
||||
|
|
@ -84,7 +84,8 @@ void run_particle_restart()
|
|||
read_particle_restart(p, previous_run_mode);
|
||||
|
||||
// write track if that was requested on command line
|
||||
if (settings::write_all_tracks) p.write_track_ = true;
|
||||
if (settings::write_all_tracks)
|
||||
p.write_track() = true;
|
||||
|
||||
// Set all tallies to 0 for now (just tracking errors)
|
||||
model::tallies.clear();
|
||||
|
|
@ -93,33 +94,27 @@ void run_particle_restart()
|
|||
int64_t particle_seed;
|
||||
switch (previous_run_mode) {
|
||||
case RunMode::EIGENVALUE:
|
||||
particle_seed = (simulation::total_gen + overall_generation() - 1)*settings::n_particles + p.id_;
|
||||
particle_seed = (simulation::total_gen + overall_generation() - 1) *
|
||||
settings::n_particles +
|
||||
p.id();
|
||||
break;
|
||||
case RunMode::FIXED_SOURCE:
|
||||
particle_seed = p.id_;
|
||||
particle_seed = p.id();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error{"Unexpected run mode: " +
|
||||
std::to_string(static_cast<int>(previous_run_mode))};
|
||||
}
|
||||
init_particle_seeds(particle_seed, p.seeds_);
|
||||
init_particle_seeds(particle_seed, p.seeds());
|
||||
|
||||
// Force calculation of cross-sections by setting last energy to zero
|
||||
if (settings::run_CE) {
|
||||
for (auto& micro : p.neutron_xs_) micro.last_E = 0.0;
|
||||
p.invalidate_neutron_xs();
|
||||
}
|
||||
|
||||
// Prepare to write out particle track.
|
||||
if (p.write_track_) add_particle_track(p);
|
||||
|
||||
// Every particle starts with no accumulated flux derivative.
|
||||
if (!model::active_tallies.empty()) {
|
||||
p.flux_derivs_.resize(model::tally_derivs.size(), 0.0);
|
||||
std::fill(p.flux_derivs_.begin(), p.flux_derivs_.end(), 0.0);
|
||||
}
|
||||
|
||||
// Allocate space for tally filter matches
|
||||
p.filter_matches_.resize(model::tally_filters.size());
|
||||
if (p.write_track())
|
||||
add_particle_track(p);
|
||||
|
||||
// Transport neutron
|
||||
transport_history_based_single_particle(p);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "openmc/photon.h"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/bremsstrahlung.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/distribution_multi.h"
|
||||
|
|
@ -15,7 +16,6 @@
|
|||
#include "xtensor/xoperation.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <tuple> // for tie
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ namespace data {
|
|||
xt::xtensor<double, 1> compton_profile_pz;
|
||||
|
||||
std::unordered_map<std::string, int> element_map;
|
||||
std::vector<std::unique_ptr<PhotonInteraction>> elements;
|
||||
vector<unique_ptr<PhotonInteraction>> elements;
|
||||
|
||||
} // namespace data
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
|
||||
// Read subshell photoionization cross section and atomic relaxation data
|
||||
rgroup = open_group(group, "subshells");
|
||||
std::vector<std::string> designators;
|
||||
vector<std::string> designators;
|
||||
read_attribute(rgroup, "designators", designators);
|
||||
auto n_shell = designators.size();
|
||||
if (n_shell == 0) {
|
||||
|
|
@ -233,7 +233,7 @@ PhotonInteraction::PhotonInteraction(hid_t group)
|
|||
close_group(rgroup);
|
||||
|
||||
// Truncate the bremsstrahlung data at the cutoff energy
|
||||
int photon = static_cast<int>(Particle::Type::photon);
|
||||
int photon = static_cast<int>(ParticleType::photon);
|
||||
const auto& E {electron_energy};
|
||||
double cutoff = settings::energy_cutoff[photon];
|
||||
if (cutoff > E(0)) {
|
||||
|
|
@ -456,7 +456,7 @@ void PhotonInteraction::calculate_xs(Particle& p) const
|
|||
// Perform binary search on the element energy grid in order to determine
|
||||
// which points to interpolate between
|
||||
int n_grid = energy_.size();
|
||||
double log_E = std::log(p.E_);
|
||||
double log_E = std::log(p.E());
|
||||
int i_grid;
|
||||
if (log_E <= energy_[0]) {
|
||||
i_grid = 0;
|
||||
|
|
@ -474,7 +474,7 @@ void PhotonInteraction::calculate_xs(Particle& p) const
|
|||
// calculate interpolation factor
|
||||
double f = (log_E - energy_(i_grid)) / (energy_(i_grid+1) - energy_(i_grid));
|
||||
|
||||
auto& xs {p.photon_xs_[index_]};
|
||||
auto& xs {p.photon_xs(index_)};
|
||||
xs.index_grid = i_grid;
|
||||
xs.interp_factor = f;
|
||||
|
||||
|
|
@ -508,7 +508,7 @@ void PhotonInteraction::calculate_xs(Particle& p) const
|
|||
|
||||
// Calculate microscopic total cross section
|
||||
xs.total = xs.coherent + xs.incoherent + xs.photoelectric + xs.pair_production;
|
||||
xs.last_E = p.E_;
|
||||
xs.last_E = p.E();
|
||||
}
|
||||
|
||||
double PhotonInteraction::rayleigh_scatter(double alpha, uint64_t* seed) const
|
||||
|
|
@ -666,7 +666,7 @@ void PhotonInteraction::atomic_relaxation(const ElectronSubshell& shell, Particl
|
|||
if (shell.n_transitions == 0) {
|
||||
Direction u = isotropic_direction(p.current_seed());
|
||||
double E = shell.binding_energy;
|
||||
p.create_secondary(p.wgt_, u, E, Particle::Type::photon);
|
||||
p.create_secondary(p.wgt(), u, E, ParticleType::photon);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -693,7 +693,7 @@ void PhotonInteraction::atomic_relaxation(const ElectronSubshell& shell, Particl
|
|||
// Non-radiative transition -- Auger/Coster-Kronig effect
|
||||
|
||||
// Create auger electron
|
||||
p.create_secondary(p.wgt_, u, E, Particle::Type::electron);
|
||||
p.create_secondary(p.wgt(), u, E, ParticleType::electron);
|
||||
|
||||
// Fill hole left by emitted auger electron
|
||||
int i_hole = shell_map_.at(secondary);
|
||||
|
|
@ -703,7 +703,7 @@ void PhotonInteraction::atomic_relaxation(const ElectronSubshell& shell, Particl
|
|||
// Radiative transition -- get X-ray energy
|
||||
|
||||
// Create fluorescent photon
|
||||
p.create_secondary(p.wgt_, u, E, Particle::Type::photon);
|
||||
p.create_secondary(p.wgt(), u, E, ParticleType::photon);
|
||||
}
|
||||
|
||||
// Fill hole created by electron transitioning to the photoelectron hole
|
||||
|
|
|
|||
307
src/physics.cpp
307
src/physics.cpp
|
|
@ -38,46 +38,46 @@ namespace openmc {
|
|||
void collision(Particle& p)
|
||||
{
|
||||
// Add to collision counter for particle
|
||||
++(p.n_collision_);
|
||||
++(p.n_collision());
|
||||
|
||||
// Sample reaction for the material the particle is in
|
||||
switch (p.type_) {
|
||||
case Particle::Type::neutron:
|
||||
switch (p.type()) {
|
||||
case ParticleType::neutron:
|
||||
sample_neutron_reaction(p);
|
||||
break;
|
||||
case Particle::Type::photon:
|
||||
case ParticleType::photon:
|
||||
sample_photon_reaction(p);
|
||||
break;
|
||||
case Particle::Type::electron:
|
||||
case ParticleType::electron:
|
||||
sample_electron_reaction(p);
|
||||
break;
|
||||
case Particle::Type::positron:
|
||||
case ParticleType::positron:
|
||||
sample_positron_reaction(p);
|
||||
break;
|
||||
}
|
||||
|
||||
// Kill particle if energy falls below cutoff
|
||||
int type = static_cast<int>(p.type_);
|
||||
if (p.E_ < settings::energy_cutoff[type]) {
|
||||
p.alive_ = false;
|
||||
p.wgt_ = 0.0;
|
||||
int type = static_cast<int>(p.type());
|
||||
if (p.E() < settings::energy_cutoff[type]) {
|
||||
p.alive() = false;
|
||||
p.wgt() = 0.0;
|
||||
}
|
||||
|
||||
// Display information about collision
|
||||
if (settings::verbosity >= 10 || p.trace_) {
|
||||
if (settings::verbosity >= 10 || p.trace()) {
|
||||
std::string msg;
|
||||
if (p.event_ == TallyEvent::KILL) {
|
||||
msg = fmt::format(" Killed. Energy = {} eV.", p.E_);
|
||||
} else if (p.type_ == Particle::Type::neutron) {
|
||||
if (p.event() == TallyEvent::KILL) {
|
||||
msg = fmt::format(" Killed. Energy = {} eV.", p.E());
|
||||
} else if (p.type() == ParticleType::neutron) {
|
||||
msg = fmt::format(" {} with {}. Energy = {} eV.",
|
||||
reaction_name(p.event_mt_), data::nuclides[p.event_nuclide_]->name_,
|
||||
p.E_);
|
||||
} else if (p.type_ == Particle::Type::photon) {
|
||||
reaction_name(p.event_mt()), data::nuclides[p.event_nuclide()]->name_,
|
||||
p.E());
|
||||
} else if (p.type() == ParticleType::photon) {
|
||||
msg = fmt::format(" {} with {}. Energy = {} eV.",
|
||||
reaction_name(p.event_mt_),
|
||||
to_element(data::nuclides[p.event_nuclide_]->name_), p.E_);
|
||||
reaction_name(p.event_mt()),
|
||||
to_element(data::nuclides[p.event_nuclide()]->name_), p.E());
|
||||
} else {
|
||||
msg = fmt::format(" Disappeared. Energy = {} eV.", p.E_);
|
||||
msg = fmt::format(" Disappeared. Energy = {} eV.", p.E());
|
||||
}
|
||||
write_message(msg, 1);
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ void sample_neutron_reaction(Particle& p)
|
|||
int i_nuclide = sample_nuclide(p);
|
||||
|
||||
// Save which nuclide particle had collision with
|
||||
p.event_nuclide_ = i_nuclide;
|
||||
p.event_nuclide() = i_nuclide;
|
||||
|
||||
// Create fission bank sites. Note that while a fission reaction is sampled,
|
||||
// it never actually "happens", i.e. the weight of the particle does not
|
||||
|
|
@ -108,7 +108,7 @@ void sample_neutron_reaction(Particle& p)
|
|||
|
||||
// Make sure particle population doesn't grow out of control for
|
||||
// subcritical multiplication problems.
|
||||
if (p.secondary_bank_.size() >= 10000) {
|
||||
if (p.secondary_bank().size() >= 10000) {
|
||||
fatal_error("The secondary particle bank appears to be growing without "
|
||||
"bound. You are likely running a subcritical multiplication problem "
|
||||
"with k-effective close to or greater than one.");
|
||||
|
|
@ -124,28 +124,30 @@ void sample_neutron_reaction(Particle& p)
|
|||
// If survival biasing is being used, the following subroutine adjusts the
|
||||
// weight of the particle. Otherwise, it checks to see if absorption occurs
|
||||
|
||||
if (p.neutron_xs_[i_nuclide].absorption > 0.0) {
|
||||
if (p.neutron_xs(i_nuclide).absorption > 0.0) {
|
||||
absorption(p, i_nuclide);
|
||||
} else {
|
||||
p.wgt_absorb_ = 0.0;
|
||||
p.wgt_absorb() = 0.0;
|
||||
}
|
||||
if (!p.alive_) return;
|
||||
if (!p.alive())
|
||||
return;
|
||||
|
||||
// Sample a scattering reaction and determine the secondary energy of the
|
||||
// exiting neutron
|
||||
scatter(p, i_nuclide);
|
||||
|
||||
// Advance URR seed stream 'N' times after energy changes
|
||||
if (p.E_ != p.E_last_) {
|
||||
p.stream_ = STREAM_URR_PTABLE;
|
||||
if (p.E() != p.E_last()) {
|
||||
p.stream() = STREAM_URR_PTABLE;
|
||||
advance_prn_seed(data::nuclides.size(), p.current_seed());
|
||||
p.stream_ = STREAM_TRACKING;
|
||||
p.stream() = STREAM_TRACKING;
|
||||
}
|
||||
|
||||
// Play russian roulette if survival biasing is turned on
|
||||
if (settings::survival_biasing) {
|
||||
russian_roulette(p);
|
||||
if (!p.alive_) return;
|
||||
if (!p.alive())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,8 +159,9 @@ create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
double weight = settings::ufs_on ? ufs_get_weight(p) : 1.0;
|
||||
|
||||
// Determine the expected number of neutrons produced
|
||||
double nu_t = p.wgt_ / simulation::keff * weight * p.neutron_xs_[
|
||||
i_nuclide].nu_fission / p.neutron_xs_[i_nuclide].total;
|
||||
double nu_t = p.wgt() / simulation::keff * weight *
|
||||
p.neutron_xs(i_nuclide).nu_fission /
|
||||
p.neutron_xs(i_nuclide).total;
|
||||
|
||||
// Sample the number of neutrons produced
|
||||
int nu = static_cast<int>(nu_t);
|
||||
|
|
@ -173,9 +176,9 @@ create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
double nu_d[MAX_DELAYED_GROUPS] = {0.};
|
||||
|
||||
// Clear out particle's nu fission bank
|
||||
p.nu_bank_.clear();
|
||||
p.nu_bank().clear();
|
||||
|
||||
p.fission_ = true;
|
||||
p.fission() = true;
|
||||
int skipped = 0;
|
||||
|
||||
// Determine whether to place fission sites into the shared fission bank
|
||||
|
|
@ -184,16 +187,16 @@ create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
|
||||
for (int i = 0; i < nu; ++i) {
|
||||
// Initialize fission site object with particle data
|
||||
Particle::Bank site;
|
||||
SourceSite site;
|
||||
site.r = p.r();
|
||||
site.particle = Particle::Type::neutron;
|
||||
site.particle = ParticleType::neutron;
|
||||
site.wgt = 1. / weight;
|
||||
site.parent_id = p.id_;
|
||||
site.progeny_id = p.n_progeny_++;
|
||||
site.parent_id = p.id();
|
||||
site.progeny_id = p.n_progeny()++;
|
||||
site.surf_id = 0;
|
||||
|
||||
// Sample delayed group and angle/energy for fission reaction
|
||||
sample_fission_neutron(i_nuclide, rx, p.E_, &site, p.current_seed());
|
||||
sample_fission_neutron(i_nuclide, rx, p.E(), &site, p.current_seed());
|
||||
|
||||
// Store fission site in bank
|
||||
if (use_fission_bank) {
|
||||
|
|
@ -205,20 +208,20 @@ create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
p.secondary_bank_.push_back(site);
|
||||
p.secondary_bank().push_back(site);
|
||||
}
|
||||
|
||||
// Set the delayed group on the particle as well
|
||||
p.delayed_group_ = site.delayed_group;
|
||||
p.delayed_group() = site.delayed_group;
|
||||
|
||||
// Increment the number of neutrons born delayed
|
||||
if (p.delayed_group_ > 0) {
|
||||
nu_d[p.delayed_group_-1]++;
|
||||
if (p.delayed_group() > 0) {
|
||||
nu_d[p.delayed_group() - 1]++;
|
||||
}
|
||||
|
||||
// Write fission particles to nuBank
|
||||
p.nu_bank_.emplace_back();
|
||||
Particle::NuBank* nu_bank_entry = &p.nu_bank_.back();
|
||||
p.nu_bank().emplace_back();
|
||||
NuBank* nu_bank_entry = &p.nu_bank().back();
|
||||
nu_bank_entry->wgt = site.wgt;
|
||||
nu_bank_entry->E = site.E;
|
||||
nu_bank_entry->delayed_group = site.delayed_group;
|
||||
|
|
@ -227,7 +230,7 @@ create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
// If shared fission bank was full, and no fissions could be added,
|
||||
// set the particle fission flag to false.
|
||||
if (nu == skipped) {
|
||||
p.fission_ = false;
|
||||
p.fission() = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -236,10 +239,10 @@ create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
nu -= skipped;
|
||||
|
||||
// Store the total weight banked for analog fission tallies
|
||||
p.n_bank_ = nu;
|
||||
p.wgt_bank_ = nu / weight;
|
||||
p.n_bank() = nu;
|
||||
p.wgt_bank() = nu / weight;
|
||||
for (size_t d = 0; d < MAX_DELAYED_GROUPS; d++) {
|
||||
p.n_delayed_bank_[d] = nu_d[d];
|
||||
p.n_delayed_bank(d) = nu_d[d];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,20 +251,20 @@ void sample_photon_reaction(Particle& p)
|
|||
// Kill photon if below energy cutoff -- an extra check is made here because
|
||||
// photons with energy below the cutoff may have been produced by neutrons
|
||||
// reactions or atomic relaxation
|
||||
int photon = static_cast<int>(Particle::Type::photon);
|
||||
if (p.E_ < settings::energy_cutoff[photon]) {
|
||||
p.E_ = 0.0;
|
||||
p.alive_ = false;
|
||||
int photon = static_cast<int>(ParticleType::photon);
|
||||
if (p.E() < settings::energy_cutoff[photon]) {
|
||||
p.E() = 0.0;
|
||||
p.alive() = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Sample element within material
|
||||
int i_element = sample_element(p);
|
||||
const auto& micro {p.photon_xs_[i_element]};
|
||||
const auto& micro {p.photon_xs(i_element)};
|
||||
const auto& element {*data::elements[i_element]};
|
||||
|
||||
// Calculate photon energy over electron rest mass equivalent
|
||||
double alpha = p.E_/MASS_ELECTRON_EV;
|
||||
double alpha = p.E() / MASS_ELECTRON_EV;
|
||||
|
||||
// For tallying purposes, this routine might be called directly. In that
|
||||
// case, we need to sample a reaction via the cutoff variable
|
||||
|
|
@ -273,8 +276,8 @@ void sample_photon_reaction(Particle& p)
|
|||
if (prob > cutoff) {
|
||||
double mu = element.rayleigh_scatter(alpha, p.current_seed());
|
||||
p.u() = rotate_angle(p.u(), mu, nullptr, p.current_seed());
|
||||
p.event_ = TallyEvent::SCATTER;
|
||||
p.event_mt_ = COHERENT;
|
||||
p.event() = TallyEvent::SCATTER;
|
||||
p.event_mt() = COHERENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -297,12 +300,12 @@ void sample_photon_reaction(Particle& p)
|
|||
// Create Compton electron
|
||||
double phi = uniform_distribution(0., 2.0*PI, p.current_seed());
|
||||
double E_electron = (alpha - alpha_out)*MASS_ELECTRON_EV - e_b;
|
||||
int electron = static_cast<int>(Particle::Type::electron);
|
||||
int electron = static_cast<int>(ParticleType::electron);
|
||||
if (E_electron >= settings::energy_cutoff[electron]) {
|
||||
double mu_electron = (alpha - alpha_out*mu)
|
||||
/ std::sqrt(alpha*alpha + alpha_out*alpha_out - 2.0*alpha*alpha_out*mu);
|
||||
Direction u = rotate_angle(p.u(), mu_electron, &phi, p.current_seed());
|
||||
p.create_secondary(p.wgt_, u, E_electron, Particle::Type::electron);
|
||||
p.create_secondary(p.wgt(), u, E_electron, ParticleType::electron);
|
||||
}
|
||||
|
||||
// TODO: Compton subshell data does not match atomic relaxation data
|
||||
|
|
@ -314,10 +317,10 @@ void sample_photon_reaction(Particle& p)
|
|||
}
|
||||
|
||||
phi += PI;
|
||||
p.E_ = alpha_out*MASS_ELECTRON_EV;
|
||||
p.E() = alpha_out * MASS_ELECTRON_EV;
|
||||
p.u() = rotate_angle(p.u(), mu, &phi, p.current_seed());
|
||||
p.event_ = TallyEvent::SCATTER;
|
||||
p.event_mt_ = INCOHERENT;
|
||||
p.event() = TallyEvent::SCATTER;
|
||||
p.event_mt() = INCOHERENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +343,7 @@ void sample_photon_reaction(Particle& p)
|
|||
|
||||
prob += xs;
|
||||
if (prob > cutoff) {
|
||||
double E_electron = p.E_ - shell.binding_energy;
|
||||
double E_electron = p.E() - shell.binding_energy;
|
||||
|
||||
// Sample mu using non-relativistic Sauter distribution.
|
||||
// See Eqns 3.19 and 3.20 in "Implementing a photon physics
|
||||
|
|
@ -363,15 +366,15 @@ void sample_photon_reaction(Particle& p)
|
|||
u.z = std::sqrt(1.0 - mu*mu)*std::sin(phi);
|
||||
|
||||
// Create secondary electron
|
||||
p.create_secondary(p.wgt_, u, E_electron, Particle::Type::electron);
|
||||
p.create_secondary(p.wgt(), u, E_electron, ParticleType::electron);
|
||||
|
||||
// Allow electrons to fill orbital and produce auger electrons
|
||||
// and fluorescent photons
|
||||
element.atomic_relaxation(shell, p);
|
||||
p.event_ = TallyEvent::ABSORB;
|
||||
p.event_mt_ = 533 + shell.index_subshell;
|
||||
p.alive_ = false;
|
||||
p.E_ = 0.0;
|
||||
p.event() = TallyEvent::ABSORB;
|
||||
p.event_mt() = 533 + shell.index_subshell;
|
||||
p.alive() = false;
|
||||
p.E() = 0.0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -388,16 +391,16 @@ void sample_photon_reaction(Particle& p)
|
|||
|
||||
// Create secondary electron
|
||||
Direction u = rotate_angle(p.u(), mu_electron, nullptr, p.current_seed());
|
||||
p.create_secondary(p.wgt_, u, E_electron, Particle::Type::electron);
|
||||
p.create_secondary(p.wgt(), u, E_electron, ParticleType::electron);
|
||||
|
||||
// Create secondary positron
|
||||
u = rotate_angle(p.u(), mu_positron, nullptr, p.current_seed());
|
||||
p.create_secondary(p.wgt_, u, E_positron, Particle::Type::positron);
|
||||
p.create_secondary(p.wgt(), u, E_positron, ParticleType::positron);
|
||||
|
||||
p.event_ = TallyEvent::ABSORB;
|
||||
p.event_mt_ = PAIR_PROD;
|
||||
p.alive_ = false;
|
||||
p.E_ = 0.0;
|
||||
p.event() = TallyEvent::ABSORB;
|
||||
p.event_mt() = PAIR_PROD;
|
||||
p.alive() = false;
|
||||
p.E() = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,9 +413,9 @@ void sample_electron_reaction(Particle& p)
|
|||
thick_target_bremsstrahlung(p, &E_lost);
|
||||
}
|
||||
|
||||
p.E_ = 0.0;
|
||||
p.alive_ = false;
|
||||
p.event_ = TallyEvent::ABSORB;
|
||||
p.E() = 0.0;
|
||||
p.alive() = false;
|
||||
p.event() = TallyEvent::ABSORB;
|
||||
}
|
||||
|
||||
void sample_positron_reaction(Particle& p)
|
||||
|
|
@ -428,21 +431,21 @@ void sample_positron_reaction(Particle& p)
|
|||
Direction u = isotropic_direction(p.current_seed());
|
||||
|
||||
// Create annihilation photon pair traveling in opposite directions
|
||||
p.create_secondary(p.wgt_, u, MASS_ELECTRON_EV, Particle::Type::photon);
|
||||
p.create_secondary(p.wgt_, -u, MASS_ELECTRON_EV, Particle::Type::photon);
|
||||
p.create_secondary(p.wgt(), u, MASS_ELECTRON_EV, ParticleType::photon);
|
||||
p.create_secondary(p.wgt(), -u, MASS_ELECTRON_EV, ParticleType::photon);
|
||||
|
||||
p.E_ = 0.0;
|
||||
p.alive_ = false;
|
||||
p.event_ = TallyEvent::ABSORB;
|
||||
p.E() = 0.0;
|
||||
p.alive() = false;
|
||||
p.event() = TallyEvent::ABSORB;
|
||||
}
|
||||
|
||||
int sample_nuclide(Particle& p)
|
||||
{
|
||||
// Sample cumulative distribution function
|
||||
double cutoff = prn(p.current_seed()) * p.macro_xs_.total;
|
||||
double cutoff = prn(p.current_seed()) * p.macro_xs().total;
|
||||
|
||||
// Get pointers to nuclide/density arrays
|
||||
const auto& mat {model::materials[p.material_]};
|
||||
const auto& mat {model::materials[p.material()]};
|
||||
int n = mat->nuclide_.size();
|
||||
|
||||
double prob = 0.0;
|
||||
|
|
@ -452,7 +455,7 @@ int sample_nuclide(Particle& p)
|
|||
double atom_density = mat->atom_density_[i];
|
||||
|
||||
// Increment probability to compare to cutoff
|
||||
prob += atom_density * p.neutron_xs_[i_nuclide].total;
|
||||
prob += atom_density * p.neutron_xs(i_nuclide).total;
|
||||
if (prob >= cutoff) return i_nuclide;
|
||||
}
|
||||
|
||||
|
|
@ -464,10 +467,10 @@ int sample_nuclide(Particle& p)
|
|||
int sample_element(Particle& p)
|
||||
{
|
||||
// Sample cumulative distribution function
|
||||
double cutoff = prn(p.current_seed()) * p.macro_xs_.total;
|
||||
double cutoff = prn(p.current_seed()) * p.macro_xs().total;
|
||||
|
||||
// Get pointers to elements, densities
|
||||
const auto& mat {model::materials[p.material_]};
|
||||
const auto& mat {model::materials[p.material()]};
|
||||
|
||||
double prob = 0.0;
|
||||
for (int i = 0; i < mat->element_.size(); ++i) {
|
||||
|
|
@ -476,13 +479,13 @@ int sample_element(Particle& p)
|
|||
double atom_density = mat->atom_density_[i];
|
||||
|
||||
// Determine microscopic cross section
|
||||
double sigma = atom_density * p.photon_xs_[i_element].total;
|
||||
double sigma = atom_density * p.photon_xs(i_element).total;
|
||||
|
||||
// Increment probability to compare to cutoff
|
||||
prob += sigma;
|
||||
if (prob > cutoff) {
|
||||
// Save which nuclide particle had collision with for tally purpose
|
||||
p.event_nuclide_ = mat->nuclide_[i];
|
||||
p.event_nuclide() = mat->nuclide_[i];
|
||||
|
||||
return i_element;
|
||||
}
|
||||
|
|
@ -501,23 +504,23 @@ Reaction& sample_fission(int i_nuclide, Particle& p)
|
|||
// If we're in the URR, by default use the first fission reaction. We also
|
||||
// default to the first reaction if we know that there are no partial fission
|
||||
// reactions
|
||||
if (p.neutron_xs_[i_nuclide].use_ptable || !nuc->has_partial_fission_) {
|
||||
if (p.neutron_xs(i_nuclide).use_ptable || !nuc->has_partial_fission_) {
|
||||
return *nuc->fission_rx_[0];
|
||||
}
|
||||
|
||||
// Check to see if we are in a windowed multipole range. WMP only supports
|
||||
// the first fission reaction.
|
||||
if (nuc->multipole_) {
|
||||
if (p.E_ >= nuc->multipole_->E_min_ && p.E_ <= nuc->multipole_->E_max_) {
|
||||
if (p.E() >= nuc->multipole_->E_min_ && p.E() <= nuc->multipole_->E_max_) {
|
||||
return *nuc->fission_rx_[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Get grid index and interpolatoin factor and sample fission cdf
|
||||
int i_temp = p.neutron_xs_[i_nuclide].index_temp;
|
||||
int i_grid = p.neutron_xs_[i_nuclide].index_grid;
|
||||
double f = p.neutron_xs_[i_nuclide].interp_factor;
|
||||
double cutoff = prn(p.current_seed()) * p.neutron_xs_[i_nuclide].fission;
|
||||
int i_temp = p.neutron_xs(i_nuclide).index_temp;
|
||||
int i_grid = p.neutron_xs(i_nuclide).index_grid;
|
||||
double f = p.neutron_xs(i_nuclide).interp_factor;
|
||||
double cutoff = prn(p.current_seed()) * p.neutron_xs(i_nuclide).fission;
|
||||
double prob = 0.0;
|
||||
|
||||
// Loop through each partial fission reaction type
|
||||
|
|
@ -541,10 +544,10 @@ Reaction& sample_fission(int i_nuclide, Particle& p)
|
|||
void sample_photon_product(int i_nuclide, Particle& p, int* i_rx, int* i_product)
|
||||
{
|
||||
// Get grid index and interpolation factor and sample photon production cdf
|
||||
int i_temp = p.neutron_xs_[i_nuclide].index_temp;
|
||||
int i_grid = p.neutron_xs_[i_nuclide].index_grid;
|
||||
double f = p.neutron_xs_[i_nuclide].interp_factor;
|
||||
double cutoff = prn(p.current_seed()) * p.neutron_xs_[i_nuclide].photon_prod;
|
||||
int i_temp = p.neutron_xs(i_nuclide).index_temp;
|
||||
int i_grid = p.neutron_xs(i_nuclide).index_grid;
|
||||
double f = p.neutron_xs(i_nuclide).interp_factor;
|
||||
double cutoff = prn(p.current_seed()) * p.neutron_xs(i_nuclide).photon_prod;
|
||||
double prob = 0.0;
|
||||
|
||||
// Loop through each reaction type
|
||||
|
|
@ -561,22 +564,22 @@ void sample_photon_product(int i_nuclide, Particle& p, int* i_rx, int* i_product
|
|||
+ f*(rx->xs_[i_temp].value[i_grid - threshold + 1]));
|
||||
|
||||
for (int j = 0; j < rx->products_.size(); ++j) {
|
||||
if (rx->products_[j].particle_ == Particle::Type::photon) {
|
||||
if (rx->products_[j].particle_ == ParticleType::photon) {
|
||||
// For fission, artificially increase the photon yield to account
|
||||
// for delayed photons
|
||||
double f = 1.0;
|
||||
if (settings::delayed_photon_scaling) {
|
||||
if (is_fission(rx->mt_)) {
|
||||
if (nuc->prompt_photons_ && nuc->delayed_photons_) {
|
||||
double energy_prompt = (*nuc->prompt_photons_)(p.E_);
|
||||
double energy_delayed = (*nuc->delayed_photons_)(p.E_);
|
||||
double energy_prompt = (*nuc->prompt_photons_)(p.E());
|
||||
double energy_delayed = (*nuc->delayed_photons_)(p.E());
|
||||
f = (energy_prompt + energy_delayed)/(energy_prompt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add to cumulative probability
|
||||
prob += f * (*rx->products_[j].yield_)(p.E_) * xs;
|
||||
prob += f * (*rx->products_[j].yield_)(p.E()) * xs;
|
||||
|
||||
*i_rx = i;
|
||||
*i_product = j;
|
||||
|
|
@ -590,31 +593,33 @@ void absorption(Particle& p, int i_nuclide)
|
|||
{
|
||||
if (settings::survival_biasing) {
|
||||
// Determine weight absorbed in survival biasing
|
||||
p.wgt_absorb_ = p.wgt_ * p.neutron_xs_[i_nuclide].absorption /
|
||||
p.neutron_xs_[i_nuclide].total;
|
||||
p.wgt_absorb() = p.wgt() * p.neutron_xs(i_nuclide).absorption /
|
||||
p.neutron_xs(i_nuclide).total;
|
||||
|
||||
// Adjust weight of particle by probability of absorption
|
||||
p.wgt_ -= p.wgt_absorb_;
|
||||
p.wgt_last_ = p.wgt_;
|
||||
p.wgt() -= p.wgt_absorb();
|
||||
p.wgt_last() = p.wgt();
|
||||
|
||||
// Score implicit absorption estimate of keff
|
||||
if (settings::run_mode == RunMode::EIGENVALUE) {
|
||||
p.keff_tally_absorption_ += p.wgt_absorb_ * p.neutron_xs_[
|
||||
i_nuclide].nu_fission / p.neutron_xs_[i_nuclide].absorption;
|
||||
p.keff_tally_absorption() += p.wgt_absorb() *
|
||||
p.neutron_xs(i_nuclide).nu_fission /
|
||||
p.neutron_xs(i_nuclide).absorption;
|
||||
}
|
||||
} else {
|
||||
// See if disappearance reaction happens
|
||||
if (p.neutron_xs_[i_nuclide].absorption >
|
||||
prn(p.current_seed()) * p.neutron_xs_[i_nuclide].total) {
|
||||
if (p.neutron_xs(i_nuclide).absorption >
|
||||
prn(p.current_seed()) * p.neutron_xs(i_nuclide).total) {
|
||||
// Score absorption estimate of keff
|
||||
if (settings::run_mode == RunMode::EIGENVALUE) {
|
||||
p.keff_tally_absorption_ += p.wgt_ * p.neutron_xs_[
|
||||
i_nuclide].nu_fission / p.neutron_xs_[i_nuclide].absorption;
|
||||
p.keff_tally_absorption() += p.wgt() *
|
||||
p.neutron_xs(i_nuclide).nu_fission /
|
||||
p.neutron_xs(i_nuclide).absorption;
|
||||
}
|
||||
|
||||
p.alive_ = false;
|
||||
p.event_ = TallyEvent::ABSORB;
|
||||
p.event_mt_ = N_DISAPPEAR;
|
||||
p.alive() = false;
|
||||
p.event() = TallyEvent::ABSORB;
|
||||
p.event_mt() = N_DISAPPEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -626,7 +631,7 @@ void scatter(Particle& p, int i_nuclide)
|
|||
|
||||
// Get pointer to nuclide and grid index/interpolation factor
|
||||
const auto& nuc {data::nuclides[i_nuclide]};
|
||||
const auto& micro {p.neutron_xs_[i_nuclide]};
|
||||
const auto& micro {p.neutron_xs(i_nuclide)};
|
||||
int i_temp = micro.index_temp;
|
||||
int i_grid = micro.index_grid;
|
||||
double f = micro.interp_factor;
|
||||
|
|
@ -647,12 +652,12 @@ void scatter(Particle& p, int i_nuclide)
|
|||
// NON-S(A,B) ELASTIC SCATTERING
|
||||
|
||||
// Determine temperature
|
||||
double kT = nuc->multipole_ ? p.sqrtkT_*p.sqrtkT_ : nuc->kTs_[i_temp];
|
||||
double kT = nuc->multipole_ ? p.sqrtkT() * p.sqrtkT() : nuc->kTs_[i_temp];
|
||||
|
||||
// Perform collision physics for elastic scattering
|
||||
elastic_scatter(i_nuclide, *nuc->reactions_[0], kT, p);
|
||||
|
||||
p.event_mt_ = ELASTIC;
|
||||
p.event_mt() = ELASTIC;
|
||||
sampled = true;
|
||||
}
|
||||
|
||||
|
|
@ -663,7 +668,7 @@ void scatter(Particle& p, int i_nuclide)
|
|||
|
||||
sab_scatter(i_nuclide, micro.index_sab, p);
|
||||
|
||||
p.event_mt_ = ELASTIC;
|
||||
p.event_mt() = ELASTIC;
|
||||
sampled = true;
|
||||
}
|
||||
|
||||
|
|
@ -695,20 +700,20 @@ void scatter(Particle& p, int i_nuclide)
|
|||
// Perform collision physics for inelastic scattering
|
||||
const auto& rx {nuc->reactions_[i]};
|
||||
inelastic_scatter(*nuc, *rx, p);
|
||||
p.event_mt_ = rx->mt_;
|
||||
p.event_mt() = rx->mt_;
|
||||
}
|
||||
|
||||
// Set event component
|
||||
p.event_ = TallyEvent::SCATTER;
|
||||
p.event() = TallyEvent::SCATTER;
|
||||
|
||||
// Sample new outgoing angle for isotropic-in-lab scattering
|
||||
const auto& mat {model::materials[p.material_]};
|
||||
const auto& mat {model::materials[p.material()]};
|
||||
if (!mat->p0_.empty()) {
|
||||
int i_nuc_mat = mat->mat_nuclide_index_[i_nuclide];
|
||||
if (mat->p0_[i_nuc_mat]) {
|
||||
// Sample isotropic-in-lab outgoing direction
|
||||
p.u() = isotropic_direction(p.current_seed());
|
||||
p.mu_ = u_old.dot(p.u());
|
||||
p.mu() = u_old.dot(p.u());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -719,7 +724,7 @@ void elastic_scatter(int i_nuclide, const Reaction& rx, double kT,
|
|||
// get pointer to nuclide
|
||||
const auto& nuc {data::nuclides[i_nuclide]};
|
||||
|
||||
double vel = std::sqrt(p.E_);
|
||||
double vel = std::sqrt(p.E());
|
||||
double awr = nuc->awr_;
|
||||
|
||||
// Neutron velocity in LAB
|
||||
|
|
@ -727,9 +732,9 @@ void elastic_scatter(int i_nuclide, const Reaction& rx, double kT,
|
|||
|
||||
// Sample velocity of target nucleus
|
||||
Direction v_t {};
|
||||
if (!p.neutron_xs_[i_nuclide].use_ptable) {
|
||||
v_t = sample_target_velocity(*nuc, p.E_, p.u(), v_n,
|
||||
p.neutron_xs_[i_nuclide].elastic, kT, p.current_seed());
|
||||
if (!p.neutron_xs(i_nuclide).use_ptable) {
|
||||
v_t = sample_target_velocity(*nuc, p.E(), p.u(), v_n,
|
||||
p.neutron_xs(i_nuclide).elastic, kT, p.current_seed());
|
||||
}
|
||||
|
||||
// Velocity of center-of-mass
|
||||
|
|
@ -747,7 +752,7 @@ void elastic_scatter(int i_nuclide, const Reaction& rx, double kT,
|
|||
auto& d = rx.products_[0].distribution_[0];
|
||||
auto d_ = dynamic_cast<UncorrelatedAngleEnergy*>(d.get());
|
||||
if (!d_->angle().empty()) {
|
||||
mu_cm = d_->angle().sample(p.E_, p.current_seed());
|
||||
mu_cm = d_->angle().sample(p.E(), p.current_seed());
|
||||
} else {
|
||||
mu_cm = uniform_distribution(-1., 1., p.current_seed());
|
||||
}
|
||||
|
|
@ -763,12 +768,12 @@ void elastic_scatter(int i_nuclide, const Reaction& rx, double kT,
|
|||
// Transform back to LAB frame
|
||||
v_n += v_cm;
|
||||
|
||||
p.E_ = v_n.dot(v_n);
|
||||
vel = std::sqrt(p.E_);
|
||||
p.E() = v_n.dot(v_n);
|
||||
vel = std::sqrt(p.E());
|
||||
|
||||
// compute cosine of scattering angle in LAB frame by taking dot product of
|
||||
// neutron's pre- and post-collision angle
|
||||
p.mu_ = p.u().dot(v_n) / vel;
|
||||
p.mu() = p.u().dot(v_n) / vel;
|
||||
|
||||
// Set energy and direction of particle in LAB frame
|
||||
p.u() = v_n / vel;
|
||||
|
|
@ -776,22 +781,24 @@ void elastic_scatter(int i_nuclide, const Reaction& rx, double kT,
|
|||
// Because of floating-point roundoff, it may be possible for mu_lab to be
|
||||
// outside of the range [-1,1). In these cases, we just set mu_lab to exactly
|
||||
// -1 or 1
|
||||
if (std::abs(p.mu_) > 1.0) p.mu_ = std::copysign(1.0, p.mu_);
|
||||
if (std::abs(p.mu()) > 1.0)
|
||||
p.mu() = std::copysign(1.0, p.mu());
|
||||
}
|
||||
|
||||
void sab_scatter(int i_nuclide, int i_sab, Particle& p)
|
||||
{
|
||||
// Determine temperature index
|
||||
const auto& micro {p.neutron_xs_[i_nuclide]};
|
||||
const auto& micro {p.neutron_xs(i_nuclide)};
|
||||
int i_temp = micro.index_temp_sab;
|
||||
|
||||
// Sample energy and angle
|
||||
double E_out;
|
||||
data::thermal_scatt[i_sab]->data_[i_temp].sample(micro, p.E_, &E_out, &p.mu_, p.current_seed());
|
||||
data::thermal_scatt[i_sab]->data_[i_temp].sample(
|
||||
micro, p.E(), &E_out, &p.mu(), p.current_seed());
|
||||
|
||||
// Set energy to outgoing, change direction of particle
|
||||
p.E_ = E_out;
|
||||
p.u() = rotate_angle(p.u(), p.mu_, nullptr, p.current_seed());
|
||||
p.E() = E_out;
|
||||
p.u() = rotate_angle(p.u(), p.mu(), nullptr, p.current_seed());
|
||||
}
|
||||
|
||||
Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u,
|
||||
|
|
@ -996,7 +1003,8 @@ sample_cxs_target_velocity(double awr, double E, Direction u, double kT, uint64_
|
|||
return vt * rotate_angle(u, mu, nullptr, seed);
|
||||
}
|
||||
|
||||
void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in, Particle::Bank* site, uint64_t* seed)
|
||||
void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in,
|
||||
SourceSite* site, uint64_t* seed)
|
||||
{
|
||||
// Determine total nu, delayed nu, and delayed neutron fraction
|
||||
const auto& nuc {data::nuclides[i_nuclide]};
|
||||
|
|
@ -1044,7 +1052,7 @@ void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in, Part
|
|||
rx.products_[site->delayed_group].sample(E_in, site->E, mu, seed);
|
||||
|
||||
// resample if energy is greater than maximum neutron energy
|
||||
constexpr int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
constexpr int neutron = static_cast<int>(ParticleType::neutron);
|
||||
if (site->E < data::energy_max[neutron]) break;
|
||||
|
||||
// check for large number of resamples
|
||||
|
|
@ -1065,7 +1073,7 @@ void sample_fission_neutron(int i_nuclide, const Reaction& rx, double E_in, Part
|
|||
void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p)
|
||||
{
|
||||
// copy energy of neutron
|
||||
double E_in = p.E_;
|
||||
double E_in = p.E();
|
||||
|
||||
// sample outgoing energy and scattering cosine
|
||||
double E;
|
||||
|
|
@ -1092,8 +1100,8 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p)
|
|||
if (std::abs(mu) > 1.0) mu = std::copysign(1.0, mu);
|
||||
|
||||
// Set outgoing energy and scattering angle
|
||||
p.E_ = E;
|
||||
p.mu_ = mu;
|
||||
p.E() = E;
|
||||
p.mu() = mu;
|
||||
|
||||
// change direction of particle
|
||||
p.u() = rotate_angle(p.u(), mu, nullptr, p.current_seed());
|
||||
|
|
@ -1103,19 +1111,19 @@ void inelastic_scatter(const Nuclide& nuc, const Reaction& rx, Particle& p)
|
|||
if (std::floor(yield) == yield) {
|
||||
// If yield is integral, create exactly that many secondary particles
|
||||
for (int i = 0; i < static_cast<int>(std::round(yield)) - 1; ++i) {
|
||||
p.create_secondary(p.wgt_, p.u(), p.E_, Particle::Type::neutron);
|
||||
p.create_secondary(p.wgt(), p.u(), p.E(), ParticleType::neutron);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, change weight of particle based on yield
|
||||
p.wgt_ *= yield;
|
||||
p.wgt() *= yield;
|
||||
}
|
||||
}
|
||||
|
||||
void sample_secondary_photons(Particle& p, int i_nuclide)
|
||||
{
|
||||
// Sample the number of photons produced
|
||||
double y_t = p.neutron_xs_[i_nuclide].photon_prod /
|
||||
p.neutron_xs_[i_nuclide].total;
|
||||
double y_t =
|
||||
p.neutron_xs(i_nuclide).photon_prod / p.neutron_xs(i_nuclide).total;
|
||||
int y = static_cast<int>(y_t);
|
||||
if (prn(p.current_seed()) <= y_t - y) ++y;
|
||||
|
||||
|
|
@ -1130,7 +1138,7 @@ void sample_secondary_photons(Particle& p, int i_nuclide)
|
|||
auto& rx = data::nuclides[i_nuclide]->reactions_[i_rx];
|
||||
double E;
|
||||
double mu;
|
||||
rx->products_[i_product].sample(p.E_, E, mu, p.current_seed());
|
||||
rx->products_[i_product].sample(p.E(), E, mu, p.current_seed());
|
||||
|
||||
// Sample the new direction
|
||||
Direction u = rotate_angle(p.u(), mu, nullptr, p.current_seed());
|
||||
|
|
@ -1142,14 +1150,13 @@ void sample_secondary_photons(Particle& p, int i_nuclide)
|
|||
// calculations", Proc. PHYSOR, Cambridge, UK, Mar 29-Apr 2, 2020.
|
||||
double wgt;
|
||||
if (settings::run_mode == RunMode::EIGENVALUE && !is_fission(rx->mt_)) {
|
||||
wgt = simulation::keff * p.wgt_;
|
||||
wgt = simulation::keff * p.wgt();
|
||||
} else {
|
||||
wgt = p.wgt_;
|
||||
wgt = p.wgt();
|
||||
}
|
||||
|
||||
// Create the secondary photon
|
||||
p.create_secondary(wgt, u, E, Particle::Type::photon);
|
||||
|
||||
p.create_secondary(wgt, u, E, ParticleType::photon);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ namespace openmc {
|
|||
|
||||
void russian_roulette(Particle& p)
|
||||
{
|
||||
if (p.wgt_ < settings::weight_cutoff) {
|
||||
if (prn(p.current_seed()) < p.wgt_ / settings::weight_survive) {
|
||||
p.wgt_ = settings::weight_survive;
|
||||
p.wgt_last_ = p.wgt_;
|
||||
if (p.wgt() < settings::weight_cutoff) {
|
||||
if (prn(p.current_seed()) < p.wgt() / settings::weight_survive) {
|
||||
p.wgt() = settings::weight_survive;
|
||||
p.wgt_last() = p.wgt();
|
||||
} else {
|
||||
p.wgt_ = 0.;
|
||||
p.wgt_last_ = 0.;
|
||||
p.alive_ = false;
|
||||
p.wgt() = 0.;
|
||||
p.wgt_last() = 0.;
|
||||
p.alive() = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "openmc/math_functions.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/mgxs_interface.h"
|
||||
#include "openmc/particle.h"
|
||||
#include "openmc/physics_common.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/settings.h"
|
||||
|
|
@ -25,14 +26,14 @@ void
|
|||
collision_mg(Particle& p)
|
||||
{
|
||||
// Add to the collision counter for the particle
|
||||
p.n_collision_++;
|
||||
p.n_collision()++;
|
||||
|
||||
// Sample the reaction type
|
||||
sample_reaction(p);
|
||||
|
||||
// Display information about collision
|
||||
if ((settings::verbosity >= 10) || p.trace_) {
|
||||
write_message(fmt::format(" Energy Group = {}", p.g_), 1);
|
||||
if ((settings::verbosity >= 10) || p.trace()) {
|
||||
write_message(fmt::format(" Energy Group = {}", p.g()), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ sample_reaction(Particle& p)
|
|||
// change when sampling fission sites. The following block handles all
|
||||
// absorption (including fission)
|
||||
|
||||
if (model::materials[p.material_]->fissionable_) {
|
||||
if (model::materials[p.material()]->fissionable_) {
|
||||
if (settings::run_mode == RunMode::EIGENVALUE ||
|
||||
(settings::run_mode == RunMode::FIXED_SOURCE &&
|
||||
settings::create_fission_neutrons)) {
|
||||
|
|
@ -54,12 +55,13 @@ sample_reaction(Particle& p)
|
|||
|
||||
// If survival biasing is being used, the following subroutine adjusts the
|
||||
// weight of the particle. Otherwise, it checks to see if absorption occurs.
|
||||
if (p.macro_xs_.absorption > 0.) {
|
||||
if (p.macro_xs().absorption > 0.) {
|
||||
absorption(p);
|
||||
} else {
|
||||
p.wgt_absorb_ = 0.;
|
||||
p.wgt_absorb() = 0.;
|
||||
}
|
||||
if (!p.alive_) return;
|
||||
if (!p.alive())
|
||||
return;
|
||||
|
||||
// Sample a scattering event to determine the energy of the exiting neutron
|
||||
scatter(p);
|
||||
|
|
@ -67,24 +69,25 @@ sample_reaction(Particle& p)
|
|||
// Play Russian roulette if survival biasing is turned on
|
||||
if (settings::survival_biasing) {
|
||||
russian_roulette(p);
|
||||
if (!p.alive_) return;
|
||||
if (!p.alive())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
scatter(Particle& p)
|
||||
{
|
||||
data::mg.macro_xs_[p.material_].sample_scatter(p.g_last_, p.g_, p.mu_,
|
||||
p.wgt_, p.current_seed());
|
||||
data::mg.macro_xs_[p.material()].sample_scatter(
|
||||
p.g_last(), p.g(), p.mu(), p.wgt(), p.current_seed());
|
||||
|
||||
// Rotate the angle
|
||||
p.u() = rotate_angle(p.u(), p.mu_, nullptr, p.current_seed());
|
||||
p.u() = rotate_angle(p.u(), p.mu(), nullptr, p.current_seed());
|
||||
|
||||
// Update energy value for downstream compatability (in tallying)
|
||||
p.E_ = data::mg.energy_bin_avg_[p.g_];
|
||||
p.E() = data::mg.energy_bin_avg_[p.g()];
|
||||
|
||||
// Set event component
|
||||
p.event_ = TallyEvent::SCATTER;
|
||||
p.event() = TallyEvent::SCATTER;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -95,8 +98,8 @@ create_fission_sites(Particle& p)
|
|||
double weight = settings::ufs_on ? ufs_get_weight(p) : 1.0;
|
||||
|
||||
// Determine the expected number of neutrons produced
|
||||
double nu_t = p.wgt_ / simulation::keff * weight *
|
||||
p.macro_xs_.nu_fission / p.macro_xs_.total;
|
||||
double nu_t = p.wgt() / simulation::keff * weight * p.macro_xs().nu_fission /
|
||||
p.macro_xs().total;
|
||||
|
||||
// Sample the number of neutrons produced
|
||||
int nu = static_cast<int>(nu_t);
|
||||
|
|
@ -113,9 +116,9 @@ create_fission_sites(Particle& p)
|
|||
double nu_d[MAX_DELAYED_GROUPS] = {0.};
|
||||
|
||||
// Clear out particle's nu fission bank
|
||||
p.nu_bank_.clear();
|
||||
p.nu_bank().clear();
|
||||
|
||||
p.fission_ = true;
|
||||
p.fission() = true;
|
||||
int skipped = 0;
|
||||
|
||||
// Determine whether to place fission sites into the shared fission bank
|
||||
|
|
@ -124,12 +127,12 @@ create_fission_sites(Particle& p)
|
|||
|
||||
for (int i = 0; i < nu; ++i) {
|
||||
// Initialize fission site object with particle data
|
||||
Particle::Bank site;
|
||||
SourceSite site;
|
||||
site.r = p.r();
|
||||
site.particle = Particle::Type::neutron;
|
||||
site.particle = ParticleType::neutron;
|
||||
site.wgt = 1. / weight;
|
||||
site.parent_id = p.id_;
|
||||
site.progeny_id = p.n_progeny_++;
|
||||
site.parent_id = p.id();
|
||||
site.progeny_id = p.n_progeny()++;
|
||||
|
||||
// Sample the cosine of the angle, assuming fission neutrons are emitted
|
||||
// isotropically
|
||||
|
|
@ -144,8 +147,8 @@ create_fission_sites(Particle& p)
|
|||
// Sample secondary energy distribution for the fission reaction
|
||||
int dg;
|
||||
int gout;
|
||||
data::mg.macro_xs_[p.material_].sample_fission_energy(p.g_, dg, gout,
|
||||
p.current_seed());
|
||||
data::mg.macro_xs_[p.material()].sample_fission_energy(
|
||||
p.g(), dg, gout, p.current_seed());
|
||||
|
||||
// Store the energy and delayed groups on the fission bank
|
||||
site.E = gout;
|
||||
|
|
@ -164,20 +167,20 @@ create_fission_sites(Particle& p)
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
p.secondary_bank_.push_back(site);
|
||||
p.secondary_bank().push_back(site);
|
||||
}
|
||||
|
||||
// Set the delayed group on the particle as well
|
||||
p.delayed_group_ = dg + 1;
|
||||
p.delayed_group() = dg + 1;
|
||||
|
||||
// Increment the number of neutrons born delayed
|
||||
if (p.delayed_group_ > 0) {
|
||||
if (p.delayed_group() > 0) {
|
||||
nu_d[dg]++;
|
||||
}
|
||||
|
||||
// Write fission particles to nuBank
|
||||
p.nu_bank_.emplace_back();
|
||||
Particle::NuBank* nu_bank_entry = &p.nu_bank_.back();
|
||||
p.nu_bank().emplace_back();
|
||||
NuBank* nu_bank_entry = &p.nu_bank().back();
|
||||
nu_bank_entry->wgt = site.wgt;
|
||||
nu_bank_entry->E = site.E;
|
||||
nu_bank_entry->delayed_group = site.delayed_group;
|
||||
|
|
@ -186,7 +189,7 @@ create_fission_sites(Particle& p)
|
|||
// If shared fission bank was full, and no fissions could be added,
|
||||
// set the particle fission flag to false.
|
||||
if (nu == skipped) {
|
||||
p.fission_ = false;
|
||||
p.fission() = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -195,10 +198,10 @@ create_fission_sites(Particle& p)
|
|||
nu -= skipped;
|
||||
|
||||
// Store the total weight banked for analog fission tallies
|
||||
p.n_bank_ = nu;
|
||||
p.wgt_bank_ = nu / weight;
|
||||
p.n_bank() = nu;
|
||||
p.wgt_bank() = nu / weight;
|
||||
for (size_t d = 0; d < MAX_DELAYED_GROUPS; d++) {
|
||||
p.n_delayed_bank_[d] = nu_d[d];
|
||||
p.n_delayed_bank(d) = nu_d[d];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -207,23 +210,22 @@ absorption(Particle& p)
|
|||
{
|
||||
if (settings::survival_biasing) {
|
||||
// Determine weight absorbed in survival biasing
|
||||
p.wgt_absorb_ = p.wgt_ * p.macro_xs_.absorption / p.macro_xs_.total;
|
||||
p.wgt_absorb() = p.wgt() * p.macro_xs().absorption / p.macro_xs().total;
|
||||
|
||||
// Adjust weight of particle by the probability of absorption
|
||||
p.wgt_ -= p.wgt_absorb_;
|
||||
p.wgt_last_ = p.wgt_;
|
||||
p.wgt() -= p.wgt_absorb();
|
||||
p.wgt_last() = p.wgt();
|
||||
|
||||
// Score implicit absorpion estimate of keff
|
||||
p.keff_tally_absorption_ += p.wgt_absorb_ * p.macro_xs_.nu_fission /
|
||||
p.macro_xs_.absorption;
|
||||
p.keff_tally_absorption() +=
|
||||
p.wgt_absorb() * p.macro_xs().nu_fission / p.macro_xs().absorption;
|
||||
} else {
|
||||
if (p.macro_xs_.absorption > prn(p.current_seed()) * p.macro_xs_.total) {
|
||||
p.keff_tally_absorption_ += p.wgt_ * p.macro_xs_.nu_fission /
|
||||
p.macro_xs_.absorption;
|
||||
p.alive_ = false;
|
||||
p.event_ = TallyEvent::ABSORB;
|
||||
if (p.macro_xs().absorption > prn(p.current_seed()) * p.macro_xs().total) {
|
||||
p.keff_tally_absorption() +=
|
||||
p.wgt() * p.macro_xs().nu_fission / p.macro_xs().absorption;
|
||||
p.alive() = false;
|
||||
p.event() = TallyEvent::ABSORB;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
40
src/plot.cpp
40
src/plot.cpp
|
|
@ -42,19 +42,19 @@ IdData::IdData(size_t h_res, size_t v_res)
|
|||
void
|
||||
IdData::set_value(size_t y, size_t x, const Particle& p, int level) {
|
||||
// set cell data
|
||||
if (p.n_coord_ <= level) {
|
||||
if (p.n_coord() <= level) {
|
||||
data_(y, x, 0) = NOT_FOUND;
|
||||
} else {
|
||||
data_(y, x, 0) = model::cells.at(p.coord_.at(level).cell)->id_;
|
||||
data_(y, x, 0) = model::cells.at(p.coord(level).cell)->id_;
|
||||
}
|
||||
|
||||
// set material data
|
||||
Cell* c = model::cells.at(p.coord_.at(p.n_coord_ - 1).cell).get();
|
||||
if (p.material_ == MATERIAL_VOID) {
|
||||
Cell* c = model::cells.at(p.coord(p.n_coord() - 1).cell).get();
|
||||
if (p.material() == MATERIAL_VOID) {
|
||||
data_(y, x, 1) = MATERIAL_VOID;
|
||||
return;
|
||||
} else if (c->type_ == Fill::MATERIAL) {
|
||||
Material* m = model::materials.at(p.material_).get();
|
||||
Material* m = model::materials.at(p.material()).get();
|
||||
data_(y, x, 1) = m->id_;
|
||||
}
|
||||
}
|
||||
|
|
@ -69,10 +69,10 @@ PropertyData::PropertyData(size_t h_res, size_t v_res)
|
|||
|
||||
void
|
||||
PropertyData::set_value(size_t y, size_t x, const Particle& p, int level) {
|
||||
Cell* c = model::cells.at(p.coord_.at(p.n_coord_ - 1).cell).get();
|
||||
data_(y,x,0) = (p.sqrtkT_ * p.sqrtkT_) / K_BOLTZMANN;
|
||||
if (c->type_ != Fill::UNIVERSE && p.material_ != MATERIAL_VOID) {
|
||||
Material* m = model::materials.at(p.material_).get();
|
||||
Cell* c = model::cells.at(p.coord(p.n_coord() - 1).cell).get();
|
||||
data_(y, x, 0) = (p.sqrtkT() * p.sqrtkT()) / K_BOLTZMANN;
|
||||
if (c->type_ != Fill::UNIVERSE && p.material() != MATERIAL_VOID) {
|
||||
Material* m = model::materials.at(p.material()).get();
|
||||
data_(y,x,1) = m->density_gpcc_;
|
||||
}
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ void PropertyData::set_overlap(size_t y, size_t x) {
|
|||
namespace model {
|
||||
|
||||
std::unordered_map<int, int> plot_map;
|
||||
std::vector<Plot> plots;
|
||||
vector<Plot> plots;
|
||||
uint64_t plotter_seed = 1;
|
||||
|
||||
} // namespace model
|
||||
|
|
@ -244,7 +244,7 @@ Plot::set_output_path(pugi::xml_node plot_node)
|
|||
path_plot_ = filename;
|
||||
|
||||
// Copy plot pixel size
|
||||
std::vector<int> pxls = get_node_array<int>(plot_node, "pixels");
|
||||
vector<int> pxls = get_node_array<int>(plot_node, "pixels");
|
||||
if (PlotType::slice == type_) {
|
||||
if (pxls.size() == 2) {
|
||||
pixels_[0] = pxls[0];
|
||||
|
|
@ -268,7 +268,7 @@ Plot::set_bg_color(pugi::xml_node plot_node)
|
|||
{
|
||||
// Copy plot background color
|
||||
if (check_for_node(plot_node, "background")) {
|
||||
std::vector<int> bg_rgb = get_node_array<int>(plot_node, "background");
|
||||
vector<int> bg_rgb = get_node_array<int>(plot_node, "background");
|
||||
if (PlotType::voxel == type_) {
|
||||
if (mpi::master) {
|
||||
warning(fmt::format("Background color ignored in voxel plot {}", id_));
|
||||
|
|
@ -320,7 +320,7 @@ void
|
|||
Plot::set_width(pugi::xml_node plot_node)
|
||||
{
|
||||
// Copy plotting width
|
||||
std::vector<double> pl_width = get_node_array<double>(plot_node, "width");
|
||||
vector<double> pl_width = get_node_array<double>(plot_node, "width");
|
||||
if (PlotType::slice == type_) {
|
||||
if (pl_width.size() == 2) {
|
||||
width_.x = pl_width[0];
|
||||
|
|
@ -391,7 +391,7 @@ Plot::set_user_colors(pugi::xml_node plot_node)
|
|||
|
||||
for (auto cn : plot_node.children("color")) {
|
||||
// Make sure 3 values are specified for RGB
|
||||
std::vector<int> user_rgb = get_node_array<int>(cn, "rgb");
|
||||
vector<int> user_rgb = get_node_array<int>(cn, "rgb");
|
||||
if (user_rgb.size() != 3) {
|
||||
fatal_error(fmt::format("Bad RGB in plot {}", id_));
|
||||
}
|
||||
|
|
@ -461,7 +461,7 @@ Plot::set_meshlines(pugi::xml_node plot_node)
|
|||
// Check for color
|
||||
if (check_for_node(meshlines_node, "color")) {
|
||||
// Check and make sure 3 values are specified for RGB
|
||||
std::vector<int> ml_rgb = get_node_array<int>(meshlines_node, "color");
|
||||
vector<int> ml_rgb = get_node_array<int>(meshlines_node, "color");
|
||||
if (ml_rgb.size() != 3) {
|
||||
fatal_error(fmt::format("Bad RGB for meshlines color in plot {}", id_));
|
||||
}
|
||||
|
|
@ -544,7 +544,7 @@ Plot::set_mask(pugi::xml_node plot_node)
|
|||
pugi::xml_node mask_node = mask_nodes[0].node();
|
||||
|
||||
// Determine how many components there are and allocate
|
||||
std::vector<int> iarray = get_node_array<int>(mask_node, "components");
|
||||
vector<int> iarray = get_node_array<int>(mask_node, "components");
|
||||
if (iarray.size() == 0) {
|
||||
fatal_error(fmt::format("Missing <components> in mask of plot {}", id_));
|
||||
}
|
||||
|
|
@ -575,7 +575,7 @@ Plot::set_mask(pugi::xml_node plot_node)
|
|||
for (int j = 0; j < colors_.size(); j++) {
|
||||
if (std::find(iarray.begin(), iarray.end(), j) == iarray.end()) {
|
||||
if (check_for_node(mask_node, "background")) {
|
||||
std::vector<int> bg_rgb = get_node_array<int>(mask_node, "background");
|
||||
vector<int> bg_rgb = get_node_array<int>(mask_node, "background");
|
||||
colors_[j] = bg_rgb;
|
||||
} else {
|
||||
colors_[j] = WHITE;
|
||||
|
|
@ -599,7 +599,7 @@ void Plot::set_overlap_color(pugi::xml_node plot_node) {
|
|||
warning(fmt::format(
|
||||
"Overlap color specified in plot {} but overlaps won't be shown.", id_));
|
||||
}
|
||||
std::vector<int> olap_clr = get_node_array<int>(plot_node, "overlap_color");
|
||||
vector<int> olap_clr = get_node_array<int>(plot_node, "overlap_color");
|
||||
if (olap_clr.size() == 3) {
|
||||
overlap_color_ = olap_clr;
|
||||
} else {
|
||||
|
|
@ -778,7 +778,7 @@ void draw_mesh_lines(Plot const& pl, ImageData& data)
|
|||
void create_voxel(Plot const& pl)
|
||||
{
|
||||
// compute voxel widths in each direction
|
||||
std::array<double, 3> vox;
|
||||
array<double, 3> vox;
|
||||
vox[0] = pl.width_[0]/(double)pl.pixels_[0];
|
||||
vox[1] = pl.width_[1]/(double)pl.pixels_[1];
|
||||
vox[2] = pl.width_[2]/(double)pl.pixels_[2];
|
||||
|
|
@ -803,7 +803,7 @@ void create_voxel(Plot const& pl)
|
|||
|
||||
// Write current date and time
|
||||
write_attribute(file_id, "date_and_time", time_stamp().c_str());
|
||||
std::array<int, 3> pixels;
|
||||
array<int, 3> pixels;
|
||||
std::copy(pl.pixels_.begin(), pl.pixels_.end(), pixels.begin());
|
||||
write_attribute(file_id, "num_voxels", pixels);
|
||||
write_attribute(file_id, "voxel_width", vox);
|
||||
|
|
|
|||
|
|
@ -84,8 +84,7 @@ Position::operator-() const
|
|||
return {-x, -y, -z};
|
||||
}
|
||||
|
||||
Position
|
||||
Position::rotate(const std::vector<double>& rotation) const
|
||||
Position Position::rotate(const vector<double>& rotation) const
|
||||
{
|
||||
return {
|
||||
x*rotation[0] + y*rotation[1] + z*rotation[2],
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace openmc {
|
|||
// Reaction implementation
|
||||
//==============================================================================
|
||||
|
||||
Reaction::Reaction(hid_t group, const std::vector<int>& temperatures)
|
||||
Reaction::Reaction(hid_t group, const vector<int>& temperatures)
|
||||
{
|
||||
read_attribute(group, "Q_value", q_value_);
|
||||
read_attribute(group, "mt", mt_);
|
||||
|
|
@ -65,9 +65,9 @@ Reaction::Reaction(hid_t group, const std::vector<int>& temperatures)
|
|||
}
|
||||
}
|
||||
|
||||
double
|
||||
Reaction::collapse_rate(gsl::index i_temp, gsl::span<const double> energy,
|
||||
gsl::span<const double> flux, const std::vector<double>& grid) const
|
||||
double Reaction::collapse_rate(gsl::index i_temp,
|
||||
gsl::span<const double> energy, gsl::span<const double> flux,
|
||||
const vector<double>& grid) const
|
||||
{
|
||||
// Find index corresponding to first energy
|
||||
const auto& xs = xs_[i_temp].value;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "openmc/reaction_product.h"
|
||||
|
||||
#include <memory> // for unique_ptr
|
||||
#include <string> // for string
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
|
@ -8,6 +7,7 @@
|
|||
#include "openmc/endf.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/memory.h"
|
||||
#include "openmc/particle.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/secondary_correlated.h"
|
||||
|
|
@ -42,7 +42,7 @@ ReactionProduct::ReactionProduct(hid_t group)
|
|||
if (emission_mode_ == EmissionMode::delayed) {
|
||||
if (attribute_exists(group, "decay_rate")) {
|
||||
read_attribute(group, "decay_rate", decay_rate_);
|
||||
} else if (particle_ == Particle::Type::neutron) {
|
||||
} else if (particle_ == ParticleType::neutron) {
|
||||
warning(fmt::format("Decay rate doesn't exist for delayed neutron "
|
||||
"emission ({}).", object_name(group)));
|
||||
}
|
||||
|
|
@ -69,13 +69,13 @@ ReactionProduct::ReactionProduct(hid_t group)
|
|||
// Determine distribution type and read data
|
||||
read_attribute(dgroup, "type", temp);
|
||||
if (temp == "uncorrelated") {
|
||||
distribution_.push_back(std::make_unique<UncorrelatedAngleEnergy>(dgroup));
|
||||
distribution_.push_back(make_unique<UncorrelatedAngleEnergy>(dgroup));
|
||||
} else if (temp == "correlated") {
|
||||
distribution_.push_back(std::make_unique<CorrelatedAngleEnergy>(dgroup));
|
||||
distribution_.push_back(make_unique<CorrelatedAngleEnergy>(dgroup));
|
||||
} else if (temp == "nbody") {
|
||||
distribution_.push_back(std::make_unique<NBodyPhaseSpace>(dgroup));
|
||||
distribution_.push_back(make_unique<NBodyPhaseSpace>(dgroup));
|
||||
} else if (temp == "kalbach-mann") {
|
||||
distribution_.push_back(std::make_unique<KalbachMann>(dgroup));
|
||||
distribution_.push_back(make_unique<KalbachMann>(dgroup));
|
||||
}
|
||||
|
||||
close_group(dgroup);
|
||||
|
|
|
|||
|
|
@ -70,12 +70,10 @@ 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 std::vector<ScattData*>& those_scatts,
|
||||
const std::vector<double>& scalars, xt::xtensor<int, 1>& in_gmin,
|
||||
xt::xtensor<int, 1>& in_gmax, double_2dvec& sparse_mult,
|
||||
double_3dvec& sparse_scatter)
|
||||
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,
|
||||
double_2dvec& sparse_mult, double_3dvec& sparse_scatter)
|
||||
{
|
||||
size_t groups = those_scatts[0] -> energy.size();
|
||||
|
||||
|
|
@ -378,9 +376,8 @@ ScattDataLegendre::sample(int gin, int& gout, double& mu, double& wgt,
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
ScattDataLegendre::combine(const std::vector<ScattData*>& those_scatts,
|
||||
const std::vector<double>& scalars)
|
||||
void ScattDataLegendre::combine(
|
||||
const vector<ScattData*>& those_scatts, const vector<double>& scalars)
|
||||
{
|
||||
// Find the max order in the data set and make sure we can combine the sets
|
||||
size_t max_order = 0;
|
||||
|
|
@ -595,9 +592,8 @@ ScattDataHistogram::get_matrix(size_t max_order)
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
ScattDataHistogram::combine(const std::vector<ScattData*>& those_scatts,
|
||||
const std::vector<double>& scalars)
|
||||
void ScattDataHistogram::combine(
|
||||
const vector<ScattData*>& those_scatts, const vector<double>& scalars)
|
||||
{
|
||||
// Find the max order in the data set and make sure we can combine the sets
|
||||
size_t max_order = those_scatts[0]->get_order();
|
||||
|
|
@ -814,9 +810,8 @@ ScattDataTabular::get_matrix(size_t max_order)
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
ScattDataTabular::combine(const std::vector<ScattData*>& those_scatts,
|
||||
const std::vector<double>& scalars)
|
||||
void ScattDataTabular::combine(
|
||||
const vector<ScattData*>& those_scatts, const vector<double>& scalars)
|
||||
{
|
||||
// Find the max order in the data set and make sure we can combine the sets
|
||||
size_t max_order = those_scatts[0]->get_order();
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
|
||||
// Get outgoing energy distribution data
|
||||
dset = open_dataset(group, "energy_out");
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
std::vector<int> n_discrete;
|
||||
vector<int> offsets;
|
||||
vector<int> interp;
|
||||
vector<int> n_discrete;
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
|
@ -136,9 +136,9 @@ CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
|||
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));
|
||||
|
||||
std::vector<double> x {xs.begin(), xs.end()};
|
||||
std::vector<double> p {ps.begin(), ps.end()};
|
||||
std::vector<double> c {cs.begin(), cs.end()};
|
||||
vector<double> x {xs.begin(), xs.end()};
|
||||
vector<double> p {ps.begin(), ps.end()};
|
||||
vector<double> c {cs.begin(), cs.end()};
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include <cmath> // for log, sqrt, sinh
|
||||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
#include <vector>
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
|
@ -13,6 +12,7 @@
|
|||
#include "openmc/random_dist.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/search.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -44,9 +44,9 @@ KalbachMann::KalbachMann(hid_t group)
|
|||
|
||||
// Get outgoing energy distribution data
|
||||
dset = open_dataset(group, "distribution");
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
std::vector<int> n_discrete;
|
||||
vector<int> offsets;
|
||||
vector<int> interp;
|
||||
vector<int> n_discrete;
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
namespace openmc {
|
||||
|
||||
// Helper function to get index on incident energy grid
|
||||
void
|
||||
get_energy_index(const std::vector<double>& energies, double E, int& i, double& f)
|
||||
void get_energy_index(
|
||||
const vector<double>& energies, double E, int& i, double& f)
|
||||
{
|
||||
// Get index and interpolation factor for elastic grid
|
||||
i = 0;
|
||||
|
|
@ -81,9 +81,9 @@ IncoherentElasticAE::sample(double E_in, double& E_out, double& mu,
|
|||
// IncoherentElasticAEDiscrete implementation
|
||||
//==============================================================================
|
||||
|
||||
IncoherentElasticAEDiscrete::IncoherentElasticAEDiscrete(hid_t group,
|
||||
const std::vector<double>& energy)
|
||||
: energy_{energy}
|
||||
IncoherentElasticAEDiscrete::IncoherentElasticAEDiscrete(
|
||||
hid_t group, const vector<double>& energy)
|
||||
: energy_ {energy}
|
||||
{
|
||||
read_dataset(group, "mu_out", mu_out_);
|
||||
}
|
||||
|
|
@ -135,9 +135,9 @@ IncoherentElasticAEDiscrete::sample(double E_in, double& E_out, double& mu,
|
|||
// IncoherentInelasticAEDiscrete implementation
|
||||
//==============================================================================
|
||||
|
||||
IncoherentInelasticAEDiscrete::IncoherentInelasticAEDiscrete(hid_t group,
|
||||
const std::vector<double>& energy)
|
||||
: energy_{energy}
|
||||
IncoherentInelasticAEDiscrete::IncoherentInelasticAEDiscrete(
|
||||
hid_t group, const vector<double>& energy)
|
||||
: energy_ {energy}
|
||||
{
|
||||
read_dataset(group, "energy_out", energy_out_);
|
||||
read_dataset(group, "mu_out", mu_out_);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ UncorrelatedAngleEnergy::UncorrelatedAngleEnergy(hid_t group)
|
|||
|
||||
std::string type;
|
||||
read_attribute(energy_group, "type", type);
|
||||
using UPtrEDist = std::unique_ptr<EnergyDistribution>;
|
||||
using UPtrEDist = unique_ptr<EnergyDistribution>;
|
||||
if (type == "discrete_photon") {
|
||||
energy_ = UPtrEDist{new DiscretePhoton{energy_group}};
|
||||
} else if (type == "level") {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ int64_t n_particles {-1};
|
|||
int64_t max_particles_in_flight {100000};
|
||||
|
||||
ElectronTreatment electron_treatment {ElectronTreatment::TTB};
|
||||
std::array<double, 4> energy_cutoff {0.0, 1000.0, 0.0, 0.0};
|
||||
array<double, 4> energy_cutoff {0.0, 1000.0, 0.0, 0.0};
|
||||
int legendre_to_tabular_points {C_NONE};
|
||||
int max_order {0};
|
||||
int n_log_bins {8000};
|
||||
|
|
@ -96,7 +96,7 @@ int n_max_batches;
|
|||
ResScatMethod res_scat_method {ResScatMethod::rvs};
|
||||
double res_scat_energy_min {0.01};
|
||||
double res_scat_energy_max {1000.0};
|
||||
std::vector<std::string> res_scat_nuclides;
|
||||
vector<std::string> res_scat_nuclides;
|
||||
RunMode run_mode {RunMode::UNSET};
|
||||
std::unordered_set<int> sourcepoint_batch;
|
||||
std::unordered_set<int> statepoint_batch;
|
||||
|
|
@ -105,11 +105,11 @@ int64_t max_surface_particles;
|
|||
TemperatureMethod temperature_method {TemperatureMethod::NEAREST};
|
||||
double temperature_tolerance {10.0};
|
||||
double temperature_default {293.6};
|
||||
std::array<double, 2> temperature_range {0.0, 0.0};
|
||||
array<double, 2> temperature_range {0.0, 0.0};
|
||||
int trace_batch;
|
||||
int trace_gen;
|
||||
int64_t trace_particle;
|
||||
std::vector<std::array<int, 3>> track_identifiers;
|
||||
vector<array<int, 3>> track_identifiers;
|
||||
int trigger_batch_interval {1};
|
||||
int verbosity {7};
|
||||
double weight_cutoff {0.25};
|
||||
|
|
@ -425,7 +425,7 @@ void read_settings_xml()
|
|||
for (pugi::xml_node node : root.children("source")) {
|
||||
if (check_for_node(node, "file")) {
|
||||
auto path = get_node_value(node, "file", false, true);
|
||||
model::external_sources.push_back(std::make_unique<FileSource>(path));
|
||||
model::external_sources.push_back(make_unique<FileSource>(path));
|
||||
} else if (check_for_node(node, "library")) {
|
||||
// Get shared library path and parameters
|
||||
auto path = get_node_value(node, "library", false, true);
|
||||
|
|
@ -435,9 +435,10 @@ void read_settings_xml()
|
|||
}
|
||||
|
||||
// Create custom source
|
||||
model::external_sources.push_back(std::make_unique<CustomSourceWrapper>(path, parameters));
|
||||
model::external_sources.push_back(
|
||||
make_unique<CustomSourceWrapper>(path, parameters));
|
||||
} else {
|
||||
model::external_sources.push_back(std::make_unique<IndependentSource>(node));
|
||||
model::external_sources.push_back(make_unique<IndependentSource>(node));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,16 +453,14 @@ void read_settings_xml()
|
|||
if (check_for_node(node_ssr, "path")) {
|
||||
path = get_node_value(node_ssr, "path", false, true);
|
||||
}
|
||||
model::external_sources.push_back(std::make_unique<FileSource>(path));
|
||||
model::external_sources.push_back(make_unique<FileSource>(path));
|
||||
}
|
||||
|
||||
// If no source specified, default to isotropic point source at origin with Watt spectrum
|
||||
if (model::external_sources.empty()) {
|
||||
model::external_sources.push_back(std::make_unique<IndependentSource>(
|
||||
UPtrSpace{new SpatialPoint({0.0, 0.0, 0.0})},
|
||||
UPtrAngle{new Isotropic()},
|
||||
UPtrDist{new Watt(0.988e6, 2.249e-6)}
|
||||
));
|
||||
model::external_sources.push_back(make_unique<IndependentSource>(
|
||||
UPtrSpace {new SpatialPoint({0.0, 0.0, 0.0})},
|
||||
UPtrAngle {new Isotropic()}, UPtrDist {new Watt(0.988e6, 2.249e-6)}));
|
||||
}
|
||||
|
||||
// Check if we want to write out source
|
||||
|
|
|
|||
|
|
@ -267,9 +267,8 @@ int64_t work_per_rank;
|
|||
const RegularMesh* entropy_mesh {nullptr};
|
||||
const RegularMesh* ufs_mesh {nullptr};
|
||||
|
||||
std::vector<double> k_generation;
|
||||
std::vector<int64_t> work_index;
|
||||
|
||||
vector<double> k_generation;
|
||||
vector<int64_t> work_index;
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
|
|
@ -464,74 +463,61 @@ void initialize_history(Particle& p, int64_t index_source)
|
|||
auto site = sample_external_source(&seed);
|
||||
p.from_source(&site);
|
||||
}
|
||||
p.current_work_ = index_source;
|
||||
p.current_work() = index_source;
|
||||
|
||||
// set identifier for particle
|
||||
p.id_ = simulation::work_index[mpi::rank] + index_source;
|
||||
p.id() = simulation::work_index[mpi::rank] + index_source;
|
||||
|
||||
// set progeny count to zero
|
||||
p.n_progeny_ = 0;
|
||||
p.n_progeny() = 0;
|
||||
|
||||
// Reset particle event counter
|
||||
p.n_event_ = 0;
|
||||
p.n_event() = 0;
|
||||
|
||||
// set random number seed
|
||||
int64_t particle_seed = (simulation::total_gen + overall_generation() - 1)
|
||||
* settings::n_particles + p.id_;
|
||||
init_particle_seeds(particle_seed, p.seeds_);
|
||||
int64_t particle_seed =
|
||||
(simulation::total_gen + overall_generation() - 1) * settings::n_particles +
|
||||
p.id();
|
||||
init_particle_seeds(particle_seed, p.seeds());
|
||||
|
||||
// set particle trace
|
||||
p.trace_ = false;
|
||||
p.trace() = false;
|
||||
if (simulation::current_batch == settings::trace_batch &&
|
||||
simulation::current_gen == settings::trace_gen &&
|
||||
p.id_ == settings::trace_particle) p.trace_ = true;
|
||||
p.id() == settings::trace_particle)
|
||||
p.trace() = true;
|
||||
|
||||
// Set particle track.
|
||||
p.write_track_ = false;
|
||||
p.write_track() = false;
|
||||
if (settings::write_all_tracks) {
|
||||
p.write_track_ = true;
|
||||
p.write_track() = true;
|
||||
} else if (settings::track_identifiers.size() > 0) {
|
||||
for (const auto& t : settings::track_identifiers) {
|
||||
if (simulation::current_batch == t[0] &&
|
||||
simulation::current_gen == t[1] &&
|
||||
p.id_ == t[2]) {
|
||||
p.write_track_ = true;
|
||||
simulation::current_gen == t[1] && p.id() == t[2]) {
|
||||
p.write_track() = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display message if high verbosity or trace is on
|
||||
if (settings::verbosity >= 9 || p.trace_) {
|
||||
write_message("Simulating Particle {}", p.id_);
|
||||
if (settings::verbosity >= 9 || p.trace()) {
|
||||
write_message("Simulating Particle {}", p.id());
|
||||
}
|
||||
|
||||
// Add paricle's starting weight to count for normalizing tallies later
|
||||
#pragma omp atomic
|
||||
simulation::total_weight += p.wgt_;
|
||||
simulation::total_weight += p.wgt();
|
||||
|
||||
initialize_history_partial(p);
|
||||
}
|
||||
|
||||
void initialize_history_partial(Particle& p)
|
||||
{
|
||||
// Force calculation of cross-sections by setting last energy to zero
|
||||
if (settings::run_CE) {
|
||||
for (auto& micro : p.neutron_xs_) micro.last_E = 0.0;
|
||||
p.invalidate_neutron_xs();
|
||||
}
|
||||
|
||||
// Prepare to write out particle track.
|
||||
if (p.write_track_) add_particle_track(p);
|
||||
|
||||
// Every particle starts with no accumulated flux derivative.
|
||||
if (!model::active_tallies.empty())
|
||||
{
|
||||
p.flux_derivs_.resize(model::tally_derivs.size(), 0.0);
|
||||
std::fill(p.flux_derivs_.begin(), p.flux_derivs_.end(), 0.0);
|
||||
}
|
||||
|
||||
// Allocate space for tally filter matches
|
||||
p.filter_matches_.resize(model::tally_filters.size());
|
||||
if (p.write_track())
|
||||
add_particle_track(p);
|
||||
}
|
||||
|
||||
int overall_generation()
|
||||
|
|
@ -571,7 +557,7 @@ void initialize_data()
|
|||
data::energy_min = {0.0, 0.0};
|
||||
for (const auto& nuc : data::nuclides) {
|
||||
if (nuc->grid_.size() >= 1) {
|
||||
int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
int neutron = static_cast<int>(ParticleType::neutron);
|
||||
data::energy_min[neutron] = std::max(data::energy_min[neutron],
|
||||
nuc->grid_[0].energy.front());
|
||||
data::energy_max[neutron] = std::min(data::energy_max[neutron],
|
||||
|
|
@ -582,7 +568,7 @@ void initialize_data()
|
|||
if (settings::photon_transport) {
|
||||
for (const auto& elem : data::elements) {
|
||||
if (elem->energy_.size() >= 1) {
|
||||
int photon = static_cast<int>(Particle::Type::photon);
|
||||
int photon = static_cast<int>(ParticleType::photon);
|
||||
int n = elem->energy_.size();
|
||||
data::energy_min[photon] = std::max(data::energy_min[photon],
|
||||
std::exp(elem->energy_(1)));
|
||||
|
|
@ -595,7 +581,7 @@ void initialize_data()
|
|||
// Determine if minimum/maximum energy for bremsstrahlung is greater/less
|
||||
// than the current minimum/maximum
|
||||
if (data::ttb_e_grid.size() >= 1) {
|
||||
int photon = static_cast<int>(Particle::Type::photon);
|
||||
int photon = static_cast<int>(ParticleType::photon);
|
||||
int n_e = data::ttb_e_grid.size();
|
||||
data::energy_min[photon] = std::max(data::energy_min[photon],
|
||||
std::exp(data::ttb_e_grid(1)));
|
||||
|
|
@ -611,7 +597,7 @@ void initialize_data()
|
|||
// grid has not been allocated
|
||||
if (nuc->grid_.size() > 0) {
|
||||
double max_E = nuc->grid_[0].energy.back();
|
||||
int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
int neutron = static_cast<int>(ParticleType::neutron);
|
||||
if (max_E == data::energy_max[neutron]) {
|
||||
write_message(7, "Maximum neutron transport energy: {} eV for {}",
|
||||
data::energy_max[neutron], nuc->name_);
|
||||
|
|
@ -628,7 +614,7 @@ void initialize_data()
|
|||
for (auto& nuc : data::nuclides) {
|
||||
nuc->init_grid();
|
||||
}
|
||||
int neutron = static_cast<int>(Particle::Type::neutron);
|
||||
int neutron = static_cast<int>(ParticleType::neutron);
|
||||
simulation::log_spacing = std::log(data::energy_max[neutron] /
|
||||
data::energy_min[neutron]) / settings::n_log_bins;
|
||||
}
|
||||
|
|
@ -678,13 +664,13 @@ void transport_history_based_single_particle(Particle& p)
|
|||
while (true) {
|
||||
p.event_calculate_xs();
|
||||
p.event_advance();
|
||||
if (p.collision_distance_ > p.boundary_.distance) {
|
||||
if (p.collision_distance() > p.boundary().distance) {
|
||||
p.event_cross_surface();
|
||||
} else {
|
||||
p.event_collide();
|
||||
}
|
||||
p.event_revive_from_secondary();
|
||||
if (!p.alive_)
|
||||
if (!p.alive())
|
||||
break;
|
||||
}
|
||||
p.event_death();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#endif
|
||||
|
||||
#include <algorithm> // for move
|
||||
#include <memory> // for unique_ptr
|
||||
|
||||
#ifdef HAS_DYNAMIC_LINKING
|
||||
#include <dlfcn.h> // for dlopen, dlsym, dlclose, dlerror
|
||||
|
|
@ -15,15 +14,16 @@
|
|||
#include "xtensor/xadapt.hpp"
|
||||
|
||||
#include "openmc/bank.h"
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/file_utils.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/material.h"
|
||||
#include "openmc/memory.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/mgxs_interface.h"
|
||||
#include "openmc/nuclide.h"
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/search.h"
|
||||
#include "openmc/settings.h"
|
||||
|
|
@ -39,8 +39,7 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
|
||||
std::vector<std::unique_ptr<Source>> external_sources;
|
||||
|
||||
vector<unique_ptr<Source>> external_sources;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -56,9 +55,9 @@ IndependentSource::IndependentSource(pugi::xml_node node)
|
|||
if (check_for_node(node, "particle")) {
|
||||
auto temp_str = get_node_value(node, "particle", true, true);
|
||||
if (temp_str == "neutron") {
|
||||
particle_ = Particle::Type::neutron;
|
||||
particle_ = ParticleType::neutron;
|
||||
} else if (temp_str == "photon") {
|
||||
particle_ = Particle::Type::photon;
|
||||
particle_ = ParticleType::photon;
|
||||
settings::photon_transport = true;
|
||||
} else {
|
||||
fatal_error(std::string("Unknown source particle type: ") + temp_str);
|
||||
|
|
@ -141,9 +140,9 @@ IndependentSource::IndependentSource(pugi::xml_node node)
|
|||
}
|
||||
}
|
||||
|
||||
Particle::Bank IndependentSource::sample(uint64_t* seed) const
|
||||
SourceSite IndependentSource::sample(uint64_t* seed) const
|
||||
{
|
||||
Particle::Bank site;
|
||||
SourceSite site;
|
||||
|
||||
// Set weight to one by default
|
||||
site.wgt = 1.0;
|
||||
|
|
@ -263,7 +262,7 @@ FileSource::FileSource(std::string path)
|
|||
file_close(file_id);
|
||||
}
|
||||
|
||||
Particle::Bank FileSource::sample(uint64_t* seed) const
|
||||
SourceSite FileSource::sample(uint64_t* seed) const
|
||||
{
|
||||
size_t i_site = sites_.size()*prn(seed);
|
||||
return sites_[i_site];
|
||||
|
|
@ -349,7 +348,7 @@ void initialize_source()
|
|||
}
|
||||
}
|
||||
|
||||
Particle::Bank sample_external_source(uint64_t* seed)
|
||||
SourceSite sample_external_source(uint64_t* seed)
|
||||
{
|
||||
// Determine total source strength
|
||||
double total_strength = 0.0;
|
||||
|
|
@ -368,7 +367,7 @@ Particle::Bank sample_external_source(uint64_t* seed)
|
|||
}
|
||||
|
||||
// Sample source site from i-th source distribution
|
||||
Particle::Bank site {model::external_sources[i]->sample(seed)};
|
||||
SourceSite site {model::external_sources[i]->sample(seed)};
|
||||
|
||||
// If running in MG, convert site.E to group
|
||||
if (!settings::run_CE) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include <algorithm>
|
||||
#include <cstdint> // for int64_t
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include "xtensor/xbuilder.hpp" // for empty_like
|
||||
|
|
@ -27,6 +26,7 @@
|
|||
#include "openmc/tallies/filter_mesh.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
#include "openmc/timer.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ openmc_statepoint_write(const char* filename, bool* write_source)
|
|||
write_attribute(filters_group, "n_filters", model::tally_filters.size());
|
||||
if (!model::tally_filters.empty()) {
|
||||
// Write filter IDs
|
||||
std::vector<int32_t> filter_ids;
|
||||
vector<int32_t> filter_ids;
|
||||
filter_ids.reserve(model::tally_filters.size());
|
||||
for (const auto& filt : model::tally_filters)
|
||||
filter_ids.push_back(filt->id());
|
||||
|
|
@ -161,7 +161,7 @@ openmc_statepoint_write(const char* filename, bool* write_source)
|
|||
write_attribute(tallies_group, "n_tallies", model::tallies.size());
|
||||
if (!model::tallies.empty()) {
|
||||
// Write tally IDs
|
||||
std::vector<int32_t> tally_ids;
|
||||
vector<int32_t> tally_ids;
|
||||
tally_ids.reserve(model::tallies.size());
|
||||
for (const auto& tally : model::tallies)
|
||||
tally_ids.push_back(tally->id_);
|
||||
|
|
@ -195,7 +195,7 @@ openmc_statepoint_write(const char* filename, bool* write_source)
|
|||
// Write the ID of each filter attached to this tally
|
||||
write_dataset(tally_group, "n_filters", tally->filters().size());
|
||||
if (!tally->filters().empty()) {
|
||||
std::vector<int32_t> filter_ids;
|
||||
vector<int32_t> filter_ids;
|
||||
filter_ids.reserve(tally->filters().size());
|
||||
for (auto i_filt : tally->filters())
|
||||
filter_ids.push_back(model::tally_filters[i_filt]->id());
|
||||
|
|
@ -203,7 +203,7 @@ openmc_statepoint_write(const char* filename, bool* write_source)
|
|||
}
|
||||
|
||||
// Write the nuclides this tally scores
|
||||
std::vector<std::string> nuclides;
|
||||
vector<std::string> nuclides;
|
||||
for (auto i_nuclide : tally->nuclides_) {
|
||||
if (i_nuclide == -1) {
|
||||
nuclides.push_back("total");
|
||||
|
|
@ -221,7 +221,7 @@ openmc_statepoint_write(const char* filename, bool* write_source)
|
|||
model::tally_derivs[tally->deriv_].id);
|
||||
|
||||
// Write the tally score bins
|
||||
std::vector<std::string> scores;
|
||||
vector<std::string> scores;
|
||||
for (auto sc : tally->scores_) scores.push_back(reaction_name(sc));
|
||||
write_dataset(tally_group, "n_score_bins", scores.size());
|
||||
write_dataset(tally_group, "score_bins", scores);
|
||||
|
|
@ -351,7 +351,7 @@ void load_state_point()
|
|||
|
||||
// Read revision number for state point file and make sure it matches with
|
||||
// current version
|
||||
std::array<int, 2> array;
|
||||
array<int, 2> array;
|
||||
read_attribute(file_id, "version", array);
|
||||
if (array != VERSION_STATEPOINT) {
|
||||
fatal_error("State point version does not match current version in OpenMC.");
|
||||
|
|
@ -512,27 +512,29 @@ hid_t h5banktype() {
|
|||
// - openmc/statepoint.py
|
||||
// - docs/source/io_formats/statepoint.rst
|
||||
// - docs/source/io_formats/source.rst
|
||||
hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(struct Particle::Bank));
|
||||
H5Tinsert(banktype, "r", HOFFSET(Particle::Bank, r), postype);
|
||||
H5Tinsert(banktype, "u", HOFFSET(Particle::Bank, u), postype);
|
||||
H5Tinsert(banktype, "E", HOFFSET(Particle::Bank, E), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(banktype, "wgt", HOFFSET(Particle::Bank, wgt), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(banktype, "delayed_group", HOFFSET(Particle::Bank, delayed_group), H5T_NATIVE_INT);
|
||||
H5Tinsert(banktype, "surf_id", HOFFSET(Particle::Bank, surf_id), H5T_NATIVE_INT);
|
||||
H5Tinsert(banktype, "particle", HOFFSET(Particle::Bank, particle), H5T_NATIVE_INT);
|
||||
hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(struct SourceSite));
|
||||
H5Tinsert(banktype, "r", HOFFSET(SourceSite, r), postype);
|
||||
H5Tinsert(banktype, "u", HOFFSET(SourceSite, u), postype);
|
||||
H5Tinsert(banktype, "E", HOFFSET(SourceSite, E), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(banktype, "wgt", HOFFSET(SourceSite, wgt), H5T_NATIVE_DOUBLE);
|
||||
H5Tinsert(banktype, "delayed_group", HOFFSET(SourceSite, delayed_group),
|
||||
H5T_NATIVE_INT);
|
||||
H5Tinsert(banktype, "surf_id", HOFFSET(SourceSite, surf_id), H5T_NATIVE_INT);
|
||||
H5Tinsert(
|
||||
banktype, "particle", HOFFSET(SourceSite, particle), H5T_NATIVE_INT);
|
||||
|
||||
H5Tclose(postype);
|
||||
return banktype;
|
||||
}
|
||||
|
||||
std::vector<int64_t> calculate_surf_source_size()
|
||||
vector<int64_t> calculate_surf_source_size()
|
||||
{
|
||||
std::vector<int64_t> surf_source_index;
|
||||
vector<int64_t> surf_source_index;
|
||||
surf_source_index.reserve(mpi::n_procs + 1);
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
surf_source_index.resize(mpi::n_procs);
|
||||
std::vector<int64_t> bank_size(mpi::n_procs);
|
||||
vector<int64_t> bank_size(mpi::n_procs);
|
||||
|
||||
// Populate the surf_source_index with cumulative sum of the number of
|
||||
// surface source banks per process
|
||||
|
|
@ -594,10 +596,10 @@ write_source_bank(hid_t group_id, bool surf_source_bank)
|
|||
int64_t count_size = simulation::work_per_rank;
|
||||
|
||||
// Set vectors for source bank and starting bank index of each process
|
||||
std::vector<int64_t>* bank_index = &simulation::work_index;
|
||||
std::vector<Particle::Bank>* source_bank = &simulation::source_bank;
|
||||
std::vector<int64_t> surf_source_index_vector;
|
||||
std::vector<Particle::Bank> surf_source_bank_vector;
|
||||
vector<int64_t>* bank_index = &simulation::work_index;
|
||||
vector<SourceSite>* source_bank = &simulation::source_bank;
|
||||
vector<int64_t> surf_source_index_vector;
|
||||
vector<SourceSite> surf_source_bank_vector;
|
||||
|
||||
// Reset dataspace sizes and vectors for surface source bank
|
||||
if (surf_source_bank) {
|
||||
|
|
@ -653,7 +655,7 @@ write_source_bank(hid_t group_id, bool surf_source_bank)
|
|||
|
||||
// Save source bank sites since the array is overwritten below
|
||||
#ifdef OPENMC_MPI
|
||||
std::vector<Particle::Bank> temp_source {source_bank->begin(), source_bank->end()};
|
||||
vector<SourceSite> temp_source {source_bank->begin(), source_bank->end()};
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < mpi::n_procs; ++i) {
|
||||
|
|
@ -664,7 +666,7 @@ write_source_bank(hid_t group_id, bool surf_source_bank)
|
|||
#ifdef OPENMC_MPI
|
||||
// Receive source sites from other processes
|
||||
if (i > 0)
|
||||
MPI_Recv(source_bank->data(), count[0], mpi::bank, i, i,
|
||||
MPI_Recv(source_bank->data(), count[0], mpi::source_site, i, i,
|
||||
mpi::intracomm, MPI_STATUS_IGNORE);
|
||||
#endif
|
||||
|
||||
|
|
@ -689,7 +691,7 @@ write_source_bank(hid_t group_id, bool surf_source_bank)
|
|||
#endif
|
||||
} else {
|
||||
#ifdef OPENMC_MPI
|
||||
MPI_Send(source_bank->data(), count_size, mpi::bank,
|
||||
MPI_Send(source_bank->data(), count_size, mpi::source_site,
|
||||
0, mpi::rank, mpi::intracomm);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -710,7 +712,8 @@ std::string dtype_member_names(hid_t dtype_id)
|
|||
return names;
|
||||
}
|
||||
|
||||
void read_source_bank(hid_t group_id, std::vector<Particle::Bank>& sites, bool distribute)
|
||||
void read_source_bank(
|
||||
hid_t group_id, vector<SourceSite>& sites, bool distribute)
|
||||
{
|
||||
hid_t banktype = h5banktype();
|
||||
|
||||
|
|
@ -774,7 +777,7 @@ void write_unstructured_mesh_results() {
|
|||
|
||||
for (auto& tally : model::tallies) {
|
||||
|
||||
std::vector<std::string> tally_scores;
|
||||
vector<std::string> tally_scores;
|
||||
for (auto filter_idx : tally->filters()) {
|
||||
auto& filter = model::tally_filters[filter_idx];
|
||||
if (filter->type() != "mesh") continue;
|
||||
|
|
@ -824,8 +827,8 @@ void write_unstructured_mesh_results() {
|
|||
int nuc_score_idx = score_idx + nuc_idx*tally->scores_.size();
|
||||
|
||||
// construct result vectors
|
||||
std::vector<double> mean_vec(umesh->n_bins()),
|
||||
std_dev_vec(umesh->n_bins());
|
||||
vector<double> mean_vec(umesh->n_bins()),
|
||||
std_dev_vec(umesh->n_bins());
|
||||
for (int j = 0; j < tally->results_.shape()[0]; j++) {
|
||||
// get the volume for this bin
|
||||
double volume = umesh->volume(j);
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ int word_count(std::string const& str)
|
|||
return count;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& in)
|
||||
vector<std::string> split(const std::string& in)
|
||||
{
|
||||
std::vector<std::string> out;
|
||||
vector<std::string> out;
|
||||
|
||||
for (int i = 0; i < in.size(); ) {
|
||||
// Increment i until we find a non-whitespace character.
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ void write_nuclides(hid_t file)
|
|||
{
|
||||
// Build vectors of nuclide names and awrs while only sorting nuclides from
|
||||
// macroscopics
|
||||
std::vector<std::string> nuc_names;
|
||||
std::vector<std::string> macro_names;
|
||||
std::vector<double> awrs;
|
||||
vector<std::string> nuc_names;
|
||||
vector<std::string> macro_names;
|
||||
vector<double> awrs;
|
||||
|
||||
for (int i = 0; i < data::nuclides.size(); ++i) {
|
||||
if (settings::run_CE) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "openmc/surface.h"
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
|
|
@ -8,15 +7,16 @@
|
|||
#include <fmt/core.h>
|
||||
#include <gsl/gsl>
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/container_util.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/dagmc.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/hdf5_interface.h"
|
||||
#include "openmc/math_functions.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/string_utils.h"
|
||||
#include "openmc/xml_interface.h"
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/math_functions.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
std::unordered_map<int, int> surface_map;
|
||||
std::vector<std::unique_ptr<Surface>> surfaces;
|
||||
vector<unique_ptr<Surface>> surfaces;
|
||||
} // namespace model
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -264,15 +264,15 @@ Direction DAGSurface::normal(Position r) const
|
|||
Direction DAGSurface::reflect(Position r, Direction u, Particle* p) const
|
||||
{
|
||||
Expects(p);
|
||||
p->history_.reset_to_last_intersection();
|
||||
p->history().reset_to_last_intersection();
|
||||
moab::ErrorCode rval;
|
||||
moab::EntityHandle surf = dagmc_ptr_->entity_by_index(2, dag_index_);
|
||||
double pnt[3] = {r.x, r.y, r.z};
|
||||
double dir[3];
|
||||
rval = dagmc_ptr_->get_angle(surf, pnt, dir, &p->history_);
|
||||
rval = dagmc_ptr_->get_angle(surf, pnt, dir, &p->history());
|
||||
MB_CHK_ERR_CONT(rval);
|
||||
p->last_dir_ = u.reflect(dir);
|
||||
return p->last_dir_;
|
||||
p->last_dir() = u.reflect(dir);
|
||||
return p->last_dir();
|
||||
}
|
||||
|
||||
void DAGSurface::to_hdf5(hid_t group_id) const {}
|
||||
|
|
@ -322,7 +322,7 @@ Direction SurfaceXPlane::normal(Position r) const
|
|||
void SurfaceXPlane::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "x-plane", false);
|
||||
std::array<double, 1> coeffs {{x0_}};
|
||||
array<double, 1> coeffs {{x0_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -364,7 +364,7 @@ Direction SurfaceYPlane::normal(Position r) const
|
|||
void SurfaceYPlane::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "y-plane", false);
|
||||
std::array<double, 1> coeffs {{y0_}};
|
||||
array<double, 1> coeffs {{y0_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +406,7 @@ Direction SurfaceZPlane::normal(Position r) const
|
|||
void SurfaceZPlane::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "z-plane", false);
|
||||
std::array<double, 1> coeffs {{z0_}};
|
||||
array<double, 1> coeffs {{z0_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -459,7 +459,7 @@ SurfacePlane::normal(Position r) const
|
|||
void SurfacePlane::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "plane", false);
|
||||
std::array<double, 4> coeffs {{A_, B_, C_, D_}};
|
||||
array<double, 4> coeffs {{A_, B_, C_, D_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -567,7 +567,7 @@ Direction SurfaceXCylinder::normal(Position r) const
|
|||
void SurfaceXCylinder::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "x-cylinder", false);
|
||||
std::array<double, 3> coeffs {{y0_, z0_, radius_}};
|
||||
array<double, 3> coeffs {{y0_, z0_, radius_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -607,7 +607,7 @@ Direction SurfaceYCylinder::normal(Position r) const
|
|||
void SurfaceYCylinder::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "y-cylinder", false);
|
||||
std::array<double, 3> coeffs {{x0_, z0_, radius_}};
|
||||
array<double, 3> coeffs {{x0_, z0_, radius_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -648,7 +648,7 @@ Direction SurfaceZCylinder::normal(Position r) const
|
|||
void SurfaceZCylinder::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "z-cylinder", false);
|
||||
std::array<double, 3> coeffs {{x0_, y0_, radius_}};
|
||||
array<double, 3> coeffs {{x0_, y0_, radius_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -725,7 +725,7 @@ Direction SurfaceSphere::normal(Position r) const
|
|||
void SurfaceSphere::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "sphere", false);
|
||||
std::array<double, 4> coeffs {{x0_, y0_, z0_, radius_}};
|
||||
array<double, 4> coeffs {{x0_, y0_, z0_, radius_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -854,7 +854,7 @@ Direction SurfaceXCone::normal(Position r) const
|
|||
void SurfaceXCone::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "x-cone", false);
|
||||
std::array<double, 4> coeffs {{x0_, y0_, z0_, radius_sq_}};
|
||||
array<double, 4> coeffs {{x0_, y0_, z0_, radius_sq_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -887,7 +887,7 @@ Direction SurfaceYCone::normal(Position r) const
|
|||
void SurfaceYCone::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "y-cone", false);
|
||||
std::array<double, 4> coeffs {{x0_, y0_, z0_, radius_sq_}};
|
||||
array<double, 4> coeffs {{x0_, y0_, z0_, radius_sq_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -920,7 +920,7 @@ Direction SurfaceZCone::normal(Position r) const
|
|||
void SurfaceZCone::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "z-cone", false);
|
||||
std::array<double, 4> coeffs {{x0_, y0_, z0_, radius_sq_}};
|
||||
array<double, 4> coeffs {{x0_, y0_, z0_, radius_sq_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -1025,7 +1025,7 @@ SurfaceQuadric::normal(Position r) const
|
|||
void SurfaceQuadric::to_hdf5_inner(hid_t group_id) const
|
||||
{
|
||||
write_string(group_id, "type", "quadric", false);
|
||||
std::array<double, 10> coeffs {{A_, B_, C_, D_, E_, F_, G_, H_, J_, K_}};
|
||||
array<double, 10> coeffs {{A_, B_, C_, D_, E_, F_, G_, H_, J_, K_}};
|
||||
write_dataset(group_id, "coefficients", coeffs);
|
||||
}
|
||||
|
||||
|
|
@ -1054,40 +1054,40 @@ void read_surfaces(pugi::xml_node node)
|
|||
// Allocate and initialize the new surface
|
||||
|
||||
if (surf_type == "x-plane") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceXPlane>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceXPlane>(surf_node));
|
||||
|
||||
} else if (surf_type == "y-plane") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceYPlane>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceYPlane>(surf_node));
|
||||
|
||||
} else if (surf_type == "z-plane") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceZPlane>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceZPlane>(surf_node));
|
||||
|
||||
} else if (surf_type == "plane") {
|
||||
model::surfaces.push_back(std::make_unique<SurfacePlane>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfacePlane>(surf_node));
|
||||
|
||||
} else if (surf_type == "x-cylinder") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceXCylinder>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceXCylinder>(surf_node));
|
||||
|
||||
} else if (surf_type == "y-cylinder") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceYCylinder>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceYCylinder>(surf_node));
|
||||
|
||||
} else if (surf_type == "z-cylinder") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceZCylinder>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceZCylinder>(surf_node));
|
||||
|
||||
} else if (surf_type == "sphere") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceSphere>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceSphere>(surf_node));
|
||||
|
||||
} else if (surf_type == "x-cone") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceXCone>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceXCone>(surf_node));
|
||||
|
||||
} else if (surf_type == "y-cone") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceYCone>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceYCone>(surf_node));
|
||||
|
||||
} else if (surf_type == "z-cone") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceZCone>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceZCone>(surf_node));
|
||||
|
||||
} else if (surf_type == "quadric") {
|
||||
model::surfaces.push_back(std::make_unique<SurfaceQuadric>(surf_node));
|
||||
model::surfaces.push_back(make_unique<SurfaceQuadric>(surf_node));
|
||||
|
||||
} else {
|
||||
fatal_error(fmt::format("Invalid surface type, \"{}\"", surf_type));
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <fmt/core.h>
|
||||
|
||||
template class std::vector<openmc::TallyDerivative>;
|
||||
template class openmc::vector<openmc::TallyDerivative>;
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
std::unordered_map<int, int> tally_deriv_map;
|
||||
std::vector<TallyDerivative> tally_derivs;
|
||||
vector<TallyDerivative> tally_derivs;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -109,17 +109,17 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
// perturbated variable.
|
||||
|
||||
const auto& deriv {model::tally_derivs[tally.deriv_]};
|
||||
const auto flux_deriv = p.flux_derivs_[tally.deriv_];
|
||||
const auto flux_deriv = p.flux_derivs(tally.deriv_);
|
||||
|
||||
// Handle special cases where we know that d_c/d_p must be zero.
|
||||
if (score_bin == SCORE_FLUX) {
|
||||
score *= flux_deriv;
|
||||
return;
|
||||
} else if (p.material_ == MATERIAL_VOID) {
|
||||
} else if (p.material() == MATERIAL_VOID) {
|
||||
score *= flux_deriv;
|
||||
return;
|
||||
}
|
||||
const Material& material {*model::materials[p.material_]};
|
||||
const Material& material {*model::materials[p.material()]};
|
||||
if (material.id_ != deriv.diff_material) {
|
||||
score *= flux_deriv;
|
||||
return;
|
||||
|
|
@ -179,7 +179,7 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
switch (tally.estimator_) {
|
||||
|
||||
case TallyEstimator::ANALOG:
|
||||
if (p.event_nuclide_ != deriv.diff_nuclide) {
|
||||
if (p.event_nuclide() != deriv.diff_nuclide) {
|
||||
score *= flux_deriv;
|
||||
return;
|
||||
}
|
||||
|
|
@ -210,12 +210,11 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
switch (score_bin) {
|
||||
|
||||
case SCORE_TOTAL:
|
||||
if (i_nuclide == -1 && p.macro_xs_.total > 0.0) {
|
||||
score *= flux_deriv
|
||||
+ p.neutron_xs_[deriv.diff_nuclide].total
|
||||
/ p.macro_xs_.total;
|
||||
} else if (i_nuclide == deriv.diff_nuclide
|
||||
&& p.neutron_xs_[i_nuclide].total) {
|
||||
if (i_nuclide == -1 && p.macro_xs().total > 0.0) {
|
||||
score *= flux_deriv +
|
||||
p.neutron_xs(deriv.diff_nuclide).total / p.macro_xs().total;
|
||||
} else if (i_nuclide == deriv.diff_nuclide &&
|
||||
p.neutron_xs(i_nuclide).total) {
|
||||
score *= flux_deriv + 1. / atom_density;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
|
|
@ -223,13 +222,12 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
break;
|
||||
|
||||
case SCORE_SCATTER:
|
||||
if (i_nuclide == -1 && (p.macro_xs_.total
|
||||
- p.macro_xs_.absorption) > 0.0) {
|
||||
score *= flux_deriv
|
||||
+ (p.neutron_xs_[deriv.diff_nuclide].total
|
||||
- p.neutron_xs_[deriv.diff_nuclide].absorption)
|
||||
/ (p.macro_xs_.total
|
||||
- p.macro_xs_.absorption);
|
||||
if (i_nuclide == -1 &&
|
||||
(p.macro_xs().total - p.macro_xs().absorption) > 0.0) {
|
||||
score *=
|
||||
flux_deriv + (p.neutron_xs(deriv.diff_nuclide).total -
|
||||
p.neutron_xs(deriv.diff_nuclide).absorption) /
|
||||
(p.macro_xs().total - p.macro_xs().absorption);
|
||||
} else if (i_nuclide == deriv.diff_nuclide) {
|
||||
score *= flux_deriv + 1. / atom_density;
|
||||
} else {
|
||||
|
|
@ -238,12 +236,11 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
break;
|
||||
|
||||
case SCORE_ABSORPTION:
|
||||
if (i_nuclide == -1 && p.macro_xs_.absorption > 0.0) {
|
||||
score *= flux_deriv
|
||||
+ p.neutron_xs_[deriv.diff_nuclide].absorption
|
||||
/ p.macro_xs_.absorption;
|
||||
} else if (i_nuclide == deriv.diff_nuclide
|
||||
&& p.neutron_xs_[i_nuclide].absorption) {
|
||||
if (i_nuclide == -1 && p.macro_xs().absorption > 0.0) {
|
||||
score *= flux_deriv + p.neutron_xs(deriv.diff_nuclide).absorption /
|
||||
p.macro_xs().absorption;
|
||||
} else if (i_nuclide == deriv.diff_nuclide &&
|
||||
p.neutron_xs(i_nuclide).absorption) {
|
||||
score *= flux_deriv + 1. / atom_density;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
|
|
@ -251,12 +248,11 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
break;
|
||||
|
||||
case SCORE_FISSION:
|
||||
if (i_nuclide == -1 && p.macro_xs_.fission > 0.0) {
|
||||
score *= flux_deriv
|
||||
+ p.neutron_xs_[deriv.diff_nuclide].fission
|
||||
/ p.macro_xs_.fission;
|
||||
} else if (i_nuclide == deriv.diff_nuclide
|
||||
&& p.neutron_xs_[i_nuclide].fission) {
|
||||
if (i_nuclide == -1 && p.macro_xs().fission > 0.0) {
|
||||
score *= flux_deriv + p.neutron_xs(deriv.diff_nuclide).fission /
|
||||
p.macro_xs().fission;
|
||||
} else if (i_nuclide == deriv.diff_nuclide &&
|
||||
p.neutron_xs(i_nuclide).fission) {
|
||||
score *= flux_deriv + 1. / atom_density;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
|
|
@ -264,12 +260,11 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
break;
|
||||
|
||||
case SCORE_NU_FISSION:
|
||||
if (i_nuclide == -1 && p.macro_xs_.nu_fission > 0.0) {
|
||||
score *= flux_deriv
|
||||
+ p.neutron_xs_[deriv.diff_nuclide].nu_fission
|
||||
/ p.macro_xs_.nu_fission;
|
||||
} else if (i_nuclide == deriv.diff_nuclide
|
||||
&& p.neutron_xs_[i_nuclide].nu_fission) {
|
||||
if (i_nuclide == -1 && p.macro_xs().nu_fission > 0.0) {
|
||||
score *= flux_deriv + p.neutron_xs(deriv.diff_nuclide).nu_fission /
|
||||
p.macro_xs().nu_fission;
|
||||
} else if (i_nuclide == deriv.diff_nuclide &&
|
||||
p.neutron_xs(i_nuclide).nu_fission) {
|
||||
score *= flux_deriv + 1. / atom_density;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
|
|
@ -309,10 +304,11 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
// Find the index of the event nuclide.
|
||||
int i;
|
||||
for (i = 0; i < material.nuclide_.size(); ++i)
|
||||
if (material.nuclide_[i] == p.event_nuclide_) break;
|
||||
if (material.nuclide_[i] == p.event_nuclide())
|
||||
break;
|
||||
|
||||
const auto& nuc {*data::nuclides[p.event_nuclide_]};
|
||||
if (!multipole_in_range(nuc, p.E_last_)) {
|
||||
const auto& nuc {*data::nuclides[p.event_nuclide()]};
|
||||
if (!multipole_in_range(nuc, p.E_last())) {
|
||||
score *= flux_deriv;
|
||||
break;
|
||||
}
|
||||
|
|
@ -320,63 +316,65 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
switch (score_bin) {
|
||||
|
||||
case SCORE_TOTAL:
|
||||
if (p.neutron_xs_[p.event_nuclide_].total) {
|
||||
if (p.neutron_xs(p.event_nuclide()).total) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv + (dsig_s + dsig_a) * material.atom_density_(i)
|
||||
/ p.macro_xs_.total;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + (dsig_s + dsig_a) *
|
||||
material.atom_density_(i) /
|
||||
p.macro_xs().total;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_SCATTER:
|
||||
if (p.neutron_xs_[p.event_nuclide_].total
|
||||
- p.neutron_xs_[p.event_nuclide_].absorption) {
|
||||
if (p.neutron_xs(p.event_nuclide()).total -
|
||||
p.neutron_xs(p.event_nuclide()).absorption) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv + dsig_s * material.atom_density_(i)
|
||||
/ (p.macro_xs_.total - p.macro_xs_.absorption);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *=
|
||||
flux_deriv + dsig_s * material.atom_density_(i) /
|
||||
(p.macro_xs().total - p.macro_xs().absorption);
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_ABSORPTION:
|
||||
if (p.neutron_xs_[p.event_nuclide_].absorption) {
|
||||
if (p.neutron_xs(p.event_nuclide()).absorption) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv + dsig_a * material.atom_density_(i)
|
||||
/ p.macro_xs_.absorption;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + dsig_a * material.atom_density_(i) /
|
||||
p.macro_xs().absorption;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_FISSION:
|
||||
if (p.neutron_xs_[p.event_nuclide_].fission) {
|
||||
if (p.neutron_xs(p.event_nuclide()).fission) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv + dsig_f * material.atom_density_(i)
|
||||
/ p.macro_xs_.fission;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv +
|
||||
dsig_f * material.atom_density_(i) / p.macro_xs().fission;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_NU_FISSION:
|
||||
if (p.neutron_xs_[p.event_nuclide_].fission) {
|
||||
double nu = p.neutron_xs_[p.event_nuclide_].nu_fission
|
||||
/ p.neutron_xs_[p.event_nuclide_].fission;
|
||||
if (p.neutron_xs(p.event_nuclide()).fission) {
|
||||
double nu = p.neutron_xs(p.event_nuclide()).nu_fission /
|
||||
p.neutron_xs(p.event_nuclide()).fission;
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv + nu * dsig_f * material.atom_density_(i)
|
||||
/ p.macro_xs_.nu_fission;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + nu * dsig_f * material.atom_density_(i) /
|
||||
p.macro_xs().nu_fission;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
|
|
@ -392,7 +390,7 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
case TallyEstimator::COLLISION:
|
||||
if (i_nuclide != -1) {
|
||||
const auto& nuc {data::nuclides[i_nuclide]};
|
||||
if (!multipole_in_range(*nuc, p.E_last_)) {
|
||||
if (!multipole_in_range(*nuc, p.E_last())) {
|
||||
score *= flux_deriv;
|
||||
return;
|
||||
}
|
||||
|
|
@ -401,141 +399,136 @@ apply_derivative_to_score(const Particle& p, int i_tally, int i_nuclide,
|
|||
switch (score_bin) {
|
||||
|
||||
case SCORE_TOTAL:
|
||||
if (i_nuclide == -1 && p.macro_xs_.total > 0.0) {
|
||||
if (i_nuclide == -1 && p.macro_xs().total > 0.0) {
|
||||
double cum_dsig = 0;
|
||||
for (auto i = 0; i < material.nuclide_.size(); ++i) {
|
||||
auto i_nuc = material.nuclide_[i];
|
||||
const auto& nuc {*data::nuclides[i_nuc]};
|
||||
if (multipole_in_range(nuc, p.E_last_)
|
||||
&& p.neutron_xs_[i_nuc].total) {
|
||||
if (multipole_in_range(nuc, p.E_last()) &&
|
||||
p.neutron_xs(i_nuc).total) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
cum_dsig += (dsig_s + dsig_a) * material.atom_density_(i);
|
||||
}
|
||||
}
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs_.total;
|
||||
} else if (p.neutron_xs_[i_nuclide].total) {
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs().total;
|
||||
} else if (p.neutron_xs(i_nuclide).total) {
|
||||
const auto& nuc {*data::nuclides[i_nuclide]};
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv
|
||||
+ (dsig_s + dsig_a) / p.neutron_xs_[i_nuclide].total;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *=
|
||||
flux_deriv + (dsig_s + dsig_a) / p.neutron_xs(i_nuclide).total;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_SCATTER:
|
||||
if (i_nuclide == -1 && (p.macro_xs_.total
|
||||
- p.macro_xs_.absorption)) {
|
||||
if (i_nuclide == -1 && (p.macro_xs().total - p.macro_xs().absorption)) {
|
||||
double cum_dsig = 0;
|
||||
for (auto i = 0; i < material.nuclide_.size(); ++i) {
|
||||
auto i_nuc = material.nuclide_[i];
|
||||
const auto& nuc {*data::nuclides[i_nuc]};
|
||||
if (multipole_in_range(nuc, p.E_last_)
|
||||
&& (p.neutron_xs_[i_nuc].total
|
||||
- p.neutron_xs_[i_nuc].absorption)) {
|
||||
if (multipole_in_range(nuc, p.E_last()) &&
|
||||
(p.neutron_xs(i_nuc).total - p.neutron_xs(i_nuc).absorption)) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
cum_dsig += dsig_s * material.atom_density_(i);
|
||||
}
|
||||
}
|
||||
score *= flux_deriv + cum_dsig / (p.macro_xs_.total
|
||||
- p.macro_xs_.absorption);
|
||||
} else if (p.neutron_xs_[i_nuclide].total
|
||||
- p.neutron_xs_[i_nuclide].absorption) {
|
||||
score *= flux_deriv +
|
||||
cum_dsig / (p.macro_xs().total - p.macro_xs().absorption);
|
||||
} else if (p.neutron_xs(i_nuclide).total -
|
||||
p.neutron_xs(i_nuclide).absorption) {
|
||||
const auto& nuc {*data::nuclides[i_nuclide]};
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv + dsig_s / (p.neutron_xs_[i_nuclide].total
|
||||
- p.neutron_xs_[i_nuclide].absorption);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + dsig_s / (p.neutron_xs(i_nuclide).total -
|
||||
p.neutron_xs(i_nuclide).absorption);
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_ABSORPTION:
|
||||
if (i_nuclide == -1 && p.macro_xs_.absorption > 0.0) {
|
||||
if (i_nuclide == -1 && p.macro_xs().absorption > 0.0) {
|
||||
double cum_dsig = 0;
|
||||
for (auto i = 0; i < material.nuclide_.size(); ++i) {
|
||||
auto i_nuc = material.nuclide_[i];
|
||||
const auto& nuc {*data::nuclides[i_nuc]};
|
||||
if (multipole_in_range(nuc, p.E_last_)
|
||||
&& p.neutron_xs_[i_nuc].absorption) {
|
||||
if (multipole_in_range(nuc, p.E_last()) &&
|
||||
p.neutron_xs(i_nuc).absorption) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
cum_dsig += dsig_a * material.atom_density_(i);
|
||||
}
|
||||
}
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs_.absorption;
|
||||
} else if (p.neutron_xs_[i_nuclide].absorption) {
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs().absorption;
|
||||
} else if (p.neutron_xs(i_nuclide).absorption) {
|
||||
const auto& nuc {*data::nuclides[i_nuclide]};
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv
|
||||
+ dsig_a / p.neutron_xs_[i_nuclide].absorption;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + dsig_a / p.neutron_xs(i_nuclide).absorption;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_FISSION:
|
||||
if (i_nuclide == -1 && p.macro_xs_.fission > 0.0) {
|
||||
if (i_nuclide == -1 && p.macro_xs().fission > 0.0) {
|
||||
double cum_dsig = 0;
|
||||
for (auto i = 0; i < material.nuclide_.size(); ++i) {
|
||||
auto i_nuc = material.nuclide_[i];
|
||||
const auto& nuc {*data::nuclides[i_nuc]};
|
||||
if (multipole_in_range(nuc, p.E_last_)
|
||||
&& p.neutron_xs_[i_nuc].fission) {
|
||||
if (multipole_in_range(nuc, p.E_last()) &&
|
||||
p.neutron_xs(i_nuc).fission) {
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
cum_dsig += dsig_f * material.atom_density_(i);
|
||||
}
|
||||
}
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs_.fission;
|
||||
} else if (p.neutron_xs_[i_nuclide].fission) {
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs().fission;
|
||||
} else if (p.neutron_xs(i_nuclide).fission) {
|
||||
const auto& nuc {*data::nuclides[i_nuclide]};
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv
|
||||
+ dsig_f / p.neutron_xs_[i_nuclide].fission;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + dsig_f / p.neutron_xs(i_nuclide).fission;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_NU_FISSION:
|
||||
if (i_nuclide == -1 && p.macro_xs_.nu_fission > 0.0) {
|
||||
if (i_nuclide == -1 && p.macro_xs().nu_fission > 0.0) {
|
||||
double cum_dsig = 0;
|
||||
for (auto i = 0; i < material.nuclide_.size(); ++i) {
|
||||
auto i_nuc = material.nuclide_[i];
|
||||
const auto& nuc {*data::nuclides[i_nuc]};
|
||||
if (multipole_in_range(nuc, p.E_last_)
|
||||
&& p.neutron_xs_[i_nuc].fission) {
|
||||
double nu = p.neutron_xs_[i_nuc].nu_fission
|
||||
/ p.neutron_xs_[i_nuc].fission;
|
||||
if (multipole_in_range(nuc, p.E_last()) &&
|
||||
p.neutron_xs(i_nuc).fission) {
|
||||
double nu =
|
||||
p.neutron_xs(i_nuc).nu_fission / p.neutron_xs(i_nuc).fission;
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
cum_dsig += nu * dsig_f * material.atom_density_(i);
|
||||
}
|
||||
}
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs_.nu_fission;
|
||||
} else if (p.neutron_xs_[i_nuclide].fission) {
|
||||
score *= flux_deriv + cum_dsig / p.macro_xs().nu_fission;
|
||||
} else if (p.neutron_xs(i_nuclide).fission) {
|
||||
const auto& nuc {*data::nuclides[i_nuclide]};
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
score *= flux_deriv
|
||||
+ dsig_f / p.neutron_xs_[i_nuclide].fission;
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
score *= flux_deriv + dsig_f / p.neutron_xs(i_nuclide).fission;
|
||||
} else {
|
||||
score *= flux_deriv;
|
||||
}
|
||||
|
|
@ -558,13 +551,14 @@ void
|
|||
score_track_derivative(Particle& p, double distance)
|
||||
{
|
||||
// A void material cannot be perturbed so it will not affect flux derivatives.
|
||||
if (p.material_ == MATERIAL_VOID) return;
|
||||
if (p.material() == MATERIAL_VOID)
|
||||
return;
|
||||
|
||||
const Material& material {*model::materials[p.material_]};
|
||||
const Material& material {*model::materials[p.material()]};
|
||||
|
||||
for (auto idx = 0; idx < model::tally_derivs.size(); idx++) {
|
||||
const auto& deriv = model::tally_derivs[idx];
|
||||
auto& flux_deriv = p.flux_derivs_[idx];
|
||||
auto& flux_deriv = p.flux_derivs(idx);
|
||||
if (deriv.diff_material != material.id_) continue;
|
||||
|
||||
switch (deriv.variable) {
|
||||
|
|
@ -573,28 +567,26 @@ score_track_derivative(Particle& p, double distance)
|
|||
// phi is proportional to e^(-Sigma_tot * dist)
|
||||
// (1 / phi) * (d_phi / d_rho) = - (d_Sigma_tot / d_rho) * dist
|
||||
// (1 / phi) * (d_phi / d_rho) = - Sigma_tot / rho * dist
|
||||
flux_deriv -= distance * p.macro_xs_.total
|
||||
/ material.density_gpcc_;
|
||||
flux_deriv -= distance * p.macro_xs().total / material.density_gpcc_;
|
||||
break;
|
||||
|
||||
case DerivativeVariable::NUCLIDE_DENSITY:
|
||||
// phi is proportional to e^(-Sigma_tot * dist)
|
||||
// (1 / phi) * (d_phi / d_N) = - (d_Sigma_tot / d_N) * dist
|
||||
// (1 / phi) * (d_phi / d_N) = - sigma_tot * dist
|
||||
flux_deriv -= distance
|
||||
* p.neutron_xs_[deriv.diff_nuclide].total;
|
||||
flux_deriv -= distance * p.neutron_xs(deriv.diff_nuclide).total;
|
||||
break;
|
||||
|
||||
case DerivativeVariable::TEMPERATURE:
|
||||
for (auto i = 0; i < material.nuclide_.size(); ++i) {
|
||||
const auto& nuc {*data::nuclides[material.nuclide_[i]]};
|
||||
if (multipole_in_range(nuc, p.E_last_)) {
|
||||
if (multipole_in_range(nuc, p.E_last())) {
|
||||
// phi is proportional to e^(-Sigma_tot * dist)
|
||||
// (1 / phi) * (d_phi / d_T) = - (d_Sigma_tot / d_T) * dist
|
||||
// (1 / phi) * (d_phi / d_T) = - N (d_sigma_tot / d_T) * dist
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E(), p.sqrtkT());
|
||||
flux_deriv -= distance * (dsig_s + dsig_a)
|
||||
* material.atom_density_(i);
|
||||
}
|
||||
|
|
@ -607,13 +599,14 @@ score_track_derivative(Particle& p, double distance)
|
|||
void score_collision_derivative(Particle& p)
|
||||
{
|
||||
// A void material cannot be perturbed so it will not affect flux derivatives.
|
||||
if (p.material_ == MATERIAL_VOID) return;
|
||||
if (p.material() == MATERIAL_VOID)
|
||||
return;
|
||||
|
||||
const Material& material {*model::materials[p.material_]};
|
||||
const Material& material {*model::materials[p.material()]};
|
||||
|
||||
for (auto idx = 0; idx < model::tally_derivs.size(); idx++) {
|
||||
const auto& deriv = model::tally_derivs[idx];
|
||||
auto& flux_deriv = p.flux_derivs_[idx];
|
||||
auto& flux_deriv = p.flux_derivs(idx);
|
||||
|
||||
if (deriv.diff_material != material.id_) continue;
|
||||
|
||||
|
|
@ -627,7 +620,8 @@ void score_collision_derivative(Particle& p)
|
|||
break;
|
||||
|
||||
case DerivativeVariable::NUCLIDE_DENSITY:
|
||||
if (p.event_nuclide_ != deriv.diff_nuclide) continue;
|
||||
if (p.event_nuclide() != deriv.diff_nuclide)
|
||||
continue;
|
||||
// Find the index in this material for the diff_nuclide.
|
||||
int i;
|
||||
for (i = 0; i < material.nuclide_.size(); ++i)
|
||||
|
|
@ -649,14 +643,14 @@ void score_collision_derivative(Particle& p)
|
|||
// Loop over the material's nuclides until we find the event nuclide.
|
||||
for (auto i_nuc : material.nuclide_) {
|
||||
const auto& nuc {*data::nuclides[i_nuc]};
|
||||
if (i_nuc == p.event_nuclide_ && multipole_in_range(nuc, p.E_last_)) {
|
||||
if (i_nuc == p.event_nuclide() && multipole_in_range(nuc, p.E_last())) {
|
||||
// phi is proportional to Sigma_s
|
||||
// (1 / phi) * (d_phi / d_T) = (d_Sigma_s / d_T) / Sigma_s
|
||||
// (1 / phi) * (d_phi / d_T) = (d_sigma_s / d_T) / sigma_s
|
||||
const auto& micro_xs {p.neutron_xs_[i_nuc]};
|
||||
const auto& micro_xs {p.neutron_xs(i_nuc)};
|
||||
double dsig_s, dsig_a, dsig_f;
|
||||
std::tie(dsig_s, dsig_a, dsig_f)
|
||||
= nuc.multipole_->evaluate_deriv(p.E_last_, p.sqrtkT_);
|
||||
std::tie(dsig_s, dsig_a, dsig_f) =
|
||||
nuc.multipole_->evaluate_deriv(p.E_last(), p.sqrtkT());
|
||||
flux_deriv += dsig_s / (micro_xs.total - micro_xs.absorption);
|
||||
// Note that this is an approximation! The real scattering cross
|
||||
// section is
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "openmc/tallies/filter_zernike.h"
|
||||
|
||||
// explicit template instantiation definition
|
||||
template class std::vector<openmc::FilterMatch>;
|
||||
template class openmc::vector<openmc::FilterMatch>;
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
std::unordered_map<int, int> filter_map;
|
||||
std::vector<std::unique_ptr<Filter>> tally_filters;
|
||||
vector<unique_ptr<Filter>> tally_filters;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -75,7 +75,7 @@ T* Filter::create(int32_t id) {
|
|||
static_assert(std::is_base_of<Filter, T>::value,
|
||||
"Type specified is not derived from openmc::Filter");
|
||||
// Create filter and add to filters vector
|
||||
auto filter = std::make_unique<T>();
|
||||
auto filter = make_unique<T>();
|
||||
auto ptr_out = filter.get();
|
||||
model::tally_filters.emplace_back(std::move(filter));
|
||||
// Assign ID
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ void
|
|||
AzimuthalFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
Direction u = (estimator == TallyEstimator::TRACKLENGTH) ? p.u() : p.u_last_;
|
||||
Direction u = (estimator == TallyEstimator::TRACKLENGTH) ? p.u() : p.u_last();
|
||||
double phi = std::atan2(u.y, u.x);
|
||||
|
||||
if (phi >= bins_.front() && phi <= bins_.back()) {
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ void
|
|||
CellFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
for (int i = 0; i < p.n_coord_; i++) {
|
||||
auto search = map_.find(p.coord_[i].cell);
|
||||
for (int i = 0; i < p.n_coord(); i++) {
|
||||
auto search = map_.find(p.coord(i).cell);
|
||||
if (search != map_.end()) {
|
||||
match.bins_.push_back(search->second);
|
||||
match.weights_.push_back(1.0);
|
||||
|
|
@ -62,7 +62,7 @@ void
|
|||
CellFilter::to_statepoint(hid_t filter_group) const
|
||||
{
|
||||
Filter::to_statepoint(filter_group);
|
||||
std::vector<int32_t> cell_ids;
|
||||
vector<int32_t> cell_ids;
|
||||
for (auto c : cells_) cell_ids.push_back(model::cells[c]->id_);
|
||||
write_dataset(filter_group, "bins", cell_ids);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ CellInstanceFilter::from_xml(pugi::xml_node node)
|
|||
Expects(cells.size() % 2 == 0);
|
||||
|
||||
// Convert into vector of CellInstance
|
||||
std::vector<CellInstance> instances;
|
||||
vector<CellInstance> instances;
|
||||
for (gsl::index i = 0; i < cells.size() / 2; ++i) {
|
||||
int32_t cell_id = cells[2*i];
|
||||
gsl::index instance = cells[2*i + 1];
|
||||
|
|
@ -69,8 +69,8 @@ void
|
|||
CellInstanceFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
gsl::index index_cell = p.coord_[p.n_coord_ - 1].cell;
|
||||
gsl::index instance = p.cell_instance_;
|
||||
gsl::index index_cell = p.coord(p.n_coord() - 1).cell;
|
||||
gsl::index instance = p.cell_instance();
|
||||
auto search = map_.find({index_cell, instance});
|
||||
if (search != map_.end()) {
|
||||
int index_bin = search->second;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ void
|
|||
CellbornFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
auto search = map_.find(p.cell_born_);
|
||||
auto search = map_.find(p.cell_born());
|
||||
if (search != map_.end()) {
|
||||
match.bins_.push_back(search->second);
|
||||
match.weights_.push_back(1.0);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ void
|
|||
CellFromFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
for (int i = 0; i < p.n_coord_last_; i++) {
|
||||
auto search = map_.find(p.cell_last_[i]);
|
||||
for (int i = 0; i < p.n_coord_last(); i++) {
|
||||
auto search = map_.find(p.cell_last(i));
|
||||
if (search != map_.end()) {
|
||||
match.bins_.push_back(search->second);
|
||||
match.weights_.push_back(1.0);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ void CollisionFilter::get_all_bins(
|
|||
const Particle& p, TallyEstimator estimator, FilterMatch& match) const
|
||||
{
|
||||
// Get the number of collisions for the particle
|
||||
auto n = p.n_collision_;
|
||||
auto n = p.n_collision();
|
||||
|
||||
// Bin the collision number. Must fit exactly the desired collision number.
|
||||
auto search = map_.find(n);
|
||||
|
|
|
|||
|
|
@ -43,20 +43,18 @@ DistribcellFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
|||
{
|
||||
int offset = 0;
|
||||
auto distribcell_index = model::cells[cell_]->distribcell_index_;
|
||||
for (int i = 0; i < p.n_coord_; i++) {
|
||||
auto& c {*model::cells[p.coord_[i].cell]};
|
||||
for (int i = 0; i < p.n_coord(); i++) {
|
||||
auto& c {*model::cells[p.coord(i).cell]};
|
||||
if (c.type_ == Fill::UNIVERSE) {
|
||||
offset += c.offset_[distribcell_index];
|
||||
} else if (c.type_ == Fill::LATTICE) {
|
||||
auto& lat {*model::lattices[p.coord_[i+1].lattice]};
|
||||
int i_xyz[3] {p.coord_[i+1].lattice_x,
|
||||
p.coord_[i+1].lattice_y,
|
||||
p.coord_[i+1].lattice_z};
|
||||
auto& lat {*model::lattices[p.coord(i + 1).lattice]};
|
||||
const auto& i_xyz {p.coord(i + 1).lattice_i};
|
||||
if (lat.are_valid_indices(i_xyz)) {
|
||||
offset += lat.offset(distribcell_index, i_xyz);
|
||||
}
|
||||
}
|
||||
if (cell_ == p.coord_[i].cell) {
|
||||
if (cell_ == p.coord(i).cell) {
|
||||
match.bins_.push_back(offset);
|
||||
match.weights_.push_back(1.0);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -61,17 +61,17 @@ void
|
|||
EnergyFilter::get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match)
|
||||
const
|
||||
{
|
||||
if (p.g_ != F90_NONE && matches_transport_groups_) {
|
||||
if (p.g() != F90_NONE && matches_transport_groups_) {
|
||||
if (estimator == TallyEstimator::TRACKLENGTH) {
|
||||
match.bins_.push_back(data::mg.num_energy_groups_ - p.g_ - 1);
|
||||
match.bins_.push_back(data::mg.num_energy_groups_ - p.g() - 1);
|
||||
} else {
|
||||
match.bins_.push_back(data::mg.num_energy_groups_ - p.g_last_ - 1);
|
||||
match.bins_.push_back(data::mg.num_energy_groups_ - p.g_last() - 1);
|
||||
}
|
||||
match.weights_.push_back(1.0);
|
||||
|
||||
} else {
|
||||
// Get the pre-collision energy of the particle.
|
||||
auto E = p.E_last_;
|
||||
auto E = p.E_last();
|
||||
|
||||
// Bin the energy.
|
||||
if (E >= bins_.front() && E <= bins_.back()) {
|
||||
|
|
@ -103,13 +103,13 @@ void
|
|||
EnergyoutFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
if (p.g_ != F90_NONE && matches_transport_groups_) {
|
||||
match.bins_.push_back(data::mg.num_energy_groups_ - p.g_ - 1);
|
||||
if (p.g() != F90_NONE && matches_transport_groups_) {
|
||||
match.bins_.push_back(data::mg.num_energy_groups_ - p.g() - 1);
|
||||
match.weights_.push_back(1.0);
|
||||
|
||||
} else {
|
||||
if (p.E_ >= bins_.front() && p.E_ <= bins_.back()) {
|
||||
auto bin = lower_bound_index(bins_.begin(), bins_.end(), p.E_);
|
||||
if (p.E() >= bins_.front() && p.E() <= bins_.back()) {
|
||||
auto bin = lower_bound_index(bins_.begin(), bins_.end(), p.E());
|
||||
match.bins_.push_back(bin);
|
||||
match.weights_.push_back(1.0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ void
|
|||
EnergyFunctionFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
if (p.E_last_ >= energy_.front() && p.E_last_ <= energy_.back()) {
|
||||
if (p.E_last() >= energy_.front() && p.E_last() <= energy_.back()) {
|
||||
// Search for the incoming energy bin.
|
||||
auto i = lower_bound_index(energy_.begin(), energy_.end(), p.E_last_);
|
||||
auto i = lower_bound_index(energy_.begin(), energy_.end(), p.E_last());
|
||||
|
||||
// Compute the interpolation factor between the nearest bins.
|
||||
double f = (p.E_last_ - energy_[i]) / (energy_[i+1] - energy_[i]);
|
||||
double f = (p.E_last() - energy_[i]) / (energy_[i + 1] - energy_[i]);
|
||||
|
||||
// Interpolate on the lin-lin grid.
|
||||
match.bins_.push_back(0);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ void
|
|||
LegendreFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
std::vector<double> wgt(n_bins_);
|
||||
calc_pn_c(order_, p.mu_, wgt.data());
|
||||
vector<double> wgt(n_bins_);
|
||||
calc_pn_c(order_, p.mu(), wgt.data());
|
||||
for (int i = 0; i < n_bins_; i++) {
|
||||
match.bins_.push_back(i);
|
||||
match.weights_.push_back(wgt[i]);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void
|
|||
MaterialFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
auto search = map_.find(p.material_);
|
||||
auto search = map_.find(p.material());
|
||||
if (search != map_.end()) {
|
||||
match.bins_.push_back(search->second);
|
||||
match.weights_.push_back(1.0);
|
||||
|
|
@ -59,7 +59,7 @@ void
|
|||
MaterialFilter::to_statepoint(hid_t filter_group) const
|
||||
{
|
||||
Filter::to_statepoint(filter_group);
|
||||
std::vector<int32_t> material_ids;
|
||||
vector<int32_t> material_ids;
|
||||
for (auto c : materials_) material_ids.push_back(model::materials[c]->id_);
|
||||
write_dataset(filter_group, "bins", material_ids);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ MeshFilter::get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatc
|
|||
const
|
||||
{
|
||||
|
||||
Position last_r = p.r_last_;
|
||||
Position last_r = p.r_last();
|
||||
Position r = p.r();
|
||||
Position u = p.u();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ void
|
|||
MeshSurfaceFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
Position r0 = p.r_last_current_;
|
||||
Position r0 = p.r_last_current();
|
||||
Position r1 = p.r();
|
||||
if (translated_) {
|
||||
r0 -= translation();
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ void
|
|||
MuFilter::get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match)
|
||||
const
|
||||
{
|
||||
if (p.mu_ >= bins_.front() && p.mu_ <= bins_.back()) {
|
||||
auto bin = lower_bound_index(bins_.begin(), bins_.end(), p.mu_);
|
||||
if (p.mu() >= bins_.front() && p.mu() <= bins_.back()) {
|
||||
auto bin = lower_bound_index(bins_.begin(), bins_.end(), p.mu());
|
||||
match.bins_.push_back(bin);
|
||||
match.weights_.push_back(1.0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,16 +11,15 @@ ParticleFilter::from_xml(pugi::xml_node node)
|
|||
{
|
||||
auto particles = get_node_array<std::string>(node, "bins");
|
||||
|
||||
// Convert to vector of Particle::Type
|
||||
std::vector<Particle::Type> types;
|
||||
// Convert to vector of ParticleType
|
||||
vector<ParticleType> types;
|
||||
for (auto& p : particles) {
|
||||
types.push_back(str_to_particle_type(p));
|
||||
}
|
||||
this->set_particles(types);
|
||||
}
|
||||
|
||||
void
|
||||
ParticleFilter::set_particles(gsl::span<Particle::Type> particles)
|
||||
void ParticleFilter::set_particles(gsl::span<ParticleType> particles)
|
||||
{
|
||||
// Clear existing particles
|
||||
particles_.clear();
|
||||
|
|
@ -38,7 +37,7 @@ ParticleFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
|||
FilterMatch& match) const
|
||||
{
|
||||
for (auto i = 0; i < particles_.size(); i++) {
|
||||
if (particles_[i] == p.type_) {
|
||||
if (particles_[i] == p.type()) {
|
||||
match.bins_.push_back(i);
|
||||
match.weights_.push_back(1.0);
|
||||
}
|
||||
|
|
@ -49,7 +48,7 @@ void
|
|||
ParticleFilter::to_statepoint(hid_t filter_group) const
|
||||
{
|
||||
Filter::to_statepoint(filter_group);
|
||||
std::vector<std::string> particles;
|
||||
vector<std::string> particles;
|
||||
for (auto p : particles_) {
|
||||
particles.push_back(particle_type_to_str(p));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ void
|
|||
PolarFilter::get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match)
|
||||
const
|
||||
{
|
||||
double z = (estimator == TallyEstimator::TRACKLENGTH) ? p.u().z : p.u_last_.z;
|
||||
double z =
|
||||
(estimator == TallyEstimator::TRACKLENGTH) ? p.u().z : p.u_last().z;
|
||||
double theta = std::acos(z);
|
||||
|
||||
if (theta >= bins_.front() && theta <= bins_.back()) {
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ SphericalHarmonicsFilter::get_all_bins(const Particle& p, TallyEstimator estimat
|
|||
FilterMatch& match) const
|
||||
{
|
||||
// Determine cosine term for scatter expansion if necessary
|
||||
std::vector<double> wgt(order_ + 1);
|
||||
vector<double> wgt(order_ + 1);
|
||||
if (cosine_ == SphericalHarmonicsCosine::scatter) {
|
||||
calc_pn_c(order_, p.mu_, wgt.data());
|
||||
calc_pn_c(order_, p.mu(), wgt.data());
|
||||
} else {
|
||||
for (int i = 0; i < order_ + 1; i++) {
|
||||
wgt[i] = 1;
|
||||
|
|
@ -59,8 +59,8 @@ SphericalHarmonicsFilter::get_all_bins(const Particle& p, TallyEstimator estimat
|
|||
}
|
||||
|
||||
// Find the Rn,m values
|
||||
std::vector<double> rn(n_bins_);
|
||||
calc_rn(order_, p.u_last_, rn.data());
|
||||
vector<double> rn(n_bins_);
|
||||
calc_rn(order_, p.u_last(), rn.data());
|
||||
|
||||
int j = 0;
|
||||
for (int n = 0; n < order_ + 1; n++) {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ SpatialLegendreFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
|||
double x_norm = 2.0*(x - min_) / (max_ - min_) - 1.0;
|
||||
|
||||
// Compute and return the Legendre weights.
|
||||
std::vector<double> wgt(order_ + 1);
|
||||
vector<double> wgt(order_ + 1);
|
||||
calc_pn_c(order_, x_norm, wgt.data());
|
||||
for (int i = 0; i < order_ + 1; i++) {
|
||||
match.bins_.push_back(i);
|
||||
|
|
|
|||
|
|
@ -50,10 +50,10 @@ void
|
|||
SurfaceFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
auto search = map_.find(std::abs(p.surface_)-1);
|
||||
auto search = map_.find(std::abs(p.surface()) - 1);
|
||||
if (search != map_.end()) {
|
||||
match.bins_.push_back(search->second);
|
||||
if (p.surface_ < 0) {
|
||||
if (p.surface() < 0) {
|
||||
match.weights_.push_back(-1.0);
|
||||
} else {
|
||||
match.weights_.push_back(1.0);
|
||||
|
|
@ -65,7 +65,7 @@ void
|
|||
SurfaceFilter::to_statepoint(hid_t filter_group) const
|
||||
{
|
||||
Filter::to_statepoint(filter_group);
|
||||
std::vector<int32_t> surface_ids;
|
||||
vector<int32_t> surface_ids;
|
||||
for (auto c : surfaces_) surface_ids.push_back(model::surfaces[c]->id_);
|
||||
write_dataset(filter_group, "bins", surface_ids);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ void
|
|||
UniverseFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
||||
FilterMatch& match) const
|
||||
{
|
||||
for (int i = 0; i < p.n_coord_; i++) {
|
||||
auto search = map_.find(p.coord_[i].universe);
|
||||
for (int i = 0; i < p.n_coord(); i++) {
|
||||
auto search = map_.find(p.coord(i).universe);
|
||||
if (search != map_.end()) {
|
||||
match.bins_.push_back(search->second);
|
||||
match.weights_.push_back(1.0);
|
||||
|
|
@ -61,7 +61,7 @@ void
|
|||
UniverseFilter::to_statepoint(hid_t filter_group) const
|
||||
{
|
||||
Filter::to_statepoint(filter_group);
|
||||
std::vector<int32_t> universe_ids;
|
||||
vector<int32_t> universe_ids;
|
||||
for (auto u : universes_) universe_ids.push_back(model::universes[u]->id_);
|
||||
write_dataset(filter_group, "bins", universe_ids);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ ZernikeFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
|||
|
||||
if (r <= 1.0) {
|
||||
// Compute and return the Zernike weights.
|
||||
std::vector<double> zn(n_bins_);
|
||||
vector<double> zn(n_bins_);
|
||||
calc_zn(order_, r, theta, zn.data());
|
||||
for (int i = 0; i < n_bins_; i++) {
|
||||
match.bins_.push_back(i);
|
||||
|
|
@ -98,7 +98,7 @@ ZernikeRadialFilter::get_all_bins(const Particle& p, TallyEstimator estimator,
|
|||
|
||||
if (r <= 1.0) {
|
||||
// Compute and return the Zernike weights.
|
||||
std::vector<double> zn(n_bins_);
|
||||
vector<double> zn(n_bins_);
|
||||
calc_zn_rad(order_, r, zn.data());
|
||||
for (int i = 0; i < n_bins_; i++) {
|
||||
match.bins_.push_back(i);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#include "openmc/tallies/tally.h"
|
||||
|
||||
#include "openmc/array.h"
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/constants.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/file_utils.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/mesh.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/mgxs_interface.h"
|
||||
#include "openmc/nuclide.h"
|
||||
#include "openmc/particle.h"
|
||||
|
|
@ -18,9 +19,9 @@
|
|||
#include "openmc/tallies/filter.h"
|
||||
#include "openmc/tallies/filter_cell.h"
|
||||
#include "openmc/tallies/filter_cellfrom.h"
|
||||
#include "openmc/tallies/filter_collision.h"
|
||||
#include "openmc/tallies/filter_delayedgroup.h"
|
||||
#include "openmc/tallies/filter_energy.h"
|
||||
#include "openmc/tallies/filter_collision.h"
|
||||
#include "openmc/tallies/filter_legendre.h"
|
||||
#include "openmc/tallies/filter_mesh.h"
|
||||
#include "openmc/tallies/filter_meshsurface.h"
|
||||
|
|
@ -35,7 +36,6 @@
|
|||
#include "xtensor/xview.hpp"
|
||||
|
||||
#include <algorithm> // for max
|
||||
#include <array>
|
||||
#include <cstddef> // for size_t
|
||||
#include <string>
|
||||
|
||||
|
|
@ -47,13 +47,13 @@ namespace openmc {
|
|||
|
||||
namespace model {
|
||||
std::unordered_map<int, int> tally_map;
|
||||
std::vector<std::unique_ptr<Tally>> tallies;
|
||||
std::vector<int> active_tallies;
|
||||
std::vector<int> active_analog_tallies;
|
||||
std::vector<int> active_tracklength_tallies;
|
||||
std::vector<int> active_collision_tallies;
|
||||
std::vector<int> active_meshsurf_tallies;
|
||||
std::vector<int> active_surface_tallies;
|
||||
vector<unique_ptr<Tally>> tallies;
|
||||
vector<int> active_tallies;
|
||||
vector<int> active_analog_tallies;
|
||||
vector<int> active_tracklength_tallies;
|
||||
vector<int> active_collision_tallies;
|
||||
vector<int> active_meshsurf_tallies;
|
||||
vector<int> active_surface_tallies;
|
||||
}
|
||||
|
||||
namespace simulation {
|
||||
|
|
@ -103,13 +103,13 @@ Tally::Tally(pugi::xml_node node)
|
|||
}
|
||||
|
||||
// Determine number of filters
|
||||
std::vector<int> filter_ids;
|
||||
vector<int> filter_ids;
|
||||
if (check_for_node(node, "filters")) {
|
||||
filter_ids = get_node_array<int>(node, "filters");
|
||||
}
|
||||
|
||||
// Allocate and store filter user ids
|
||||
std::vector<Filter*> filters;
|
||||
vector<Filter*> filters;
|
||||
for (int filter_id : filter_ids) {
|
||||
// Determine if filter ID is valid
|
||||
auto it = model::filter_map.find(filter_id);
|
||||
|
|
@ -196,7 +196,7 @@ Tally::Tally(pugi::xml_node node)
|
|||
const auto& f = model::tally_filters[particle_filter_index].get();
|
||||
auto pf = dynamic_cast<ParticleFilter*>(f);
|
||||
for (auto p : pf->particles()) {
|
||||
if (p != Particle::Type::neutron) {
|
||||
if (p != ParticleType::neutron) {
|
||||
warning(fmt::format("Particle filter other than NEUTRON used with "
|
||||
"photon transport turned off. All tallies for particle type {}"
|
||||
" will have no scores", static_cast<int>(p)));
|
||||
|
|
@ -308,7 +308,7 @@ Tally::~Tally()
|
|||
Tally*
|
||||
Tally::create(int32_t id)
|
||||
{
|
||||
model::tallies.push_back(std::make_unique<Tally>(id));
|
||||
model::tallies.push_back(make_unique<Tally>(id));
|
||||
return model::tallies.back().get();
|
||||
}
|
||||
|
||||
|
|
@ -388,8 +388,7 @@ Tally::set_scores(pugi::xml_node node)
|
|||
set_scores(scores);
|
||||
}
|
||||
|
||||
void
|
||||
Tally::set_scores(const std::vector<std::string>& scores)
|
||||
void Tally::set_scores(const vector<std::string>& scores)
|
||||
{
|
||||
// Reset state and prepare for the new scores.
|
||||
scores_.clear();
|
||||
|
|
@ -541,8 +540,7 @@ Tally::set_nuclides(pugi::xml_node node)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Tally::set_nuclides(const std::vector<std::string>& nuclides)
|
||||
void Tally::set_nuclides(const vector<std::string>& nuclides)
|
||||
{
|
||||
nuclides_.clear();
|
||||
|
||||
|
|
@ -595,7 +593,7 @@ Tally::init_triggers(pugi::xml_node node)
|
|||
}
|
||||
|
||||
// Read the trigger scores.
|
||||
std::vector<std::string> trigger_scores;
|
||||
vector<std::string> trigger_scores;
|
||||
if (check_for_node(trigger_node, "scores")) {
|
||||
trigger_scores = get_node_array<std::string>(trigger_node, "scores");
|
||||
} else {
|
||||
|
|
@ -739,7 +737,7 @@ void read_tallies_xml()
|
|||
}
|
||||
|
||||
for (auto node_tal : root.children("tally")) {
|
||||
model::tallies.push_back(std::make_unique<Tally>(node_tal));
|
||||
model::tallies.push_back(make_unique<Tally>(node_tal));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -918,7 +916,7 @@ openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end)
|
|||
if (index_start) *index_start = model::tallies.size();
|
||||
if (index_end) *index_end = model::tallies.size() + n - 1;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
model::tallies.push_back(std::make_unique<Tally>(-1));
|
||||
model::tallies.push_back(make_unique<Tally>(-1));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1108,7 +1106,7 @@ openmc_tally_set_scores(int32_t index, int n, const char** scores)
|
|||
return OPENMC_E_OUT_OF_BOUNDS;
|
||||
}
|
||||
|
||||
std::vector<std::string> scores_str(scores, scores+n);
|
||||
vector<std::string> scores_str(scores, scores + n);
|
||||
try {
|
||||
model::tallies[index]->set_scores(scores_str);
|
||||
} catch (const std::invalid_argument& ex) {
|
||||
|
|
@ -1143,8 +1141,8 @@ openmc_tally_set_nuclides(int32_t index, int n, const char** nuclides)
|
|||
return OPENMC_E_OUT_OF_BOUNDS;
|
||||
}
|
||||
|
||||
std::vector<std::string> words(nuclides, nuclides+n);
|
||||
std::vector<int> nucs;
|
||||
vector<std::string> words(nuclides, nuclides + n);
|
||||
vector<int> nucs;
|
||||
for (auto word : words){
|
||||
if (word == "total") {
|
||||
nucs.push_back(-1);
|
||||
|
|
@ -1188,7 +1186,7 @@ openmc_tally_set_filters(int32_t index, size_t n, const int32_t* indices)
|
|||
// Set the filters.
|
||||
try {
|
||||
// Convert indices to filter pointers
|
||||
std::vector<Filter*> filters;
|
||||
vector<Filter*> filters;
|
||||
for (gsl::index i = 0; i < n; ++i) {
|
||||
int32_t i_filt = indices[i];
|
||||
filters.push_back(model::tally_filters.at(i_filt).get());
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,14 +28,15 @@ namespace openmc {
|
|||
|
||||
namespace data {
|
||||
std::unordered_map<std::string, int> thermal_scatt_map;
|
||||
std::vector<std::unique_ptr<ThermalScattering>> thermal_scatt;
|
||||
vector<unique_ptr<ThermalScattering>> thermal_scatt;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// ThermalScattering implementation
|
||||
//==============================================================================
|
||||
|
||||
ThermalScattering::ThermalScattering(hid_t group, const std::vector<double>& temperature)
|
||||
ThermalScattering::ThermalScattering(
|
||||
hid_t group, const vector<double>& temperature)
|
||||
{
|
||||
// Get name of table from group
|
||||
name_ = object_name(group);
|
||||
|
|
@ -65,7 +66,7 @@ ThermalScattering::ThermalScattering(hid_t group, const std::vector<double>& tem
|
|||
// Determine actual temperatures to read -- start by checking whether a
|
||||
// temperature range was given, in which case all temperatures in the range
|
||||
// are loaded irrespective of what temperatures actually appear in the model
|
||||
std::vector<int> temps_to_read;
|
||||
vector<int> temps_to_read;
|
||||
if (settings::temperature_range[1] > 0.0) {
|
||||
for (const auto& T : temps_available) {
|
||||
if (settings::temperature_range[0] <= T &&
|
||||
|
|
@ -203,15 +204,14 @@ ThermalData::ThermalData(hid_t group)
|
|||
read_attribute(dgroup, "type", temp);
|
||||
if (temp == "coherent_elastic") {
|
||||
auto xs = dynamic_cast<CoherentElasticXS*>(elastic_.xs.get());
|
||||
elastic_.distribution = std::make_unique<CoherentElasticAE>(*xs);
|
||||
elastic_.distribution = make_unique<CoherentElasticAE>(*xs);
|
||||
} else {
|
||||
if (temp == "incoherent_elastic") {
|
||||
elastic_.distribution = std::make_unique<IncoherentElasticAE>(dgroup);
|
||||
elastic_.distribution = make_unique<IncoherentElasticAE>(dgroup);
|
||||
} else if (temp == "incoherent_elastic_discrete") {
|
||||
auto xs = dynamic_cast<Tabulated1D*>(elastic_.xs.get());
|
||||
elastic_.distribution = std::make_unique<IncoherentElasticAEDiscrete>(
|
||||
dgroup, xs->x()
|
||||
);
|
||||
elastic_.distribution =
|
||||
make_unique<IncoherentElasticAEDiscrete>(dgroup, xs->x());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,12 +231,11 @@ ThermalData::ThermalData(hid_t group)
|
|||
std::string temp;
|
||||
read_attribute(dgroup, "type", temp);
|
||||
if (temp == "incoherent_inelastic") {
|
||||
inelastic_.distribution = std::make_unique<IncoherentInelasticAE>(dgroup);
|
||||
inelastic_.distribution = make_unique<IncoherentInelasticAE>(dgroup);
|
||||
} else if (temp == "incoherent_inelastic_discrete") {
|
||||
auto xs = dynamic_cast<Tabulated1D*>(inelastic_.xs.get());
|
||||
inelastic_.distribution = std::make_unique<IncoherentInelasticAEDiscrete>(
|
||||
dgroup, xs->x()
|
||||
);
|
||||
inelastic_.distribution =
|
||||
make_unique<IncoherentInelasticAEDiscrete>(dgroup, xs->x());
|
||||
}
|
||||
|
||||
close_group(inelastic_group);
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
#include "openmc/position.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/simulation.h"
|
||||
#include "openmc/vector.h"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include "xtensor/xtensor.hpp"
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openmc {
|
||||
|
||||
|
|
@ -25,35 +25,35 @@ namespace openmc {
|
|||
|
||||
void add_particle_track(Particle& p)
|
||||
{
|
||||
p.tracks_.emplace_back();
|
||||
p.tracks().emplace_back();
|
||||
}
|
||||
|
||||
void write_particle_track(Particle& p)
|
||||
{
|
||||
p.tracks_.back().push_back(p.r());
|
||||
p.tracks().back().push_back(p.r());
|
||||
}
|
||||
|
||||
void finalize_particle_track(Particle& p)
|
||||
{
|
||||
std::string filename = fmt::format("{}track_{}_{}_{}.h5",
|
||||
settings::path_output, simulation::current_batch, simulation::current_gen,
|
||||
p.id_);
|
||||
std::string filename =
|
||||
fmt::format("{}track_{}_{}_{}.h5", settings::path_output,
|
||||
simulation::current_batch, simulation::current_gen, p.id());
|
||||
|
||||
// Determine number of coordinates for each particle
|
||||
std::vector<int> n_coords;
|
||||
for (auto& coords : p.tracks_) {
|
||||
vector<int> n_coords;
|
||||
for (auto& coords : p.tracks()) {
|
||||
n_coords.push_back(coords.size());
|
||||
}
|
||||
|
||||
#pragma omp critical (FinalizeParticleTrack)
|
||||
#pragma omp critical (FinalizeParticleTrack)
|
||||
{
|
||||
hid_t file_id = file_open(filename, 'w');
|
||||
write_attribute(file_id, "filetype", "track");
|
||||
write_attribute(file_id, "version", VERSION_TRACK);
|
||||
write_attribute(file_id, "n_particles", p.tracks_.size());
|
||||
write_attribute(file_id, "n_particles", p.tracks().size());
|
||||
write_attribute(file_id, "n_coords", n_coords);
|
||||
for (auto i = 1; i <= p.tracks_.size(); ++i) {
|
||||
const auto& t {p.tracks_[i-1]};
|
||||
for (auto i = 1; i <= p.tracks().size(); ++i) {
|
||||
const auto& t {p.tracks()[i - 1]};
|
||||
size_t n = t.size();
|
||||
xt::xtensor<double, 2> data({n,3});
|
||||
for (int j = 0; j < n; ++j) {
|
||||
|
|
@ -68,7 +68,7 @@ void finalize_particle_track(Particle& p)
|
|||
}
|
||||
|
||||
// Clear particle tracks
|
||||
p.tracks_.clear();
|
||||
p.tracks().clear();
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace openmc {
|
|||
//==============================================================================
|
||||
|
||||
namespace model {
|
||||
std::vector<VolumeCalculation> volume_calcs;
|
||||
vector<VolumeCalculation> volume_calcs;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -94,12 +94,14 @@ VolumeCalculation::VolumeCalculation(pugi::xml_node node)
|
|||
|
||||
}
|
||||
|
||||
std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
||||
vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
||||
{
|
||||
// Shared data that is collected from all threads
|
||||
int n = domain_ids_.size();
|
||||
std::vector<std::vector<int>> master_indices(n); // List of material indices for each domain
|
||||
std::vector<std::vector<int>> master_hits(n); // Number of hits for each material in each domain
|
||||
vector<vector<int>> master_indices(
|
||||
n); // List of material indices for each domain
|
||||
vector<vector<int>> master_hits(
|
||||
n); // Number of hits for each material in each domain
|
||||
int iterations = 0;
|
||||
|
||||
// Divide work over MPI processes
|
||||
|
|
@ -119,8 +121,8 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
#pragma omp parallel
|
||||
{
|
||||
// Variables that are private to each thread
|
||||
std::vector<std::vector<int>> indices(n);
|
||||
std::vector<std::vector<int>> hits(n);
|
||||
vector<vector<int>> indices(n);
|
||||
vector<vector<int>> hits(n);
|
||||
Particle p;
|
||||
|
||||
// Sample locations and count hits
|
||||
|
|
@ -129,7 +131,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
int64_t id = iterations * n_samples_ + i;
|
||||
uint64_t seed = init_seed(id, STREAM_VOLUME);
|
||||
|
||||
p.n_coord_ = 1;
|
||||
p.n_coord() = 1;
|
||||
Position xi {prn(&seed), prn(&seed), prn(&seed)};
|
||||
p.r() = lower_left_ + xi*(upper_right_ - lower_left_);
|
||||
p.u() = {0.5, 0.5, 0.5};
|
||||
|
|
@ -139,28 +141,33 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
continue;
|
||||
|
||||
if (domain_type_ == TallyDomain::MATERIAL) {
|
||||
if (p.material_ != MATERIAL_VOID) {
|
||||
if (p.material() != MATERIAL_VOID) {
|
||||
for (int i_domain = 0; i_domain < n; i_domain++) {
|
||||
if (model::materials[p.material_]->id_ == domain_ids_[i_domain]) {
|
||||
this->check_hit(p.material_, indices[i_domain], hits[i_domain]);
|
||||
if (model::materials[p.material()]->id_ ==
|
||||
domain_ids_[i_domain]) {
|
||||
this->check_hit(
|
||||
p.material(), indices[i_domain], hits[i_domain]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (domain_type_ == TallyDomain::CELL) {
|
||||
for (int level = 0; level < p.n_coord_; ++level) {
|
||||
for (int level = 0; level < p.n_coord(); ++level) {
|
||||
for (int i_domain=0; i_domain < n; i_domain++) {
|
||||
if (model::cells[p.coord_[level].cell]->id_ == domain_ids_[i_domain]) {
|
||||
this->check_hit(p.material_, indices[i_domain], hits[i_domain]);
|
||||
if (model::cells[p.coord(level).cell]->id_ ==
|
||||
domain_ids_[i_domain]) {
|
||||
this->check_hit(
|
||||
p.material(), indices[i_domain], hits[i_domain]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (domain_type_ == TallyDomain::UNIVERSE) {
|
||||
for (int level = 0; level < p.n_coord_; ++level) {
|
||||
for (int level = 0; level < p.n_coord(); ++level) {
|
||||
for (int i_domain = 0; i_domain < n; ++i_domain) {
|
||||
if (model::universes[p.coord_[level].universe]->id_ == domain_ids_[i_domain]) {
|
||||
check_hit(p.material_, indices[i_domain], hits[i_domain]);
|
||||
if (model::universes[p.coord(level).universe]->id_ ==
|
||||
domain_ids_[i_domain]) {
|
||||
check_hit(p.material(), indices[i_domain], hits[i_domain]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -219,7 +226,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
double trigger_val = -INFTY;
|
||||
|
||||
// Set size for members of the Result struct
|
||||
std::vector<Result> results(n);
|
||||
vector<Result> results(n);
|
||||
|
||||
for (int i_domain = 0; i_domain < n; ++i_domain) {
|
||||
// Get reference to result for this domain
|
||||
|
|
@ -235,7 +242,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
for (int j = 1; j < mpi::n_procs; j++) {
|
||||
int q;
|
||||
MPI_Recv(&q, 1, MPI_INTEGER, j, 2*j, mpi::intracomm, MPI_STATUS_IGNORE);
|
||||
std::vector<int> buffer(2*q);
|
||||
vector<int> buffer(2 * q);
|
||||
MPI_Recv(buffer.data(), 2*q, MPI_INTEGER, j, 2*j + 1, mpi::intracomm, MPI_STATUS_IGNORE);
|
||||
for (int k = 0; k < q; ++k) {
|
||||
bool already_added = false;
|
||||
|
|
@ -254,7 +261,7 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
}
|
||||
} else {
|
||||
int q = master_indices[i_domain].size();
|
||||
std::vector<int> buffer(2*q);
|
||||
vector<int> buffer(2 * q);
|
||||
for (int k = 0; k < q; ++k) {
|
||||
buffer[2*k] = master_indices[i_domain][k];
|
||||
buffer[2*k + 1] = master_hits[i_domain][k];
|
||||
|
|
@ -348,8 +355,8 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
|
|||
} // end while
|
||||
}
|
||||
|
||||
void VolumeCalculation::to_hdf5(const std::string& filename,
|
||||
const std::vector<Result>& results) const
|
||||
void VolumeCalculation::to_hdf5(
|
||||
const std::string& filename, const vector<Result>& results) const
|
||||
{
|
||||
// Create HDF5 file
|
||||
hid_t file_id = file_open(filename, 'w');
|
||||
|
|
@ -413,7 +420,7 @@ void VolumeCalculation::to_hdf5(const std::string& filename,
|
|||
// Create array of nuclide names from the vector
|
||||
auto n_nuc = result.nuclides.size();
|
||||
|
||||
std::vector<std::string> nucnames;
|
||||
vector<std::string> nucnames;
|
||||
for (int i_nuc : result.nuclides) {
|
||||
nucnames.push_back(data::nuclides[i_nuc]->name_);
|
||||
}
|
||||
|
|
@ -433,8 +440,8 @@ void VolumeCalculation::to_hdf5(const std::string& filename,
|
|||
file_close(file_id);
|
||||
}
|
||||
|
||||
void VolumeCalculation::check_hit(int i_material, std::vector<int>& indices,
|
||||
std::vector<int>& hits) const
|
||||
void VolumeCalculation::check_hit(
|
||||
int i_material, vector<int>& indices, vector<int>& hits) const
|
||||
{
|
||||
|
||||
// Check if this material was previously hit and if so, increment count
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ WindowedMultipole::evaluate(double E, double sqrtkT) const
|
|||
if (sqrtkT > 0.0 && window.broaden_poly) {
|
||||
// Broaden the curvefit.
|
||||
double dopp = sqrt_awr_ / sqrtkT;
|
||||
std::array<double, MAX_POLY_COEFFICIENTS> broadened_polynomials;
|
||||
array<double, MAX_POLY_COEFFICIENTS> broadened_polynomials;
|
||||
broaden_wmp_polynomials(E, dopp, fit_order_ + 1, broadened_polynomials.data());
|
||||
for (int i_poly = 0; i_poly < fit_order_ + 1; ++i_poly) {
|
||||
sig_s += curvefit_(i_window, i_poly, FIT_S) * broadened_polynomials[i_poly];
|
||||
|
|
@ -216,7 +216,7 @@ WindowedMultipole::evaluate_deriv(double E, double sqrtkT) const
|
|||
void check_wmp_version(hid_t file)
|
||||
{
|
||||
if (attribute_exists(file, "version")) {
|
||||
std::array<int, 2> version;
|
||||
array<int, 2> version;
|
||||
read_attribute(file, "version", version);
|
||||
if (version[0] != WMP_VERSION[0]) {
|
||||
fatal_error(fmt::format(
|
||||
|
|
@ -252,7 +252,7 @@ void read_multipole_data(int i_nuclide)
|
|||
|
||||
// Read nuclide data from HDF5
|
||||
hid_t group = open_group(file, nuc->name_.c_str());
|
||||
nuc->multipole_ = std::make_unique<WindowedMultipole>(group);
|
||||
nuc->multipole_ = make_unique<WindowedMultipole>(group);
|
||||
close_group(group);
|
||||
file_close(file);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ XsData::XsData(bool fissionable, AngleDistributionType scatter_format, int n_pol
|
|||
fatal_error("Invalid scatter_format!");
|
||||
}
|
||||
// allocate all [temperature][angle][in group] quantities
|
||||
std::vector<size_t> shape {n_ang, n_g_};
|
||||
vector<size_t> shape {n_ang, n_g_};
|
||||
total = xt::zeros<double>(shape);
|
||||
absorption = xt::zeros<double>(shape);
|
||||
inverse_velocity = xt::zeros<double>(shape);
|
||||
|
|
@ -509,9 +509,8 @@ XsData::scatter_from_hdf5(hid_t xsdata_grp, size_t n_ang, AngleDistributionType
|
|||
|
||||
//==============================================================================
|
||||
|
||||
void
|
||||
XsData::combine(const std::vector<XsData*>& those_xs,
|
||||
const std::vector<double>& scalars)
|
||||
void XsData::combine(
|
||||
const vector<XsData*>& those_xs, const vector<double>& scalars)
|
||||
{
|
||||
// Combine the non-scattering data
|
||||
for (size_t i = 0; i < those_xs.size(); i++) {
|
||||
|
|
@ -551,7 +550,7 @@ XsData::combine(const std::vector<XsData*>& those_xs,
|
|||
// Allow the ScattData object to combine itself
|
||||
for (size_t a = 0; a < total.shape()[0]; a++) {
|
||||
// Build vector of the scattering objects to incorporate
|
||||
std::vector<ScattData*> those_scatts(those_xs.size());
|
||||
vector<ScattData*> those_scatts(those_xs.size());
|
||||
for (size_t i = 0; i < those_xs.size(); i++) {
|
||||
those_scatts[i] = those_xs[i]->scatter[a].get();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue