From 2c965ef7f810c1945cbe379852922bf0efe9832a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 11 Sep 2019 10:26:45 -0500 Subject: [PATCH] Use defaultdict(dict) when weighting fission yields The Chain.form_matrix method looks for information and fission yields for all isotopes with a fission reaction. However, the AveragedFissionYieldHelper and FissionYieldCutoffHelper are not guaranteed to return yields to all isotopes with fission reactions. Instead, the union on two sets of yields are returned: 1) yields from isotopes with a single set of fission yields 2) weighted yields computed for isotopes with both multiple sets of fission yields **and** non-zero densities. This later item can cause some isotopes that the Chain anticipates having fission yields, since they have a fission reaction, to not exist in the yields library. An isotope with multiple sets of yields but that is not physically present in the problem will not have reaction rates and also not have fission yields computed by these helpers. This will cause a KeyError during Chain.form_matrix when fission yields for these isotopes are requested. This commit changes the return type from weighted_yields on ConstantFissionYieldHelper, AveragedFissionYieldHelper, and FissionYieldCutoffHelper to be defaultdict(dict). This resolves the above issue by returning an "empty" set of yields for isotopes that potentially *should* have fission yields, but have zero density across the problem, and therefore do not have tallied reaction rates nor fission yields. Documentation for the changes to these classes have been updated --- openmc/deplete/abc.py | 22 ++++++++++++++-------- openmc/deplete/helpers.py | 29 ++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index fb638e5c21..3d4c93ac83 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -5,6 +5,7 @@ to run a full depletion simulation. """ from collections import namedtuple +from collections import defaultdict from collections.abc import Iterable import os from pathlib import Path @@ -376,14 +377,17 @@ class FissionYieldHelper(ABC): Attributes ---------- - constant_yields : dict of str to :class:`openmc.deplete.FissionYield` + constant_yields : collections.defaultdict Fission yields for all nuclides that only have one set of - fission yield data. Can be accessed as ``{parent: {product: yield}}`` + fission yield data. Dictionary of form ``{str: {str: float}}`` + representing yields for ``{parent: {product: yield}}``. Default + return object is an empty dictionary + """ def __init__(self, chain_nuclides): self._chain_nuclides = {} - self._constant_yields = {} + self._constant_yields = defaultdict(dict) # Get all nuclides with fission yield data for nuc in chain_nuclides: @@ -407,14 +411,16 @@ class FissionYieldHelper(ABC): Parameters ---------- local_mat_index : int - Index for material tracked on this process that - exists in :attr:`local_mat_index` and fits within - the first axis in :attr:`results` + Index for the material with requested fission yields. + Should correspond to the material represented in + ``mat_indexes[local_mat_index]`` during + :meth:`generate_tallies`. Returns ------- - library : dict - Dictionary of ``{parent: {product: fyield}}`` + library : collections.abc.Mapping + Dictionary-like object mapping ``{str: {str: float}``. + This reflects fission yields for ``{parent: {product: fyield}}``. """ @staticmethod diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 56644a3bba..f6e6bb04da 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -5,6 +5,7 @@ from copy import deepcopy from itertools import product from numbers import Real import bisect +from collections import defaultdict from numpy import dot, zeros, newaxis @@ -179,9 +180,11 @@ class ConstantFissionYieldHelper(FissionYieldHelper): Attributes ---------- - constant_yields : dict of str to :class:`openmc.deplete.FissionYield` + constant_yields : collections.defaultdict Fission yields for all nuclides that only have one set of - fission yield data. Can be accessed as ``{parent: {product: yield}}`` + fission yield data. Dictionary of form ``{str: {str: float}}`` + representing yields for ``{parent: {product: yield}}``. Default + return object is an empty dictionary energy : float Energy of fission yield libraries. """ @@ -237,7 +240,7 @@ class ConstantFissionYieldHelper(FissionYieldHelper): Returns ------- - library : dict + library : collections.defaultdict Dictionary of ``{parent: {product: fyield}}`` """ return self.constant_yields @@ -282,6 +285,11 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): fast_yields : dict Dictionary of the form ``{parent: {product: yield}}`` with fast yields + constant_yields : collections.defaultdict + Fission yields for all nuclides that only have one set of + fission yield data. Dictionary of form ``{str: {str: float}}`` + representing yields for ``{parent: {product: yield}}``. Default + return object is an empty dictionary results : numpy.ndarray Array of fission rate fractions with shape ``(n_mats, 2, n_nucs)``. ``results[:, 0]`` @@ -417,7 +425,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Returns ------- - library : dict + library : collections.defaultdict Dictionary of ``{parent: {product: fyield}}`` """ yields = self.constant_yields @@ -469,9 +477,11 @@ class AveragedFissionYieldHelper(TalliedFissionYieldHelper): Attributes ---------- - constant_yields : dict of str to :class:`openmc.deplete.FissionYield` + constant_yields : collections.defaultdict Fission yields for all nuclides that only have one set of - fission yield data. Can be accessed as ``{parent: {product: yield}}`` + fission yield data. Dictionary of form ``{str: {str: float}}`` + representing yields for ``{parent: {product: yield}}``. Default + return object is an empty dictionary results : None or numpy.ndarray If tallies have been generated and unpacked, then the array will have shape ``(n_mats, n_tnucs)``, where ``n_mats`` is the number @@ -569,12 +579,13 @@ class AveragedFissionYieldHelper(TalliedFissionYieldHelper): Returns ------- - library : dict - Dictionary of ``{parent: {product: fyield}}`` + library : collections.defaultdict + Dictionary of ``{parent: {product: fyield}}``. Default return + value is an empty dictionary """ if not self._tally_nucs: return self.constant_yields - mat_yields = {} + mat_yields = defaultdict(dict) average_energies = self.results[local_mat_index] for avg_e, nuc in zip(average_energies, self._tally_nucs): nuc_energies = nuc.yield_energies