From 7569139d51b46f7e382ea885af1dc7ffbb02176e Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Tue, 2 Mar 2021 22:49:25 -0500 Subject: [PATCH] added collision filter --- CMakeLists.txt | 1 + include/openmc/tallies/filter_collision.h | 54 ++++++++++ src/tallies/filter.cpp | 3 + src/tallies/filter_collision.cpp | 124 ++++++++++++++++++++++ src/tallies/tally.cpp | 1 + 5 files changed, 183 insertions(+) create mode 100644 include/openmc/tallies/filter_collision.h create mode 100644 src/tallies/filter_collision.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e0ff23cb2..e994f6c4ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,6 +320,7 @@ list(APPEND libopenmc_SOURCES src/tallies/filter_distribcell.cpp src/tallies/filter_energyfunc.cpp src/tallies/filter_energy.cpp + src/tallies/filter_collision.cpp src/tallies/filter_legendre.cpp src/tallies/filter_material.cpp src/tallies/filter_mesh.cpp diff --git a/include/openmc/tallies/filter_collision.h b/include/openmc/tallies/filter_collision.h new file mode 100644 index 0000000000..46c2b66d86 --- /dev/null +++ b/include/openmc/tallies/filter_collision.h @@ -0,0 +1,54 @@ +#ifndef OPENMC_TALLIES_FILTER_COLLISIONS_H +#define OPENMC_TALLIES_FILTER_COLLISIONS_H + +#include + +#include + +#include "openmc/tallies/filter.h" + +namespace openmc { + +//============================================================================== +//! Bins the incident neutron energy. +//============================================================================== + +class CollisionFilter : public Filter +{ +public: + //---------------------------------------------------------------------------- + // Constructors, destructors + + ~CollisionFilter() = default; + + //---------------------------------------------------------------------------- + // Methods + + std::string type() const override {return "numCollisions";} + + void from_xml(pugi::xml_node node) override; + + void get_all_bins(const Particle& p, TallyEstimator estimator, FilterMatch& match) + const override; + + void to_statepoint(hid_t filter_group) const override; + + std::string text_label(int bin) const override; + + //---------------------------------------------------------------------------- + // Accessors + + const std::vector& bins() const { return bins_; } + void set_bins(gsl::span bins); + +protected: + //---------------------------------------------------------------------------- + // Data members + + std::vector bins_; + +}; + + +} // namespace openmc +#endif // OPENMC_TALLIES_FILTER_COLLISIONS_H diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index 10f89cfa90..7da1606ca8 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -19,6 +19,7 @@ #include "openmc/tallies/filter_distribcell.h" #include "openmc/tallies/filter_energyfunc.h" #include "openmc/tallies/filter_energy.h" +#include "openmc/tallies/filter_collision.h" #include "openmc/tallies/filter_legendre.h" #include "openmc/tallies/filter_material.h" #include "openmc/tallies/filter_mesh.h" @@ -125,6 +126,8 @@ Filter* Filter::create(const std::string& type, int32_t id) return Filter::create(id); } else if (type == "energy") { return Filter::create(id); + } else if (type == "collision") { + return Filter::create(id); } else if (type == "energyout") { return Filter::create(id); } else if (type == "legendre") { diff --git a/src/tallies/filter_collision.cpp b/src/tallies/filter_collision.cpp new file mode 100644 index 0000000000..ad55e4cd80 --- /dev/null +++ b/src/tallies/filter_collision.cpp @@ -0,0 +1,124 @@ +#include "openmc/tallies/filter_collision.h" + +#include + +#include "openmc/capi.h" +#include "openmc/constants.h" // For F90_NONE +#include "openmc/mgxs_interface.h" +#include "openmc/search.h" +#include "openmc/settings.h" +#include "openmc/xml_interface.h" + +namespace openmc { + +//============================================================================== +// CollisionFilter implementation +//============================================================================== + +void +CollisionFilter::from_xml(pugi::xml_node node) +{ + auto bins = get_node_array(node, "bins"); + this->set_bins(bins); +} + +void +CollisionFilter::set_bins(gsl::span bins) +{ + // Clear existing bins + bins_.clear(); + bins_.reserve(bins.size()); + + // Copy bins, ensuring they are valid + for (gsl::index i = 0; i < bins.size(); ++i) { + if (i > 0 && bins[i] <= bins[i-1]) { + throw std::runtime_error{"Number of Collisions bins must be monotonically increasing."}; + } + bins_.push_back(bins[i]); + } + + n_bins_ = bins_.size(); + +} + +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_; + + // Bin the collision number. Must fit exactly the desired collision number . + if (n >= bins_.front() && n <= bins_.back()) { + auto it = find(bins_.begin(), bins_.end(), n); + if (it != bins_.end()){ + size_t bin = it - bins_.begin(); + if (int(bins_[bin]) == n){ + match.bins_.push_back(bin); + match.weights_.push_back(1.0); + } + } + } +} + +void +CollisionFilter::to_statepoint(hid_t filter_group) const +{ + Filter::to_statepoint(filter_group); + write_dataset(filter_group, "bins", bins_); +} + +std::string +CollisionFilter::text_label(int bin) const +{ + return fmt::format("Collision Number {}", int(bins_[bin])); +} + +//============================================================================== +// C-API functions +//============================================================================== + +extern"C" int +openmc_collision_filter_get_bins(int32_t index, const int** energies, size_t* n) +{ + // Make sure this is a valid index to an allocated filter. + if (int err = verify_filter(index)) return err; + + // Get a pointer to the filter and downcast. + const auto& filt_base = model::tally_filters[index].get(); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Tried to get collision bins on a non-collision filter."); + return OPENMC_E_INVALID_TYPE; + } + + // Output the bins. + *energies = filt->bins().data(); + *n = filt->bins().size(); + return 0; +} + +extern "C" int +openmc_collision_filter_set_bins(int32_t index, size_t n, const int* energies) +{ + // Make sure this is a valid index to an allocated filter. + if (int err = verify_filter(index)) return err; + + // Get a pointer to the filter and downcast. + const auto& filt_base = model::tally_filters[index].get(); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Tried to set collision bins on a non-collision filter."); + return OPENMC_E_INVALID_TYPE; + } + + // Update the filter. + filt->set_bins({energies, n}); + return 0; +} + +}// namespace openmc diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 038bcec649..2208bc3cb2 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -20,6 +20,7 @@ #include "openmc/tallies/filter_cellfrom.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"