diff --git a/openmc/model/model.py b/openmc/model/model.py index d927b65ae64..e46fe743aad 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -2593,6 +2593,32 @@ def _isothermal_materialwise_mgxs( for mat in mgxs_lib.domains } + def _warn_material_wise_spectral_averaging(self) -> None: + """Warn when a material fills more than one cell. + + The "material_wise" method produces one flux-weighted cross section per + material, so a material spanning regions with different spectra (e.g. + steel near the source and deep inside a shield) is collapsed to a single + spectrum-averaged cross section. :meth:`Model.differentiate_mats` gives + each region its own material, and so its own cross section. + """ + counts = {} + for cell in self.geometry.get_all_material_cells().values(): + # A distribmat fill is a list that may contain None for void. + fills = cell.fill if cell.fill_type == 'distribmat' else [cell.fill] + for mat in fills: + if mat is not None: + counts[mat] = counts.get(mat, 0) + 1 + + if any(n > 1 for n in counts.values()): + warnings.warn( + "The 'material_wise' method produces one spectrum-averaged " + "cross section per material, but one or more materials fill " + "multiple cells and will be averaged over locations that may " + "have different spectra. Use Model.differentiate_mats() to " + "generate a separate cross section per location." + ) + def _generate_material_wise_mgxs( self, groups: openmc.mgxs.EnergyGroups, @@ -2635,6 +2661,8 @@ def _generate_material_wise_mgxs( Valid entries for temperature_settings are the same as the valid entries in openmc.Settings.temperature_settings. """ + self._warn_material_wise_spectral_averaging() + temp_settings = {} if temperature_settings is None: temp_settings = self.settings.temperature diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 9234b2d2721..3684ff1c100 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -999,6 +999,25 @@ def modify_radius(radius): assert result.total_batches > 0 +def test_convert_to_multigroup_material_wise_warns_for_shared_material(): + """material_wise generation warns when one material fills multiple cells, as + its cross section is then averaged over locations with possibly different + spectra.""" + steel = openmc.Material(name="steel") + steel.add_element("Fe", 1.0) + steel.set_density("g/cm3", 7.9) + + s1 = openmc.Sphere(r=1.0) + s2 = openmc.Sphere(r=2.0, boundary_type="vacuum") + # The same material object fills two separate cells (two "locations"). + c1 = openmc.Cell(fill=steel, region=-s1) + c2 = openmc.Cell(fill=steel, region=+s1 & -s2) + model = openmc.Model(openmc.Geometry([c1, c2]), openmc.Materials([steel])) + + with pytest.warns(UserWarning, match="differentiate_mats"): + model._warn_material_wise_spectral_averaging() + + def test_id_map_to_rgb(): """Test conversion of ID map to RGB image array.""" # Create a simple model