From e9866b4d66d7896214d6b695b8a663a8c14c135c Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 31 Jan 2023 13:20:31 +0000 Subject: [PATCH 1/5] added get_tabular metho to energyfilters --- openmc/filter.py | 29 +++++++++++++++++++++++++++++ tests/unit_tests/test_filters.py | 17 +++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/openmc/filter.py b/openmc/filter.py index 99b0053515..1bb5f9b14f 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1332,6 +1332,35 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) + def get_tabular(self, values, interpolation='histogram'): + """Creates a openmc.stats.Tabular distribution using the EnergyFilter + bins and the provided values. Intended use is to help convert a + spectrum tally into a source energy. + + Parameters + ---------- + values : np.array + Array of numeric values, typically a tally.mean from a spectrum tally + interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'} + Indicate whether the density function is constant between tabulated + points or linearly-interpolated. Defaults to 'histogram'. + + Returns + ------- + openmc.stats.Tabular + Tabular distribution with histogram interpolation + """ + + probabilities = values / sum(values) + + probability_per_ev = probabilities / np.diff(self.bins).flatten() + + return openmc.stats.Tabular( + x=self.bins, + p=probability_per_ev, + interpolation=interpolation + ) + @property def lethargy_bin_width(self): """Calculates the base 10 log width of energy bins which is useful when diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 8a6f095ef7..485926f193 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -269,3 +269,20 @@ def test_energyfunc(): np.testing.assert_allclose(f.energy, new_f.energy) np.testing.assert_allclose(f.y, new_f.y) assert f.interpolation == new_f.interpolation + + +def test_tabular_from_energyfilter(): + efilter = openmc.EnergyFilter([0.0, 10.0, 20.0, 25.0]) + tab = efilter.get_tabular(values=np.array([5, 10, 10])) + + assert tab.x.tolist() == [[0.0, 10.0], [10.0, 20.0], [20.0, 25.0]] + + # combination of different values passed into get_tabular and different + # width energy bins results in a doubling value for each p value + assert tab.p.tolist() == [0.02, 0.04, 0.08] + + # 'histogram' is the default + assert tab.interpolation == 'histogram' + + tab = efilter.get_tabular(values=np.array([10, 10, 5]), interpolation='linear-linear') + assert tab.interpolation == 'linear-linear' From 8a5a5201063b2b6a29e56ab92c6c983cec98aac3 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 17:38:33 +0000 Subject: [PATCH 2/5] code review improvments from @paulromano Co-authored-by: Paul Romano --- openmc/filter.py | 31 +++++++++++++++---------------- tests/unit_tests/test_filters.py | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 1bb5f9b14f..e1c8611f91 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1332,18 +1332,19 @@ class EnergyFilter(RealFilter): cv.check_greater_than('filter value', v0, 0., equality=True) cv.check_greater_than('filter value', v1, 0., equality=True) - def get_tabular(self, values, interpolation='histogram'): - """Creates a openmc.stats.Tabular distribution using the EnergyFilter - bins and the provided values. Intended use is to help convert a - spectrum tally into a source energy. + def get_tabular(self, values, **kwargs): + """Create a tabulated distribution based on tally results with an energy filter + + This method provides an easy way to create a distribution in energy + (e.g., a source spectrum) based on tally results that were obtained from + using an :class:`~openmc.EnergyFilter`. Parameters ---------- - values : np.array - Array of numeric values, typically a tally.mean from a spectrum tally - interpolation : {'histogram', 'linear-linear', 'linear-log', 'log-linear', 'log-log'} - Indicate whether the density function is constant between tabulated - points or linearly-interpolated. Defaults to 'histogram'. + values : iterable of float + Array of numeric values, typically from a tally result + **kwargs + Keyword arguments passed to :class:`openmc.stats.Tabular` Returns ------- @@ -1351,15 +1352,13 @@ class EnergyFilter(RealFilter): Tabular distribution with histogram interpolation """ - probabilities = values / sum(values) + probabilities = np.array(values) + probabilities /= probabilities.sum() - probability_per_ev = probabilities / np.diff(self.bins).flatten() + probability_per_ev = probabilities / np.diff(self.values) - return openmc.stats.Tabular( - x=self.bins, - p=probability_per_ev, - interpolation=interpolation - ) + kwargs.setdefault('interpolation', 'histogram') + return openmc.stats.Tabular(self.bins, probability_per_ev, **kwargs) @property def lethargy_bin_width(self): diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index 485926f193..afe85cdde4 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -273,7 +273,7 @@ def test_energyfunc(): def test_tabular_from_energyfilter(): efilter = openmc.EnergyFilter([0.0, 10.0, 20.0, 25.0]) - tab = efilter.get_tabular(values=np.array([5, 10, 10])) + tab = efilter.get_tabular(values=[5, 10, 10]) assert tab.x.tolist() == [[0.0, 10.0], [10.0, 20.0], [20.0, 25.0]] From e6d8e3f4a74f1be2db6b22d11575c0951372090e Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 17:53:04 +0000 Subject: [PATCH 3/5] avoiding true divide erorr --- openmc/filter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index e1c8611f91..d646cc019e 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1352,8 +1352,7 @@ class EnergyFilter(RealFilter): Tabular distribution with histogram interpolation """ - probabilities = np.array(values) - probabilities /= probabilities.sum() + probabilities = np.array(values) / sum(values) probability_per_ev = probabilities / np.diff(self.values) From 853ef5ea49862f9c545948b4c8ecf18c3c228c41 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 19:51:46 +0000 Subject: [PATCH 4/5] 2nd round of review improvments from paulromano Co-authored-by: Paul Romano --- openmc/filter.py | 7 +++++-- tests/unit_tests/test_filters.py | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index d646cc019e..cb1b57ed03 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1352,12 +1352,15 @@ class EnergyFilter(RealFilter): Tabular distribution with histogram interpolation """ - probabilities = np.array(values) / sum(values) + probabilities = np.array(values, dtype=float) + probabilities /= probabilities.sum() + # Determine probability per eV, adding extra 0 at the end since it is a histogram probability_per_ev = probabilities / np.diff(self.values) + probability_per_ev = np.append(probability_per_ev, 0.0) kwargs.setdefault('interpolation', 'histogram') - return openmc.stats.Tabular(self.bins, probability_per_ev, **kwargs) + return openmc.stats.Tabular(self.values, probability_per_ev, **kwargs) @property def lethargy_bin_width(self): diff --git a/tests/unit_tests/test_filters.py b/tests/unit_tests/test_filters.py index afe85cdde4..d4f0edbf98 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -275,12 +275,15 @@ def test_tabular_from_energyfilter(): efilter = openmc.EnergyFilter([0.0, 10.0, 20.0, 25.0]) tab = efilter.get_tabular(values=[5, 10, 10]) - assert tab.x.tolist() == [[0.0, 10.0], [10.0, 20.0], [20.0, 25.0]] + assert tab.x.tolist() == [0.0, 10.0, 20.0, 25.0] # combination of different values passed into get_tabular and different # width energy bins results in a doubling value for each p value assert tab.p.tolist() == [0.02, 0.04, 0.08] + # distribution should integrate to unity + assert tab.integral() == approx(1.0) + # 'histogram' is the default assert tab.interpolation == 'histogram' From eaddf91b6538e58c079d9eaca6f558db344fd644 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 9 Feb 2023 21:19:11 +0000 Subject: [PATCH 5/5] Adding zero to end of test results 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 d4f0edbf98..0d34bfee3a 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -279,7 +279,7 @@ def test_tabular_from_energyfilter(): # combination of different values passed into get_tabular and different # width energy bins results in a doubling value for each p value - assert tab.p.tolist() == [0.02, 0.04, 0.08] + assert tab.p.tolist() == [0.02, 0.04, 0.08, 0.0] # distribution should integrate to unity assert tab.integral() == approx(1.0)