Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions openmc/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,10 @@ def set_density(self, units: str, density: float | None = None):
self._density = density

def add_nuclide(self, nuclide: str, percent: float, percent_type: str = 'ao'):
"""Add a nuclide to the material
"""Add a nuclide to the material.

If nuclide with the same name and percent_type already exists in the
material, its percentage will be updated.

Parameters
----------
Expand Down Expand Up @@ -559,7 +562,24 @@ def add_nuclide(self, nuclide: str, percent: float, percent_type: str = 'ao'):
if Z >= 89:
self.depletable = True

self._nuclides.append(NuclideTuple(nuclide, percent, percent_type))
# Flag to mark if we squashed the nuclide with an existing one
squashed = False

for i, nt in enumerate(self._nuclides):
if nt.name == nuclide and nt.percent_type == percent_type:
# add the percentage the two matching nuclides
self._nuclides[i] = NuclideTuple(nuclide, nt.percent + percent, percent_type)
squashed = True
break
elif nt.name == nuclide and nt.percent_type != percent_type:
warnings.warn(
f"Nuclide '{nuclide}' already present with percent_type "
f"'{nt.percent_type}'. Keeping separate entry for "
f"new percent_type '{percent_type}'."
)

if not squashed:
self._nuclides.append(NuclideTuple(nuclide, percent, percent_type))

def add_components(self, components: dict, percent_type: str = 'ao'):
""" Add multiple elements or nuclides to a material
Expand Down
41 changes: 38 additions & 3 deletions tests/unit_tests/test_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,19 @@ def test_nuclides_to_ignore(run_in_tmpdir):
def test_remove_nuclide():
"""Test removing nuclides."""
m = openmc.Material()
for nuc, percent in [('H1', 1.0), ('H2', 1.0), ('H1', 2.0), ('H2', 2.0)]:
m.add_nuclide(nuc, percent)
for nuc, percent, percent_type in [
('H1', 1.0, 'ao'),
('H2', 1.0, 'ao'),
('H1', 2.0, 'wo'),
('H2', 2.0, 'wo')
]:
m.add_nuclide(nuc, percent=percent, percent_type=percent_type)
m.remove_nuclide('H1')
assert len(m.nuclides) == 2
assert all(nuc.name == 'H2' for nuc in m.nuclides)
assert m.nuclides[0].percent == 1.0
assert m.nuclides[1].percent == 2.0


def test_remove_elements():
"""Test removing elements."""
m = openmc.Material()
Expand Down Expand Up @@ -766,3 +770,34 @@ def test_mean_free_path():
mat2.add_nuclide('Pb208', 1.0)
mat2.set_density('g/cm3', 11.34)
assert mat2.mean_free_path(energy=14e6) == pytest.approx(5.65, abs=1e-2)


def test_add_nuclide_squash_same_type():
mat1 = openmc.Material()
mat1.add_nuclide('Li6', 0.02, 'ao')
mat1.add_nuclide('Li6', 0.03, 'ao')
# Should be a single entry with 0.05 ao
entries = [nt for nt in mat1.nuclides if nt.name == 'Li6' and nt.percent_type == 'ao']
assert len(entries) == 1
assert entries[0].percent == pytest.approx(0.05)

mat2 = openmc.Material()
mat2.add_nuclide('Li6', 0.04, 'wo')
mat2.add_nuclide('Li6', 0.05, 'wo')
# Should be a single entry with 0.09 wo
entries = [nt for nt in mat2.nuclides if nt.name == 'Li6' and nt.percent_type == 'wo']
assert len(entries) == 1
assert entries[0].percent == pytest.approx(0.09)


def test_add_nuclide_keep_different_type_warns():
mat = openmc.Material()
mat.add_nuclide('Li6', 0.02, 'ao')
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
mat.add_nuclide('Li6', 0.01, 'wo')
assert any("Keeping separate entry" in str(rec.message) for rec in w)
# Should have two entries: one ao and one wo
aos = [nt for nt in mat.nuclides if nt.name == 'Li6' and nt.percent_type == 'ao']
wos = [nt for nt in mat.nuclides if nt.name == 'Li6' and nt.percent_type == 'wo']
assert len(aos) == 1 and len(wos) == 1
Loading