From a57034b83a6294d0fc0a02a23a4ccc5b25a2006c Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Tue, 2 Mar 2021 22:49:25 -0500 Subject: [PATCH 01/14] 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 3e0ff23cb24..e994f6c4ee0 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 00000000000..46c2b66d86f --- /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 10f89cfa903..7da1606ca80 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 00000000000..ad55e4cd80e --- /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 038bcec649f..2208bc3cb22 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" From c3f834c0cc4fa4903337d44f5376fa638e563f6d Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Thu, 4 Mar 2021 23:02:19 -0500 Subject: [PATCH 02/14] Applied formatting corrections --- include/openmc/tallies/filter_collision.h | 11 ++-- src/tallies/filter_collision.cpp | 65 +++++++++++------------ 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/include/openmc/tallies/filter_collision.h b/include/openmc/tallies/filter_collision.h index 46c2b66d86f..47736104166 100644 --- a/include/openmc/tallies/filter_collision.h +++ b/include/openmc/tallies/filter_collision.h @@ -13,8 +13,7 @@ namespace openmc { //! Bins the incident neutron energy. //============================================================================== -class CollisionFilter : public Filter -{ +class CollisionFilter : public Filter { public: //---------------------------------------------------------------------------- // Constructors, destructors @@ -24,12 +23,12 @@ class CollisionFilter : public Filter //---------------------------------------------------------------------------- // Methods - std::string type() const override {return "numCollisions";} + 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 get_all_bins(const Particle& p, TallyEstimator estimator, + FilterMatch& match) const override; void to_statepoint(hid_t filter_group) const override; @@ -46,9 +45,7 @@ class CollisionFilter : public Filter // Data members std::vector bins_; - }; - } // namespace openmc #endif // OPENMC_TALLIES_FILTER_COLLISIONS_H diff --git a/src/tallies/filter_collision.cpp b/src/tallies/filter_collision.cpp index ad55e4cd80e..bb5b0d1f37d 100644 --- a/src/tallies/filter_collision.cpp +++ b/src/tallies/filter_collision.cpp @@ -3,7 +3,7 @@ #include #include "openmc/capi.h" -#include "openmc/constants.h" // For F90_NONE +#include "openmc/constants.h" // For F90_NONE #include "openmc/mgxs_interface.h" #include "openmc/search.h" #include "openmc/settings.h" @@ -15,15 +15,13 @@ namespace openmc { // CollisionFilter implementation //============================================================================== -void -CollisionFilter::from_xml(pugi::xml_node node) +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) +void CollisionFilter::set_bins(gsl::span bins) { // Clear existing bins bins_.clear(); @@ -31,45 +29,42 @@ CollisionFilter::set_bins(gsl::span bins) // 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."}; + 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 +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); - } + // 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 +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 +std::string CollisionFilter::text_label(int bin) const { return fmt::format("Collision Number {}", int(bins_[bin])); } @@ -78,11 +73,12 @@ CollisionFilter::text_label(int bin) const // C-API functions //============================================================================== -extern"C" int -openmc_collision_filter_get_bins(int32_t index, const int** energies, size_t* n) +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; + 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(); @@ -100,11 +96,12 @@ openmc_collision_filter_get_bins(int32_t index, const int** energies, size_t* n) return 0; } -extern "C" int -openmc_collision_filter_set_bins(int32_t index, size_t n, const int* energies) +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; + 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(); @@ -121,4 +118,4 @@ openmc_collision_filter_set_bins(int32_t index, size_t n, const int* energies) return 0; } -}// namespace openmc +} // namespace openmc From 702a601eedeab54772ee99f1edd0317082b2356c Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Fri, 5 Mar 2021 21:07:43 +0000 Subject: [PATCH 03/14] Got the python interface for the collision filter tentatively working --- include/openmc/tallies/filter_collision.h | 2 +- openmc/filter.py | 124 +++++++++++++++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/include/openmc/tallies/filter_collision.h b/include/openmc/tallies/filter_collision.h index 47736104166..b9b6d65e2a8 100644 --- a/include/openmc/tallies/filter_collision.h +++ b/include/openmc/tallies/filter_collision.h @@ -23,7 +23,7 @@ class CollisionFilter : public Filter { //---------------------------------------------------------------------------- // Methods - std::string type() const override { return "numCollisions"; } + std::string type() const override { return "collision"; } void from_xml(pugi::xml_node node) override; diff --git a/openmc/filter.py b/openmc/filter.py index 416698470b2..5272c9494bf 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -22,7 +22,8 @@ 'universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', 'distribcell', 'delayedgroup', 'energyfunction', 'cellfrom', 'legendre', 'spatiallegendre', - 'sphericalharmonics', 'zernike', 'zernikeradial', 'particle', 'cellinstance' + 'sphericalharmonics', 'zernike', 'zernikeradial', 'particle', 'cellinstance', + 'collision' ) _CURRENT_NAMES = ( @@ -964,6 +965,127 @@ def get_pandas_dataframe(self, data_size, stride, **kwargs): return pd.concat([df, pd.DataFrame(filter_dict)]) +class CollisionFilter(Filter): + """Bins tally events based on the number of collisions. + + Parameters + ---------- + values : Iterable of Int + A list or iterable of the number of collisions, as integer values. + The events whose post-scattering collision number equals one of + the provided values will be counted. + filter_id : int + Unique identifier for the filter + + Attributes + ---------- + values : numpy.ndarray + An array of integer values representing the number of collisions events + by which to filter + id : int + Unique identifier for the filter + bins : numpy.ndarray + An array of integer values representing the number of collisions events + by which to filter + num_bins : Integral + The number of filter bins + + """ + + def __init__(self, values, filter_id=None): + self.values = np.asarray(values) + self.bins = self.values + self.id = filter_id + + + def __repr__(self): + string = type(self).__name__ + '\n' + string += '{: <16}=\t{}\n'.format('\tValues', self.values) + string += '{: <16}=\t{}\n'.format('\tID', self.id) + return string + + @Filter.bins.setter + def bins(self, bins): + Filter.bins.__set__(self, np.asarray(bins)) + + def check_bins(self, bins): + for x in bins: + # Values should be integers + cv.check_type('filter value', x, Integral) + cv.check_greater_than('filter value', x, 0, equality=True) + + def get_bin_index(self, filter_bin): + i = np.where(self.bins[:, 1] == filter_bin[1])[0] + if len(i) == 0: + msg = 'Unable to get the bin index for Filter since "{0}" ' \ + 'is not one of the bins'.format(filter_bin) + raise ValueError(msg) + else: + return i[0] + + def get_pandas_dataframe(self, data_size, stride, **kwargs): + """Builds a Pandas DataFrame for the Filter's bins. + + This method constructs a Pandas DataFrame object for the filter with + columns annotated by filter bin information. This is a helper method for + :meth:`Tally.get_pandas_dataframe`. + + Parameters + ---------- + data_size : int + The total number of bins in the tally corresponding to this filter + stride : int + Stride in memory for the filter + + Returns + ------- + pandas.DataFrame + A Pandas DataFrame with one column of the lower energy bound and one + column of upper energy bound for each filter bin. The number of + rows in the DataFrame is the same as the total number of bins in the + corresponding tally, with the filter bin appropriately tiled to map + to the corresponding tally bins. + + See also + -------- + Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() + + """ + # Initialize Pandas DataFrame + df = pd.DataFrame() + + # Extract the lower and upper energy bounds, then repeat and tile + # them as necessary to account for other filters. + bins = np.repeat(self.bins[:], stride) + tile_factor = data_size // len(bins) + bins = np.tile(bins, tile_factor) + + # Add the new energy columns to the DataFrame. + if hasattr(self, 'units'): + units = ' [{}]'.format(self.units) + else: + units = '' + + df.loc[:, self.short_name.lower() + ' collisions' ] = bins + + return df + + def to_xml_element(self): + """Return XML Element representing the Filter. + + Returns + ------- + element : xml.etree.ElementTree.Element + XML element containing filter data + + """ + element = super().to_xml_element() + element[0].text = ' '.join(str(x) for x in self.values) + return element + + + + class RealFilter(Filter): """Tally modifier that describes phase-space and other characteristics From f20dd9cec9c53f5618230dca25b388a5f6a2478f Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Thu, 25 Mar 2021 14:21:58 -0400 Subject: [PATCH 04/14] addressed some of the requested changes from PR --- docs/source/pythonapi/base.rst | 1 + include/openmc/tallies/filter_collision.h | 5 +- openmc/filter.py | 73 ++--------------------- openmc/lib/filter.py | 12 ++-- src/tallies/filter.cpp | 2 +- src/tallies/filter_collision.cpp | 72 +++------------------- 6 files changed, 28 insertions(+), 137 deletions(-) diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index 544e7009cbb..342b4c1a64f 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -118,6 +118,7 @@ Constructing Tallies openmc.CellFromFilter openmc.CellbornFilter openmc.CellInstanceFilter + openmc.CollisionFilter openmc.SurfaceFilter openmc.MeshFilter openmc.MeshSurfaceFilter diff --git a/include/openmc/tallies/filter_collision.h b/include/openmc/tallies/filter_collision.h index b9b6d65e2a8..45e6d940546 100644 --- a/include/openmc/tallies/filter_collision.h +++ b/include/openmc/tallies/filter_collision.h @@ -2,7 +2,7 @@ #define OPENMC_TALLIES_FILTER_COLLISIONS_H #include - +#include #include #include "openmc/tallies/filter.h" @@ -45,6 +45,9 @@ class CollisionFilter : public Filter { // Data members std::vector bins_; + + std::unordered_map map_; + }; } // namespace openmc diff --git a/openmc/filter.py b/openmc/filter.py index 5272c9494bf..a2c28aeb1ec 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -970,7 +970,7 @@ class CollisionFilter(Filter): Parameters ---------- - values : Iterable of Int + bins : Iterable of int A list or iterable of the number of collisions, as integer values. The events whose post-scattering collision number equals one of the provided values will be counted. @@ -979,28 +979,24 @@ class CollisionFilter(Filter): Attributes ---------- - values : numpy.ndarray - An array of integer values representing the number of collisions events - by which to filter id : int Unique identifier for the filter bins : numpy.ndarray An array of integer values representing the number of collisions events by which to filter - num_bins : Integral + num_bins : int The number of filter bins """ - def __init__(self, values, filter_id=None): - self.values = np.asarray(values) - self.bins = self.values + def __init__(self, bins, filter_id=None): + self.bins = np.asarray(bins) self.id = filter_id def __repr__(self): string = type(self).__name__ + '\n' - string += '{: <16}=\t{}\n'.format('\tValues', self.values) + string += '{: <16}=\t{}\n'.format('\tValues', self.bins) string += '{: <16}=\t{}\n'.format('\tID', self.id) return string @@ -1014,62 +1010,6 @@ def check_bins(self, bins): cv.check_type('filter value', x, Integral) cv.check_greater_than('filter value', x, 0, equality=True) - def get_bin_index(self, filter_bin): - i = np.where(self.bins[:, 1] == filter_bin[1])[0] - if len(i) == 0: - msg = 'Unable to get the bin index for Filter since "{0}" ' \ - 'is not one of the bins'.format(filter_bin) - raise ValueError(msg) - else: - return i[0] - - def get_pandas_dataframe(self, data_size, stride, **kwargs): - """Builds a Pandas DataFrame for the Filter's bins. - - This method constructs a Pandas DataFrame object for the filter with - columns annotated by filter bin information. This is a helper method for - :meth:`Tally.get_pandas_dataframe`. - - Parameters - ---------- - data_size : int - The total number of bins in the tally corresponding to this filter - stride : int - Stride in memory for the filter - - Returns - ------- - pandas.DataFrame - A Pandas DataFrame with one column of the lower energy bound and one - column of upper energy bound for each filter bin. The number of - rows in the DataFrame is the same as the total number of bins in the - corresponding tally, with the filter bin appropriately tiled to map - to the corresponding tally bins. - - See also - -------- - Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe() - - """ - # Initialize Pandas DataFrame - df = pd.DataFrame() - - # Extract the lower and upper energy bounds, then repeat and tile - # them as necessary to account for other filters. - bins = np.repeat(self.bins[:], stride) - tile_factor = data_size // len(bins) - bins = np.tile(bins, tile_factor) - - # Add the new energy columns to the DataFrame. - if hasattr(self, 'units'): - units = ' [{}]'.format(self.units) - else: - units = '' - - df.loc[:, self.short_name.lower() + ' collisions' ] = bins - - return df - def to_xml_element(self): """Return XML Element representing the Filter. @@ -1080,12 +1020,11 @@ def to_xml_element(self): """ element = super().to_xml_element() - element[0].text = ' '.join(str(x) for x in self.values) + element[0].text = ' '.join(str(x) for x in self.bins) return element - class RealFilter(Filter): """Tally modifier that describes phase-space and other characteristics diff --git a/openmc/lib/filter.py b/openmc/lib/filter.py index 1d16b68e07c..9c1eea4da53 100644 --- a/openmc/lib/filter.py +++ b/openmc/lib/filter.py @@ -16,10 +16,10 @@ __all__ = [ 'Filter', 'AzimuthalFilter', 'CellFilter', 'CellbornFilter', 'CellfromFilter', - 'CellInstanceFilter', 'DistribcellFilter', 'DelayedGroupFilter', 'EnergyFilter', - 'EnergyoutFilter', 'EnergyFunctionFilter', 'LegendreFilter', 'MaterialFilter', - 'MeshFilter', 'MeshSurfaceFilter', 'MuFilter', 'ParticleFilter', 'PolarFilter', - 'SphericalHarmonicsFilter', 'SpatialLegendreFilter', 'SurfaceFilter', + 'CellInstanceFilter', 'CollisionFilter', 'DistribcellFilter', 'DelayedGroupFilter', + 'EnergyFilter', 'EnergyoutFilter', 'EnergyFunctionFilter', 'LegendreFilter', + 'MaterialFilter', 'MeshFilter', 'MeshSurfaceFilter', 'MuFilter', 'ParticleFilter', + 'PolarFilter', 'SphericalHarmonicsFilter', 'SpatialLegendreFilter', 'SurfaceFilter', 'UniverseFilter', 'ZernikeFilter', 'ZernikeRadialFilter', 'filters' ] @@ -176,6 +176,10 @@ def bins(self, bins): self._index, len(energies), energies_p) +class CollisionFilterFilter(CollisionFilter): + filter_type = 'collision' + + class EnergyoutFilter(EnergyFilter): filter_type = 'energyout' diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index 7da1606ca80..31f572e4bd7 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -15,11 +15,11 @@ #include "openmc/tallies/filter_cellborn.h" #include "openmc/tallies/filter_cellfrom.h" #include "openmc/tallies/filter_cell_instance.h" +#include "openmc/tallies/filter_collision.h" #include "openmc/tallies/filter_delayedgroup.h" #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" diff --git a/src/tallies/filter_collision.cpp b/src/tallies/filter_collision.cpp index bb5b0d1f37d..60229941a68 100644 --- a/src/tallies/filter_collision.cpp +++ b/src/tallies/filter_collision.cpp @@ -3,8 +3,6 @@ #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" @@ -26,14 +24,12 @@ void CollisionFilter::set_bins(gsl::span bins) // Clear existing bins bins_.clear(); bins_.reserve(bins.size()); + map_.clear(); - // Copy bins, ensuring they are valid + // Copy bins 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]); + map_[bins[i]] = i; } n_bins_ = bins_.size(); @@ -47,13 +43,10 @@ void CollisionFilter::get_all_bins( // 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); - } + auto search = map_.find(n); + if (search != map_.end()){ + match.bins_.push_back(search->second); + match.weights_.push_back(1.0); } } } @@ -66,56 +59,7 @@ void CollisionFilter::to_statepoint(hid_t filter_group) const 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; + return fmt::format("Collision Number {}", bins_[bin]); } } // namespace openmc From cdbfd3bfe711575d2569d9d77c8664fc2b66d2f1 Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Thu, 25 Mar 2021 22:42:04 +0000 Subject: [PATCH 05/14] added tests for collision filter --- openmc/lib/filter.py | 2 +- src/tallies/filter_collision.cpp | 10 ++++------ tests/regression_tests/tallies/test.py | 9 ++++++++- tests/unit_tests/test_filters.py | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/openmc/lib/filter.py b/openmc/lib/filter.py index 9c1eea4da53..59897b50fa4 100644 --- a/openmc/lib/filter.py +++ b/openmc/lib/filter.py @@ -176,7 +176,7 @@ def bins(self, bins): self._index, len(energies), energies_p) -class CollisionFilterFilter(CollisionFilter): +class CollisionFilter(Filter): filter_type = 'collision' diff --git a/src/tallies/filter_collision.cpp b/src/tallies/filter_collision.cpp index 60229941a68..17350acc269 100644 --- a/src/tallies/filter_collision.cpp +++ b/src/tallies/filter_collision.cpp @@ -42,12 +42,10 @@ void CollisionFilter::get_all_bins( auto n = p.n_collision_; // Bin the collision number. Must fit exactly the desired collision number . - if (n >= bins_.front() && n <= bins_.back()) { - auto search = map_.find(n); - if (search != map_.end()){ - match.bins_.push_back(search->second); - match.weights_.push_back(1.0); - } + auto search = map_.find(n); + if (search != map_.end()){ + match.bins_.push_back(search->second); + match.weights_.push_back(1.0); } } diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index d4857b3ec73..8e1e8b60b98 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -121,6 +121,12 @@ def test_tallies(): harmonics_tally3.scores = ['flux', 'total'] harmonics_tally3.estimatir = 'tracklength' + n_collision = (1,2,5,3,6) + collision_filter = CollisionFilter(n_collision) + collision_tally = Tally() + collision_tally .filters = [collision_filter] + collision_tally .scores = ['scatter'] + universe_tally = Tally() universe_tally.filters = [ UniverseFilter((model.geometry.get_all_universes()[1], @@ -174,7 +180,8 @@ def test_tallies(): cellborn_tally, dg_tally, energy_tally, energyout_tally, transfer_tally, material_tally, mu_tally1, mu_tally2, polar_tally1, polar_tally2, polar_tally3, legendre_tally, - harmonics_tally, harmonics_tally2, harmonics_tally3, universe_tally] + harmonics_tally, harmonics_tally2, harmonics_tally3, + universe_tally,collision_tally] model.tallies += score_tallies model.tallies += flux_tallies model.tallies += all_nuclide_tallies diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index bf62abb65d1..d52775abd2f 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -46,6 +46,22 @@ def test_cell_instance(): assert instances.apply(lambda x: x in (0, 1, 2)).all() +def test_collision(): + f = openmc.CollisionFilter([1,5,3,2,8]) + assert f.bins[0] == 1 + assert f.bins[1] == 5 + assert f.bins[-1] == 8 + assert len(f.bins) == 5 + + # Make sure __repr__ works + repr(f) + + # to_xml_element() + elem = f.to_xml_element() + assert elem.tag == 'filter' + assert elem.attrib['type'] == 'collision' + + def test_legendre(): n = 5 f = openmc.LegendreFilter(n) From 2e8928a7c6a426e79f812b2bb063e5a9806676a1 Mon Sep 17 00:00:00 2001 From: Amelia Trainer Date: Tue, 30 Mar 2021 16:46:53 +0000 Subject: [PATCH 06/14] (hopefully) fixed ordering on regression test --- tests/regression_tests/tallies/inputs_true.dat | 7 +++++++ tests/regression_tests/tallies/test.py | 15 +++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat index 9409ca4a71d..5e49d6a2335 100644 --- a/tests/regression_tests/tallies/inputs_true.dat +++ b/tests/regression_tests/tallies/inputs_true.dat @@ -350,6 +350,9 @@ 1 2 3 4 6 8 + + 1 2 5 3 6 + 10 21 22 23 60 @@ -439,6 +442,10 @@ 12 total + + 15 + scatter + 13 absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable decay-rate diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 8e1e8b60b98..1f404134f9f 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -121,12 +121,6 @@ def test_tallies(): harmonics_tally3.scores = ['flux', 'total'] harmonics_tally3.estimatir = 'tracklength' - n_collision = (1,2,5,3,6) - collision_filter = CollisionFilter(n_collision) - collision_tally = Tally() - collision_tally .filters = [collision_filter] - collision_tally .scores = ['scatter'] - universe_tally = Tally() universe_tally.filters = [ UniverseFilter((model.geometry.get_all_universes()[1], @@ -175,6 +169,15 @@ def test_tallies(): fusion_tally.scores = ['H1-production', 'H2-production', 'H3-production', 'He3-production', 'He4-production', 'heating', 'damage-energy'] + n_collision = (1,2,5,3,6) + collision_filter = CollisionFilter(n_collision) + collision_tally = Tally() + collision_tally.filters = [collision_filter] + collision_tally.scores = ['scatter'] + + + + model.tallies += [ azimuthal_tally1, azimuthal_tally2, azimuthal_tally3, cellborn_tally, dg_tally, energy_tally, energyout_tally, From f11ee7ae195a353afe3c4739b63bf236470433be Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Apr 2021 09:51:51 -0500 Subject: [PATCH 07/14] Fix 'estimatir' typo in tallies test and update results --- tests/regression_tests/tallies/inputs_true.dat | 4 ++++ tests/regression_tests/tallies/results_true.dat | 2 +- tests/regression_tests/tallies/test.py | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat index 5e49d6a2335..bc9efe97efd 100644 --- a/tests/regression_tests/tallies/inputs_true.dat +++ b/tests/regression_tests/tallies/inputs_true.dat @@ -425,18 +425,22 @@ 10 scatter nu-scatter + analog 11 scatter nu-scatter flux total + analog 11 flux total + collision 11 flux total + tracklength 12 diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat index 6c56ab67aaa..6aa4d34f881 100644 --- a/tests/regression_tests/tallies/results_true.dat +++ b/tests/regression_tests/tallies/results_true.dat @@ -1 +1 @@ -ba4369130ac65812939cb417c7088ae6c8cdec118fd7dce5645b40a20a3ae47072cd72c24aa091ccc09f833a5bfc0bd72407a0dcde7d3120e39379942614a75b \ No newline at end of file +8f03bf00960a26cce719d6750746f1c99956c0173f01e10f99a246d2c254cbcd47ae98437bdf08532e4122c381b7e164f8f3c1e6f65f883684ce1e87e531443f \ No newline at end of file diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 1f404134f9f..fce84ae4560 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -103,23 +103,23 @@ def test_tallies(): legendre_tally = Tally() legendre_tally.filters = [legendre_filter] legendre_tally.scores = ['scatter', 'nu-scatter'] - legendre_tally.estimatir = 'analog' + legendre_tally.estimator = 'analog' harmonics_filter = SphericalHarmonicsFilter(order=4) harmonics_tally = Tally() harmonics_tally.filters = [harmonics_filter] harmonics_tally.scores = ['scatter', 'nu-scatter', 'flux', 'total'] - harmonics_tally.estimatir = 'analog' + harmonics_tally.estimator = 'analog' harmonics_tally2 = Tally() harmonics_tally2.filters = [harmonics_filter] harmonics_tally2.scores = ['flux', 'total'] - harmonics_tally2.estimatir = 'collision' + harmonics_tally2.estimator = 'collision' harmonics_tally3 = Tally() harmonics_tally3.filters = [harmonics_filter] harmonics_tally3.scores = ['flux', 'total'] - harmonics_tally3.estimatir = 'tracklength' + harmonics_tally3.estimator = 'tracklength' universe_tally = Tally() universe_tally.filters = [ From b5e402719cd19e2e25cd2eb9fa7cbddcd7ec8ac9 Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:42:58 -0400 Subject: [PATCH 08/14] Update openmc/filter.py Co-authored-by: Paul Romano --- openmc/filter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index a2c28aeb1ec..a9566b0f5a2 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -993,7 +993,6 @@ def __init__(self, bins, filter_id=None): self.bins = np.asarray(bins) self.id = filter_id - def __repr__(self): string = type(self).__name__ + '\n' string += '{: <16}=\t{}\n'.format('\tValues', self.bins) From 7483c956064c0d3f03080d5ba5875d30e8ac0eb3 Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:43:09 -0400 Subject: [PATCH 09/14] Update src/tallies/filter_collision.cpp Co-authored-by: Paul Romano --- src/tallies/filter_collision.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/filter_collision.cpp b/src/tallies/filter_collision.cpp index 17350acc269..daa553942b6 100644 --- a/src/tallies/filter_collision.cpp +++ b/src/tallies/filter_collision.cpp @@ -41,7 +41,7 @@ void CollisionFilter::get_all_bins( // Get the number of collisions for the particle auto n = p.n_collision_; - // Bin the collision number. Must fit exactly the desired collision number . + // Bin the collision number. Must fit exactly the desired collision number. auto search = map_.find(n); if (search != map_.end()){ match.bins_.push_back(search->second); From ccbdb3355dcbed57b5b3c68a70f21b66e317e73c Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:43:15 -0400 Subject: [PATCH 10/14] Update tests/regression_tests/tallies/test.py Co-authored-by: Paul Romano --- tests/regression_tests/tallies/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index fce84ae4560..768bfaa1e0c 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -169,7 +169,7 @@ def test_tallies(): fusion_tally.scores = ['H1-production', 'H2-production', 'H3-production', 'He3-production', 'He4-production', 'heating', 'damage-energy'] - n_collision = (1,2,5,3,6) + n_collision = (1, 2, 5, 3, 6) collision_filter = CollisionFilter(n_collision) collision_tally = Tally() collision_tally.filters = [collision_filter] From 4f8ab405fa889c3a08fb60470f88c59c70079c95 Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:43:23 -0400 Subject: [PATCH 11/14] Update tests/unit_tests/test_filters.py Co-authored-by: Paul Romano --- tests/unit_tests/test_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index d52775abd2f..ea94a600e3f 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -47,7 +47,7 @@ def test_cell_instance(): def test_collision(): - f = openmc.CollisionFilter([1,5,3,2,8]) + f = openmc.CollisionFilter([1, 5, 3, 2, 8]) assert f.bins[0] == 1 assert f.bins[1] == 5 assert f.bins[-1] == 8 From 0bbf5b2a5f69a8b2099874c7fdb29993f8f62a13 Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:43:37 -0400 Subject: [PATCH 12/14] Update tests/regression_tests/tallies/test.py Co-authored-by: Paul Romano --- tests/regression_tests/tallies/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 768bfaa1e0c..6e1ec7c84b4 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -184,7 +184,7 @@ def test_tallies(): transfer_tally, material_tally, mu_tally1, mu_tally2, polar_tally1, polar_tally2, polar_tally3, legendre_tally, harmonics_tally, harmonics_tally2, harmonics_tally3, - universe_tally,collision_tally] + universe_tally, collision_tally] model.tallies += score_tallies model.tallies += flux_tallies model.tallies += all_nuclide_tallies From 23c2caa05717a4d66831fcc0157b0b68fea75659 Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:43:46 -0400 Subject: [PATCH 13/14] Update openmc/filter.py Co-authored-by: Paul Romano --- openmc/filter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index a9566b0f5a2..2d8faf37842 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1023,7 +1023,6 @@ def to_xml_element(self): return element - class RealFilter(Filter): """Tally modifier that describes phase-space and other characteristics From b5414f7ce3e68f9cd787f4248a9925619115e5b8 Mon Sep 17 00:00:00 2001 From: Amelia J Trainer Date: Thu, 8 Apr 2021 16:43:53 -0400 Subject: [PATCH 14/14] Update tests/regression_tests/tallies/test.py Co-authored-by: Paul Romano --- tests/regression_tests/tallies/test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/regression_tests/tallies/test.py b/tests/regression_tests/tallies/test.py index 6e1ec7c84b4..7746a4e2419 100644 --- a/tests/regression_tests/tallies/test.py +++ b/tests/regression_tests/tallies/test.py @@ -175,9 +175,6 @@ def test_tallies(): collision_tally.filters = [collision_filter] collision_tally.scores = ['scatter'] - - - model.tallies += [ azimuthal_tally1, azimuthal_tally2, azimuthal_tally3, cellborn_tally, dg_tally, energy_tally, energyout_tally,