Skip to content

Commit

Permalink
Fixed and implemented material contains.
Browse files Browse the repository at this point in the history
  • Loading branch information
MicahGale committed Nov 27, 2024
1 parent 85c9c51 commit 426a7f9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
51 changes: 39 additions & 12 deletions montepy/data_inputs/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,12 +682,16 @@ def contains(
if mat.contains("U-235", "U-233", "Pu-239", threshold=1e-6):
pass
# try to find a uranium
for mat in problem.materials:
if mat.contains("U"):
pass
.. note::
If a nuclide is in a material multiple times, and cumulatively exceeds the threshold,
but for each instance it appears it is below the threshold this method will return False.
:param nuclide: the first nuclide to check for.
:type nuclide: Union[Nuclide, Nucleus, Element, str, int]
:param args: a plurality of other nuclides to check for.
Expand All @@ -704,14 +708,19 @@ def contains(
"""
nuclides = []
for nuclide in [nuclide] + args:
for nuclide in [nuclide] + list(args):
if not isinstance(nuclide, (str, int, Element, Nucleus, Nuclide)):
raise TypeError(
f"Nuclide must be a type that can be converted to a Nuclide. The allowed types are: "
f"Nuclide, Nucleus, str, int. {nuclide} given."
)
if isinstance(nuclide, (str, int)):
nuclide = montepy.Nuclide(nuclide)
nuclide = Nuclide(nuclide)
# treat elemental as element
if isinstance(nuclide, (Nucleus, Nuclide)) and nuclide.A == 0:
nuclide = nuclide.element
if isinstance(nuclide, Nuclide) and not str(nuclide.library):
nuclide = nuclide.nucleus
nuclides.append(nuclide)

if not isinstance(threshold, float):
Expand All @@ -723,18 +732,36 @@ def contains(

# fail fast
for nuclide in nuclides:
if isinstance(nuclide, (Nucleus, Element)):
if nuclide not in self:
return False
if nuclide not in self:
return False

# do exhaustive search
nuclides_search = {str(nuclide): False for nuclide in nuclides}
nuclides_search = {}
nuclei_search = {}
element_search = {}
for nuclide in nuclides:
if isinstance(nuclide, Element):
element_search[nuclide] = False
if isinstance(nuclide, Nucleus):
nuclei_search[nuclide] = False
if isinstance(nuclide, Nuclide):
nuclides_search[str(nuclide).lower()] = False

for nuclide, fraction in self:
if str(nuclide) in nuclides_search:
if fraction >= threshold:
nuclides_search[str(nuclide)] = True
return all(nuclide_search)
if fraction < threshold:
continue
if str(nuclide).lower() in nuclides_search:
nuclides_search[str(nuclide).lower()] = True
if nuclide.nucleus in nuclei_search:
nuclei_search[nuclide.nucleus] = True
if nuclide.element in element_search:
element_search[nuclide.element] = True
return all(
(
all(nuclides_search.values()),
all(nuclei_search.values()),
all(element_search.values()),
)
)

def normalize(self):
"""
Expand Down
19 changes: 19 additions & 0 deletions tests/test_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,28 @@ def test_material_append_bad(_):
)
def test_material_contains(_, big_material, content, is_in):
assert is_in == (content in big_material), "Contains didn't work properly"
assert is_in == big_material.contains(content)
with pytest.raises(TypeError):
5 in big_material

def test_material_multi_contains(_, big_material):
assert big_material.contains("1001", "U-235", "Pu-239", threshold=0.01)
assert not big_material.contains("1001", "U-235", "Pu-239", threshold=0.07)
assert not big_material.contains("U-235", "B-10")

def test_material_contains_bad(_):
mat = Material()
with pytest.raises(TypeError):
mat.contains(mat)
with pytest.raises(TypeError):
mat.contains("1001", mat)
with pytest.raises(ValueError):
mat.contains("hi")
with pytest.raises(TypeError):
mat.contains("1001", threshold="hi")
with pytest.raises(ValueError):
mat.contains("1001", threshold=-1.0)

def test_material_str(_):
in_str = "M20 1001.80c 0.5 8016.80c 0.4 94239.80c 0.1"
input_card = Input([in_str], BlockType.DATA)
Expand Down

0 comments on commit 426a7f9

Please sign in to comment.