- Change Operator attribute name for fission yield helper
- Use copy.deepcopy for constant_yields, fast_yields, and thermal_yields
- Change import location of openmc in tests
- Use bisect.bisect_left to find replacement fission yields on
FissionYieldCutoffHelper if thermal or fast energies not found
In an (n, alpha) reaction, the branching ratio for helium should
always be one, as it is produced for every reaction.
It is the branching ratio of the other targets that must be modified.
He4 is treated as a secondary particle for this case, and its
reaction is not modified nor removed from the parent.
Generalized method that allows the modification of branching
ratios for an arbitrary reaction. A similar replacement has been
made with the companion get_capture_branches -> get_branch_ratios.
Both of the new methods accept an additional reaction argument,
which defaults to "(n,gamma)", indicating what reaction to
modify/retrieve.
Also added a tolerance argument, defaults to 1e-5, for checking
the sum of user-supplied branching ratios. This tolerance is
used as 1 - tolerance < sum_br < 1 + tolerance. Additional
logic is included if the user has not specified the ground
state, which can be inferred. For this case, the lower end
is allowed to be less than 1 - tolerance, as the ground state will
have a branch ratio such the sum of ratios is unity.
Products are not checked for consistency, that is left up to the user.
tests/unit_test/test_deplete_chain.py has been modified with the
new notation, and also with a variety of calls with and without
the optional reaction argument. A minor test is added that modifies
(n,alpha) and (n,2n) reactions just to ensure that arbitrary reactions
can be used.
Minor changes:
* Internal variables changed to reflect the generality of the method
* Added documentation on what exceptions are raised in
set_branch_ratios
Related: openmc issue #1237
Renamed update_nuclides_from_operator -> update_tally_nuclides
to be more general.
The base method TalliedFissionYieldHelper.update_tally_nuclides will
raise an AttributeError if this method is called before the tallies
are generated. The inner logic for setting the tallied nuclides can
be streamlined given the assumption that the tally exists.
AveragedFissionYieldHelper.update_tally_nuclides has been improved
to set the nuclides for the weighted tally now. This was not captured
prior because the nuclides were copied over from the fission rate
tally during tally generation, prior to when nuclides were set.
If there are no nuclides with multiple sets of yields, then
the tallies needed for fission yields may or or may not exist.
Regardless, this means that using constant_yields is absolutely
appropriate and there is no need for unpacking on
FissionYieldCutoffHelper nor AveragedFissionYieldHelper.
The weighted_yields methods for these two classes simply return
the set of constant yields if this is the case.
Base class TalliedFissionYieldHelper and AveragedFissionYieldHelper
instances do not need to know the number of burnable materials,
and thus it is no longer a required input argument.
Changes propagated into the from_operator methods and
tests/unit_tests/test_deplete_fission_yields.py
Removed explicit TalliedFissionYieldHelper.from_operator
method as it is identical and now inherited from the
base FissionYieldHelper.from_operator method
Computes the effective fission yields for nuclides
with multiple sets of yields by
1) Tallying fission rate and energy-weighted fission rate
2) Determining average energy at which fission events occur
3) Interpolating [lin-lin] between adjacent fission yields based
on this average energy
Uses a second tally with an EnergyFunctionFilter to tally
E * sigma_f * phi.
Added unit tests with the proxy-style class that doesn't use the
C API to generate tallies but tests all other aspects of the
implementation. Tests cover three possible average energies
(below minimum supplied yield energy, above max supplied yield energy,
and between two)
The Operator uses fission_yield_mode="average" to select this helper.
The helper also has a from_operator class method.
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 object is used in unit testing the depletion schemes, where
the depletion matrix is pre-defined and there is no
need for fission yields. However, the depletion interface
expects the chain to have a fission_yields attribute.
If the fission yields are a single entry, then
itertools.repeat is used to apply the fission yields to all
burnable materials. Otherwise, check that the number of
fission yield libraries is equal to the number of materials
to be burned.
The user is allowed to pass a single dictionary of yields to be applied
to all materials. Otherwise, each element in the iterable
should correspond to a material ordered by the TransportOperator.
Sparse checking is performed on the supplied input.
Validation is possible, but could become a burden for potentially
many burnable materials representing a lengthy list of
nested dictionaries to dig through and validate.
TalliedFissionYieldHelper instances must be passed
the number of burnable materials at construction again.
To make things easier for the Operator, a from_operator
class method has been added to the FissionYieldHelper
and TalliedFissionYieldHelper abstract classes, as well
as more explicit versions on the ConstantFissionYieldHelper
and FissionYieldCutoffHelper. All have the call signature
cls.from_operator(operator, **kwargs)
The concrete classes have explicitely declared what the
allowed key word arguments are, while the abstract classes
forward kwargs directly onto __init__.
All explicit keyword arguments should have a counterpart
in the __init__ method.
A single argument, fission_yield_mode, is used to determine
what type of FissionYield to use on the Operator. The options
are
* "constant": ConstantFissionYieldHelper [default]
* "cutoff": FissionYieldCutoffHelper
An additional argument, fission_yield_opts, can be supplied
as a dictionary of keyword arguments to pass to the new
helper. This allows the user to have control over how
the private helper is created.
This helper performs the following tasks to weight fission yields:
1) Determine a set of "fast" and "thermal" yields
based on a user specified cutoff energy,
2) Tally fission rates above and below the cutoff, and
3) Compute the effective yield by weighting the fast and
thermal yields by the fraction of fast and thermal fissions
for all nuclides in all burnable materials.
The user is allowed to specify the cutoff energy and energies
preferred for the fast and thermal yields. By default, the
cutoff is 112 eV, chosen as it is the logarithmic mean of
0.0253 eV and 500 keV. These two values are the default energies
for thermal and fast yields.
Tests are added to check for failure in constructing this
helper (thermal energy > cutoff, non-real values passed, etc.),
selection of yields given a range of user data, and
a proxy class that emulates a variety of thermal and fast splits
to check the eventual computed yield libraries.
Designed to be subclassed by helpers that aim to compute
effective fission yields with tallied data.
Constructs a tally in all burnable materials, scoring the
fission rate in all nuclides that have non-zero density
(as reported by the Operator) and have multiple sets of yields.
For nuclides with non-zero densities and a single set of
yields, those yields are assumed to be constant across incident
neutron energies.
The unpack method is now abstract, as each subclass should have
its own data layout, some with different energy structures
perhaps?? Maybe some weighting functions?
Given a requested energy, will take fission yields from that
energy on all nuclides and hold them as constant throughout
the simulation. If the requested energy is not found for a specific
nuclide, then the closest energy is used. The default is to
take the thermal 0.0253 eV yields.
This is now the helper attached to the Operator. The user can
select what energy of yields they would like to use.
API used by the Operator:
- generate_tallies
- weighted_yields [abstract]
- update_nuclides_from_operator
- unpack
generate_tallies and unpack are empty methods, provided
so that a consistent API can be found on helpers
with tallies.
Sorts nuclides into two dictionaries: those with a single
set of fission yields, and those with multiple sets.
The former can is exposed through the
constant_yields property, returning a copy of the fission
yield dictionary {parent: {product: yield}}
The Operator now looks for/uses the weighted_yields and
update_nuclides_from_operator methods instead of the old
compute_yields and set_fissionable_nuclides methods
Addition methods __add__ and __iadd__ expect the other
argument to a FissionYield object and will add
the yields from one to the other [in place for __iadd__].
Multiplication methods __imul__, __mul__, and __rmul__
expect the other argument to be a scalar and will scale
the fission yields by this value [in place for __imul__]
Also added a __repr__ method that returns a dictionary-like
representation
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.
Method Nuclide.validate traverses over decay mode and reaction lists,
as well as all fission yield data to check for inconsistencies.
The following checks are performed:
1) For all non-fission reactions and decay modes, do the sum of
branching ratios equal about 1?
2) For fission reactions, do the sum of fission yield
fractions equal about 2?
Users are allowed to supply three control arguments:
- strict: bool that controls if errors are raised [True] or
warnings [False]
- quiet: bool that controls if warnings are printed [False] or
supressed [True]
- tolerance: float that provides some wiggle room on the comparisons
``y - tol <= x <= y + tol``
The method returns a boolean if 1) no inconsistencies were found and
strict evaluates to True, 2) strict evaluates to False regardless of
quiet. If ``strict`` evaluates to False and ``quiet``
evaluates to True, the method will return at the first inconsistency.
No type checking is done because this will potentially be called
by ``openmc.deplete.Chain`` for many nuclides as the primary
entry point. Type and value checking will be done there.
A unit test was added that creates a valid nuclide, and then
strategically invalidates it to check for the various exceptions
and error messages.
Closes: #1307
This serves as a path way for production in I129 without
impacting transport because
1) Te129 has no ground state cross section data, due to
2) Te129 decays to I129 with a half life of about an hour
Running scripts/openmc-make-depletion-chain-casl now has the
following changes:
1) Te129 is present
2) Te129_m1 decays to Te129 with branching ratio of 2/3 using
ENDFB 7.1 data [pulled using tools/ci/download-xs.sh]
Previously the yields were appended into the libraries
attribute. Now, the yields are returned directly and not
appended at all. It is up to the caller to place these yields
in the correct location.
The Operator maintains a list of of the libraries that is updated
through the unpacking method, and then set onto the Chain
after working through all local materials