From a055de8b08b35f18cabf534f1a5228f9e4616c2f Mon Sep 17 00:00:00 2001 From: approx-infinity Date: Wed, 20 May 2026 21:47:30 +0600 Subject: [PATCH 1/2] Guard average_molar_mass when material has no nuclides --- openmc/material.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmc/material.py b/openmc/material.py index 86cc3d7939c..97f80e381b8 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -296,6 +296,8 @@ def average_molar_mass(self) -> float: mass += nuc.percent # Compute and return the molar mass + if moles == 0.0: + raise ValueError("Material has no nuclides; cannot compute molar mass") return mass / moles @property From 68ce4f6c0bbeb03e3440f9bb7ea95f5769c20ca8 Mon Sep 17 00:00:00 2001 From: approx-infinity Date: Wed, 20 May 2026 22:31:06 +0600 Subject: [PATCH 2/2] Validate materials depletion inputs --- openmc/material.py | 11 ++++++- tests/unit_tests/test_materials.py | 49 ++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/openmc/material.py b/openmc/material.py index 97f80e381b8..eded9c3faa6 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -2289,7 +2289,7 @@ def deplete( multigroup_fluxes: Sequence[Sequence[float]] Energy-dependent multigroup flux values, where each sublist corresponds to a specific material. Will be normalized so that it sums to 1. - energy_group_structures': Sequence[Sequence[float] | str] + energy_group_structures: Sequence[Sequence[float] | str] Energy group boundaries in [eV] or the name of the group structure. timesteps : iterable of float or iterable of tuple Array of timesteps. Note that values are not cumulative. The units are @@ -2324,6 +2324,11 @@ def deplete( for mat in self: mat.depletable = True + if len(multigroup_fluxes) != len(self): + raise ValueError("multigroup_fluxes length must match number of materials") + if len(energy_group_structures) != len(self): + raise ValueError("energy_group_structures length must match number of materials") + chain = _get_chain(chain_file) # Create MicroXS objects for all materials @@ -2334,6 +2339,10 @@ def deplete( for material, flux, energy in zip( self, multigroup_fluxes, energy_group_structures ): + if material.volume is None: + raise ValueError( + f"Material {material.id} has no volume; cannot deplete" + ) temperature = material.temperature or 293.6 micro_xs = openmc.deplete.MicroXS.from_multigroup_flux( energies=energy, diff --git a/tests/unit_tests/test_materials.py b/tests/unit_tests/test_materials.py index 5a382b777df..6620402fdcd 100644 --- a/tests/unit_tests/test_materials.py +++ b/tests/unit_tests/test_materials.py @@ -1,5 +1,7 @@ from pathlib import Path +import pytest + import openmc from openmc.deplete import Chain @@ -78,3 +80,50 @@ def test_export_duplicate_materials_to_xml(run_in_tmpdir): materials_in = openmc.Materials.from_xml("materials.xml") assert len(materials_in) == 2 + + +def test_materials_deplete_length_mismatch(): + mats = openmc.Materials([openmc.Material()]) + + with pytest.raises(ValueError, match="multigroup_fluxes length"): + mats.deplete( + multigroup_fluxes=[], + energy_group_structures=["VITAMIN-J-42"], + timesteps=[1.0], + source_rates=1.0, + ) + + with pytest.raises(ValueError, match="energy_group_structures length"): + mats.deplete( + multigroup_fluxes=[[1.0]], + energy_group_structures=[], + timesteps=[1.0], + source_rates=1.0, + ) + + +def test_materials_deplete_missing_volume(monkeypatch): + mat = openmc.Material() + mat.add_nuclide("Ni58", 1.0) + mat.set_density("g/cm3", 7.87) + + mats = openmc.Materials([mat]) + + class DummySession: + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + return False + + monkeypatch.setattr(openmc.lib, "TemporarySession", DummySession) + + chain = Path(__file__).parents[1] / "chain_ni.xml" + with pytest.raises(ValueError, match="has no volume"): + mats.deplete( + multigroup_fluxes=[[1.0]], + energy_group_structures=["VITAMIN-J-42"], + timesteps=[1.0], + source_rates=1.0, + chain_file=chain, + )