mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 05:35:49 -04:00
Add openmc.deplete.Chain.validate method
Closes #1308 by providing a way to validate the contents of the depletion chain. This method iterates over all the nuclides and calls their validation method with the same input arguments, (strict, quiet, and tolerance). For the case where strict == False, quiet == False, and a nuclide fails the validation, the method returns early rather than continuing to iterate over all other nuclides. Type and value checking are also done on the tolerance argument. Two tests were added to test_deplete_chain.py The more interesting test works with the simple chain and various manipulations to check the robustness of the method. The other just checks the type and value checking on tolerance.
This commit is contained in:
parent
ec7af8f376
commit
6da0b3ec57
3 changed files with 108 additions and 1 deletions
|
|
@ -10,9 +10,10 @@ import math
|
|||
import re
|
||||
from collections import OrderedDict, defaultdict
|
||||
from collections.abc import Mapping
|
||||
from numbers import Real
|
||||
from warnings import warn
|
||||
|
||||
from openmc.checkvalue import check_type, check_less_than
|
||||
from openmc.checkvalue import check_type, check_less_than, check_greater_than
|
||||
from openmc.data import gnd_name, zam
|
||||
|
||||
# Try to use lxml if it is available. It preserves the order of attributes and
|
||||
|
|
@ -613,3 +614,53 @@ class Chain(object):
|
|||
new_ratios[ground_tgt] = ground_br
|
||||
parent.reactions.append(ReactionTuple(
|
||||
"(n,gamma)", ground_tgt, capt_Q, ground_br))
|
||||
|
||||
def validate(self, strict=True, quiet=False, tolerance=1e-4):
|
||||
"""Search for possible inconsistencies
|
||||
|
||||
The following checks are performed for all nuclides present:
|
||||
|
||||
1) For all non-fission reactions, do the sum of branching
|
||||
ratios equal about 1?
|
||||
2) For fission reactions, do the sum of fission yield
|
||||
fractions equal about 2?
|
||||
|
||||
Parameters
|
||||
----------
|
||||
strict : bool, optional
|
||||
Raise exceptions at the first inconsistency if true.
|
||||
Otherwise mark a warning
|
||||
quiet : bool, optional
|
||||
Flag to supress warnings and return immediately at
|
||||
the first inconsistency. Used only if
|
||||
``strict`` does not evaluate to ``True``.
|
||||
tolerance : float, optional
|
||||
Absolute tolerance for comparisons. Used to compare computed
|
||||
value ``x`` to intended value ``y`` as::
|
||||
|
||||
valid = (y - tolerance <= x <= y + tolerance)
|
||||
Returns
|
||||
-------
|
||||
valid : bool
|
||||
True if no inconsistencies were found
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If ``strict`` evaluates to ``True`` and an inconistency was
|
||||
found
|
||||
|
||||
See Also
|
||||
--------
|
||||
openmc.deplete.Nuclide.validate
|
||||
"""
|
||||
check_type("tolerance", tolerance, Real)
|
||||
check_greater_than("tolerance", tolerance, 0.0, True)
|
||||
valid = True
|
||||
# Sort through nuclides by name
|
||||
for name in sorted(self.nuclide_dict):
|
||||
stat = self[name].validate(strict, quiet, tolerance)
|
||||
if quiet and not stat:
|
||||
return stat
|
||||
valid &= stat
|
||||
return valid
|
||||
|
|
|
|||
|
|
@ -260,6 +260,10 @@ class Nuclide(object):
|
|||
ValueError
|
||||
If ``strict`` evaluates to ``True`` and an inconistency was
|
||||
found
|
||||
|
||||
See Also
|
||||
--------
|
||||
openmc.deplete.Chain.validate
|
||||
"""
|
||||
|
||||
branch_getter = attrgetter("branching_ratio")
|
||||
|
|
|
|||
|
|
@ -329,3 +329,55 @@ def test_capture_branch_failures(simple_chain):
|
|||
br = {"C": {"A": 1.0, "B": 1.0}}
|
||||
with pytest.raises(ValueError, match="C ratios"):
|
||||
simple_chain.set_capture_branches(br)
|
||||
|
||||
|
||||
def test_validate(simple_chain):
|
||||
"""Test the validate method"""
|
||||
|
||||
# current chain is invalid
|
||||
# fission yields do not sum to 2.0
|
||||
with pytest.raises(ValueError, match="Nuclide C.*fission yields"):
|
||||
simple_chain.validate(strict=True, tolerance=0.0)
|
||||
|
||||
with pytest.warns(UserWarning) as record:
|
||||
assert not simple_chain.validate(strict=False, quiet=False, tolerance=0.0)
|
||||
assert not simple_chain.validate(strict=False, quiet=True, tolerance=0.0)
|
||||
assert len(record) == 1
|
||||
assert "Nuclide C" in record[0].message.args[0]
|
||||
|
||||
# Fix fission yields but keep to restore later
|
||||
old_yields = simple_chain["C"].yield_data
|
||||
simple_chain["C"].yield_data = {0.0253: [("A", 1.4), ("B", 0.6)]}
|
||||
|
||||
assert simple_chain.validate(strict=True, tolerance=0.0)
|
||||
with pytest.warns(None) as record:
|
||||
assert simple_chain.validate(strict=False, quiet=False, tolerance=0.0)
|
||||
assert len(record) == 0
|
||||
|
||||
# Mess up "earlier" nuclide's reactions
|
||||
decay_mode = simple_chain["A"].decay_modes.pop()
|
||||
|
||||
with pytest.raises(ValueError, match="Nuclide A.*decay mode"):
|
||||
simple_chain.validate(strict=True, tolerance=0.0)
|
||||
|
||||
# restore old fission yields
|
||||
simple_chain["C"].yield_data = old_yields
|
||||
|
||||
with pytest.warns(UserWarning) as record:
|
||||
assert not simple_chain.validate(strict=False, quiet=False, tolerance=0.0)
|
||||
assert len(record) == 2
|
||||
assert "Nuclide A" in record[0].message.args[0]
|
||||
assert "Nuclide C" in record[1].message.args[0]
|
||||
|
||||
# restore decay modes
|
||||
simple_chain["A"].decay_modes.append(decay_mode)
|
||||
|
||||
|
||||
def test_validate_inputs():
|
||||
c = Chain()
|
||||
|
||||
with pytest.raises(TypeError, match="tolerance"):
|
||||
c.validate(tolerance=None)
|
||||
|
||||
with pytest.raises(ValueError, match="tolerance"):
|
||||
c.validate(tolerance=-1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue