Delegate Nuclide yield properties to FissionYieldDistribution

For consistency across the various fission yield helpers, the
Nuclide object now sets the yield data to always be a
FissionYieldDistribution or an empty dictionary.
Nuclide.yield_energies is now a property that returns the
energies from the FissionYieldDistribution.

When setting the yield_data, the Nuclide enforces the object
to be a Mapping instance. If the incoming yield_data is a
FissionYieldDistribution, no conversions are made. Otherwise,
a new distribution is created with the from_dict method.

The Chain.from_xml method now creates the yield_data for
nuclides using FissionYieldDistribution.from_dict

Changes were made to some unit tests that attempted to set
the yield_energies, which do not have a setter.
This commit is contained in:
Andrew Johnson 2019-08-14 16:09:41 -05:00
parent 0931b58269
commit f2fa86fd52
No known key found for this signature in database
GPG key ID: 253418E91B7F6FEB
5 changed files with 37 additions and 17 deletions

View file

@ -15,6 +15,7 @@ from warnings import warn
from openmc.checkvalue import check_type, check_less_than
from openmc.data import gnd_name, zam
from .nuclide import FissionYieldDistribution
# Try to use lxml if it is available. It preserves the order of attributes and
# provides a pretty-printer by default. If not available,
@ -276,11 +277,12 @@ class Chain(object):
fpy = fpy_data[parent]
if fpy.energies is not None:
nuclide.yield_energies = fpy.energies
yield_energies = fpy.energies
else:
nuclide.yield_energies = [0.0]
yield_energies = [0.0]
for E, table in zip(nuclide.yield_energies, fpy.independent):
yield_data = {}
for E, table in zip(yield_energies, fpy.independent):
yield_replace = 0.0
yields = defaultdict(float)
for product, y in table.items():
@ -294,10 +296,10 @@ class Chain(object):
if yield_replace > 0.0:
missing_fp.append((parent, E, yield_replace))
yield_data[E] = yields
nuclide.yield_data[E] = []
for k in sorted(yields, key=openmc.data.zam):
nuclide.yield_data[E].append((k, yields[k]))
nuclide.yield_data = (
FissionYieldDistribution.from_dict(yield_data))
# Display warnings
if missing_daughter:

View file

@ -86,10 +86,10 @@ class Nuclide(object):
reactions : list of openmc.deplete.ReactionTuple
Reaction information. Each element of the list is a named tuple with
attribute 'type', 'target', 'Q', and 'branching_ratio'.
yield_data : dict of float to :class:`openmc.deplete.FissionYieldDistribution`
yield_data : FissionYieldDistribution or None
Fission product yields at tabulated energies for this nuclide. Can be
treated as a nested dictionary ``{energy: {product: yield}}``
yield_energies : list of float
yield_energies : tuple of float or None
Energies at which fission product yields exist
"""
@ -107,8 +107,7 @@ class Nuclide(object):
self.reactions = []
# Neutron fission yields, if present
self.yield_data = {}
self.yield_energies = []
self._yield_data = None
@property
def n_decay_modes(self):
@ -118,6 +117,25 @@ class Nuclide(object):
def n_reaction_paths(self):
return len(self.reactions)
@property
def yield_data(self):
if self._yield_data is None:
return {}
return self._yield_data
@yield_data.setter
def yield_data(self, fission_yields):
check_type("fission_yields", fission_yields, Mapping)
if isinstance(fission_yields, FissionYieldDistribution):
self._yield_data = fission_yields
self._yield_data = FissionYieldDistribution.from_dict(fission_yields)
@property
def yield_energies(self):
if self._yield_data is None:
return None
return self.yield_data.energies
@classmethod
def from_xml(cls, element, fission_q=None):
"""Read nuclide from an XML element.
@ -173,7 +191,6 @@ class Nuclide(object):
fpy_elem = element.find('neutron_fission_yields')
if fpy_elem is not None:
nuc.yield_data = FissionYieldDistribution.from_xml_element(fpy_elem)
nuc.yield_energies = list(sorted(nuc.yield_data.keys()))
return nuc

View file

@ -129,7 +129,7 @@ def test_from_xml(simple_chain):
assert [r.branching_ratio for r in nuc.reactions] == [1.0, 0.7, 0.3]
# Yield tests
assert nuc.yield_energies == [0.0253]
assert nuc.yield_energies == (0.0253, )
assert list(nuc.yield_data) == [0.0253]
assert nuc.yield_data[0.0253].products == ("A", "B")
assert (nuc.yield_data[0.0253].yields == [0.0292737, 0.002566345]).all()
@ -163,7 +163,6 @@ def test_export_to_xml(run_in_tmpdir):
nuclide.ReactionTuple("(n,gamma)", "A", 0.0, 0.7),
nuclide.ReactionTuple("(n,gamma)", "B", 0.0, 0.3)
]
C.yield_energies = [0.0253]
C.yield_data = nuclide.FissionYieldDistribution.from_dict({
0.0253: {"A": 0.0292737, "B": 0.002566345}})

View file

@ -19,13 +19,11 @@ def nuclide_bundle():
1.40e7: {"Xe135": 4.54e-3, "Gd155": 5.83e-8}}
u235 = Nuclide()
u235.name = "U235"
u235.yield_energies = (0.0253, 5.0e5, 1.40e7)
u235.yield_data = FissionYieldDistribution.from_dict(u5yield_dict)
u8yield_dict = {5.00e5: {"Xe135": 1.12e-3, "Gd155": 1.32e-12}}
u238 = Nuclide()
u238.name = "U238"
u238.yield_energies = (5.00e5,)
u238.yield_data = FissionYieldDistribution.from_dict(u8yield_dict)
xe135 = Nuclide()

View file

@ -3,6 +3,7 @@
import xml.etree.ElementTree as ET
import numpy
import pytest
from openmc.deplete import nuclide
@ -73,8 +74,12 @@ def test_from_xml():
]
expected_yield_data = nuclide.FissionYieldDistribution.from_dict({
0.0253: {"Xe138": 0.0481413, "Zr100": 0.0497641, "Te134": 0.062155}})
assert u235.yield_energies == [0.0253]
assert u235.yield_data == expected_yield_data
# test accessing the yield energies through the FissionYieldDistribution
assert u235.yield_energies == (0.0253, )
assert u235.yield_energies is u235.yield_data.energies
with pytest.raises(AttributeError): # not settable
u235.yield_energies = [0.0253, 5e5]
def test_to_xml_element():
@ -91,7 +96,6 @@ def test_to_xml_element():
nuclide.ReactionTuple('fission', None, 2.0e8, 1.0),
nuclide.ReactionTuple('(n,gamma)', 'A', 0.0, 1.0)
]
C.yield_energies = [0.0253]
C.yield_data = nuclide.FissionYieldDistribution.from_dict(
{0.0253: {"A": 0.0292737, "B": 0.002566345}})
element = C.to_xml_element()