diff --git a/openmc/filter.py b/openmc/filter.py index 17678e026f..4d40117fe5 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1340,6 +1340,36 @@ 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, **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 : iterable of float + Array of numeric values, typically from a tally result + **kwargs + Keyword arguments passed to :class:`openmc.stats.Tabular` + + Returns + ------- + openmc.stats.Tabular + Tabular distribution with histogram interpolation + """ + + 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.values, probability_per_ev, **kwargs) + @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..0d34bfee3a 100644 --- a/tests/unit_tests/test_filters.py +++ b/tests/unit_tests/test_filters.py @@ -269,3 +269,23 @@ 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=[5, 10, 10]) + + 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, 0.0] + + # distribution should integrate to unity + assert tab.integral() == approx(1.0) + + # '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'