From a3695c784eaddd74549f50b79567bc3d12254e79 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Thu, 9 Nov 2023 17:05:42 +0100 Subject: [PATCH] Filter material from (#2750) Co-authored-by: Patrick Shriwise Co-authored-by: Paul Romano --- CMakeLists.txt | 1 + docs/source/pythonapi/base.rst | 1 + include/openmc/particle_data.h | 1 + include/openmc/tallies/filter.h | 1 + include/openmc/tallies/filter_material.h | 2 +- include/openmc/tallies/filter_materialfrom.h | 29 +++++++++++++++++ openmc/filter.py | 32 ++++++++++++++++--- openmc/lib/filter.py | 7 +++- src/tallies/filter.cpp | 3 ++ src/tallies/filter_materialfrom.cpp | 24 ++++++++++++++ .../surface_tally/inputs_true.dat | 2 +- tests/regression_tests/surface_tally/test.py | 6 ++-- 12 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 include/openmc/tallies/filter_materialfrom.h create mode 100644 src/tallies/filter_materialfrom.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 24b855977..7269f4e63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -406,6 +406,7 @@ list(APPEND libopenmc_SOURCES src/tallies/filter_energyfunc.cpp src/tallies/filter_legendre.cpp src/tallies/filter_material.cpp + src/tallies/filter_materialfrom.cpp src/tallies/filter_mesh.cpp src/tallies/filter_meshsurface.cpp src/tallies/filter_mu.cpp diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index e18423c58..ba86db117 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -118,6 +118,7 @@ Constructing Tallies openmc.Filter openmc.UniverseFilter openmc.MaterialFilter + openmc.MaterialFromFilter openmc.CellFilter openmc.CellFromFilter openmc.CellBornFilter diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index d0813f9c5..ee34c3052 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -435,6 +435,7 @@ public: int& material() { return material_; } const int& material() const { return material_; } int& material_last() { return material_last_; } + const int& material_last() const { return material_last_; } BoundaryInfo& boundary() { return boundary_; } diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h index 8a17ee7ea..dc5872ce6 100644 --- a/include/openmc/tallies/filter.h +++ b/include/openmc/tallies/filter.h @@ -31,6 +31,7 @@ enum class FilterType { ENERGY_OUT, LEGENDRE, MATERIAL, + MATERIALFROM, MESH, MESH_SURFACE, MU, diff --git a/include/openmc/tallies/filter_material.h b/include/openmc/tallies/filter_material.h index 5da556d5e..aa5df5b3a 100644 --- a/include/openmc/tallies/filter_material.h +++ b/include/openmc/tallies/filter_material.h @@ -46,7 +46,7 @@ public: void set_materials(gsl::span materials); -private: +protected: //---------------------------------------------------------------------------- // Data members diff --git a/include/openmc/tallies/filter_materialfrom.h b/include/openmc/tallies/filter_materialfrom.h new file mode 100644 index 000000000..52039852a --- /dev/null +++ b/include/openmc/tallies/filter_materialfrom.h @@ -0,0 +1,29 @@ +#ifndef OPENMC_TALLIES_FILTER_MATERIALFROM_H +#define OPENMC_TALLIES_FILTER_MATERIALFROM_H + +#include + +#include "openmc/tallies/filter_material.h" + +namespace openmc { + +//============================================================================== +//! Specifies which material particles exit when crossing a surface. +//============================================================================== + +class MaterialFromFilter : public MaterialFilter { +public: + //---------------------------------------------------------------------------- + // Methods + + std::string type_str() const override { return "materialfrom"; } + FilterType type() const override { return FilterType::MATERIALFROM; } + + void get_all_bins(const Particle& p, TallyEstimator estimator, + FilterMatch& match) const override; + + std::string text_label(int bin) const override; +}; + +} // namespace openmc +#endif // OPENMC_TALLIES_FILTER_MATERIALFROM_H diff --git a/openmc/filter.py b/openmc/filter.py index c9457ceeb..8eb81432f 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -22,7 +22,7 @@ from ._xml import get_text _FILTER_TYPES = ( 'universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', 'distribcell', 'delayedgroup', - 'energyfunction', 'cellfrom', 'legendre', 'spatiallegendre', + 'energyfunction', 'cellfrom', 'materialfrom', 'legendre', 'spatiallegendre', 'sphericalharmonics', 'zernike', 'zernikeradial', 'particle', 'cellinstance', 'collision', 'time' ) @@ -451,7 +451,7 @@ class UniverseFilter(WithIDFilter): Parameters ---------- bins : openmc.UniverseBase, int, or iterable thereof - The Universes to tally. Either openmc.UniverseBase objects or their + The Universes to tally. Either :class:`openmc.UniverseBase` objects or their Integral ID numbers can be used. filter_id : int Unique identifier for the filter @@ -475,7 +475,31 @@ class MaterialFilter(WithIDFilter): Parameters ---------- bins : openmc.Material, Integral, or iterable thereof - The Materials to tally. Either openmc.Material objects or their + The material(s) to tally. Either :class:`openmc.Material` objects or their + Integral ID numbers can be used. + filter_id : int + Unique identifier for the filter + + Attributes + ---------- + bins : Iterable of Integral + openmc.Material IDs. + id : int + Unique identifier for the filter + num_bins : Integral + The number of filter bins + + """ + expected_type = Material + + +class MaterialFromFilter(WithIDFilter): + """Bins tally event locations based on the Material they occurred in. + + Parameters + ---------- + bins : openmc.Material, Integral, or iterable thereof + The material(s) to tally. Either :class:`openmc.Material` objects or their Integral ID numbers can be used. filter_id : int Unique identifier for the filter @@ -499,7 +523,7 @@ class CellFilter(WithIDFilter): Parameters ---------- bins : openmc.Cell, int, or iterable thereof - The cells to tally. Either openmc.Cell objects or their ID numbers can + The cells to tally. Either :class:`openmc.Cell` objects or their ID numbers can be used. filter_id : int Unique identifier for the filter diff --git a/openmc/lib/filter.py b/openmc/lib/filter.py index 8b175dd02..7c2e7e5c4 100644 --- a/openmc/lib/filter.py +++ b/openmc/lib/filter.py @@ -20,7 +20,7 @@ __all__ = [ 'Filter', 'AzimuthalFilter', 'CellFilter', 'CellbornFilter', 'CellfromFilter', 'CellInstanceFilter', 'CollisionFilter', 'DistribcellFilter', 'DelayedGroupFilter', 'EnergyFilter', 'EnergyoutFilter', 'EnergyFunctionFilter', 'LegendreFilter', - 'MaterialFilter', 'MeshFilter', 'MeshSurfaceFilter', 'MuFilter', 'ParticleFilter', + 'MaterialFilter', 'MaterialFromFilter', 'MeshFilter', 'MeshSurfaceFilter', 'MuFilter', 'ParticleFilter', 'PolarFilter', 'SphericalHarmonicsFilter', 'SpatialLegendreFilter', 'SurfaceFilter', 'UniverseFilter', 'ZernikeFilter', 'ZernikeRadialFilter', 'filters' ] @@ -342,6 +342,10 @@ class MaterialFilter(Filter): _dll.openmc_material_filter_set_bins(self._index, n, bins) +class MaterialFromFilter(Filter): + filter_type = 'materialfrom' + + class MeshFilter(Filter): filter_type = 'mesh' @@ -501,6 +505,7 @@ _FILTER_TYPE_MAP = { 'energyfunction': EnergyFunctionFilter, 'legendre': LegendreFilter, 'material': MaterialFilter, + 'materialfrom': MaterialFromFilter, 'mesh': MeshFilter, 'meshsurface': MeshSurfaceFilter, 'mu': MuFilter, diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index d8efd590f..5fae4cf60 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -21,6 +21,7 @@ #include "openmc/tallies/filter_energyfunc.h" #include "openmc/tallies/filter_legendre.h" #include "openmc/tallies/filter_material.h" +#include "openmc/tallies/filter_materialfrom.h" #include "openmc/tallies/filter_mesh.h" #include "openmc/tallies/filter_meshsurface.h" #include "openmc/tallies/filter_mu.h" @@ -121,6 +122,8 @@ Filter* Filter::create(const std::string& type, int32_t id) return Filter::create(id); } else if (type == "material") { return Filter::create(id); + } else if (type == "materialfrom") { + return Filter::create(id); } else if (type == "mesh") { return Filter::create(id); } else if (type == "meshsurface") { diff --git a/src/tallies/filter_materialfrom.cpp b/src/tallies/filter_materialfrom.cpp new file mode 100644 index 000000000..91f03aef8 --- /dev/null +++ b/src/tallies/filter_materialfrom.cpp @@ -0,0 +1,24 @@ +#include "openmc/tallies/filter_materialfrom.h" + +#include "openmc/cell.h" +#include "openmc/material.h" + +namespace openmc { + +void MaterialFromFilter::get_all_bins( + const Particle& p, TallyEstimator estimator, FilterMatch& match) const +{ + auto search = map_.find(p.material_last()); + if (search != map_.end()) { + match.bins_.push_back(search->second); + match.weights_.push_back(1.0); + } +} + +std::string MaterialFromFilter::text_label(int bin) const +{ + return "Material from " + + std::to_string(model::materials[materials_[bin]]->id_); +} + +} // namespace openmc diff --git a/tests/regression_tests/surface_tally/inputs_true.dat b/tests/regression_tests/surface_tally/inputs_true.dat index dc65e2a15..abd01266d 100644 --- a/tests/regression_tests/surface_tally/inputs_true.dat +++ b/tests/regression_tests/surface_tally/inputs_true.dat @@ -54,7 +54,7 @@ 1 - + 2 diff --git a/tests/regression_tests/surface_tally/test.py b/tests/regression_tests/surface_tally/test.py index 1224ebbb9..8968db9b6 100644 --- a/tests/regression_tests/surface_tally/test.py +++ b/tests/regression_tests/surface_tally/test.py @@ -106,19 +106,19 @@ class SurfaceTallyTestHarness(PyAPITestHarness): # Create partial current tallies from water to fuel # Filters - cell_from_filter = openmc.CellFromFilter(water) + mat_from_filter = openmc.MaterialFromFilter(borated_water) cell_filter = openmc.CellFilter(fuel) # Cell to cell filters for partial current cell_to_cell_tally = openmc.Tally(name=str('water_to_fuel_1')) - cell_to_cell_tally.filters = [cell_from_filter, cell_filter, \ + cell_to_cell_tally.filters = [mat_from_filter, cell_filter, \ energy_filter, polar_filter, azimuthal_filter] cell_to_cell_tally.scores = ['current'] tallies_file.append(cell_to_cell_tally) # Cell from + surface filters for partial current cell_to_cell_tally = openmc.Tally(name=str('water_to_fuel_2')) - cell_to_cell_tally.filters = [cell_from_filter, surface_filter, \ + cell_to_cell_tally.filters = [mat_from_filter, surface_filter, \ energy_filter, polar_filter, azimuthal_filter] cell_to_cell_tally.scores = ['current'] tallies_file.append(cell_to_cell_tally)