Adjust docpages to accomodate new transport-independent depletion

scheme.
This commit is contained in:
yardasol 2022-07-29 22:59:47 -05:00
parent 3e827530ba
commit ea1e2d02c4
3 changed files with 248 additions and 144 deletions

View file

@ -103,16 +103,16 @@ integrate over the entire timestep.
Our aim here is not to exhaustively describe all integration methods but rather
to give a few examples that elucidate the main considerations one must take into
account when choosing a method. Generally, there is a tradeoff between the
accuracy of the method and its computational expense. The expense is driven
almost entirely by the time to compute a transport solution, i.e., to evaluate
:math:`\mathbf{A}` for a given :math:`\mathbf{n}`. Thus, the cost of a method
scales with the number of :math:`\mathbf{A}` evaluations that are performed per
timestep. On the other hand, methods that require more evaluations generally
achieve higher accuracy. The predictor method only requires one evaluation and
its error converges as :math:`\mathcal{O}(h)`. The CE/CM method requires two
evaluations and is thus twice as expensive as the predictor method, but achieves
an error of :math:`\mathcal{O}(h^2)`. An exhaustive description of time
integration methods and their merits can be found in the `thesis of Colin Josey
accuracy of the method and its computational expense. In the case of
transport-coupled depletion, the expense is driven almost entirely by the time
to compute a transport solution, i.e., to evaluate :math:`\mathbf{A}` for a
given :math:`\mathbf{n}`. Thus, the cost of a method scales with the number of
:math:`\mathbf{A}` evaluations that are performed per timestep. On the other
hand, methods that require more evaluations generally achieve higher accuracy. The predictor method only requires one evaluation and its error converges as
:math:`\mathcal{O}(h)`. The CE/CM method requires two evaluations and is thus
twice as expensive as the predictor method, but achieves an error of
:math:`\mathcal{O}(h^2)`. An exhaustive description of time integration methods
and their merits can be found in the `thesis of Colin Josey
<http://dspace.mit.edu/handle/1721.1/7582>`_.
OpenMC does not rely on a single time integration method but rather has several
@ -169,12 +169,14 @@ Data Considerations
In principle, solving Eq. :eq:`depletion-matrix` using CRAM is fairly simple:
just construct the burnup matrix at various times and solve a set of sparse
linear systems. However, constructing the burnup matrix itself involves not only
solving the transport equation to estimate transmutation reaction rates but also
a series of choices about what data to include. In OpenMC, the burnup matrix is
constructed based on data inside of a *depletion chain* file, which includes
fundamental data gathered from ENDF incident neutron, decay, and fission product
yield sublibraries. For each nuclide, this file includes:
linear systems. However, constructing the burnup matrix itself involves not
only solving the transport equation to estimate transmutation reaction rates
(in the case of transport-coupled depletion) or to obtain microscopic cross
sections (in the case of transport-independent depletion), but also a series of
choices about what data to include. In OpenMC, the burnup matrix is constructed
based on data inside of a *depletion chain* file, which includes fundamental
data gathered from ENDF incident neutron, decay, and fission product yield
sublibraries. For each nuclide, this file includes:
- What transmutation reactions are possible, their Q values, and their products;
- If a nuclide is not stable, what decay modes are possible, their branching
@ -185,9 +187,12 @@ yield sublibraries. For each nuclide, this file includes:
Transmutation Reactions
-----------------------
OpenMC will setup tallies in a problem based on what transmutation reactions are
available in a depletion chain file, so any arbitrary number of transmutation
reactions can be tracked. The pregenerated chain files that are available on
In transport-coupled depletion, OpenMC will setup tallies in a problem based on
what transmutation reactions are available in a depletion chain file, so any
arbitrary number of transmutation reactions can be tracked. In
transport-independent depletion, OpenMC will calculate reaction rates for every
reaction that is present in both the available cross sections and the depletion
chain file. The pregenerated chain files that are available on
https://openmc.org include the following transmutation reactions: fission, (n,\
:math:`\gamma`\ ), (n,2n), (n,3n), (n,4n), (n,p), and (n,\ :math:`\alpha`\ ).
@ -202,11 +207,12 @@ accurately model the branching of the capture reaction in Am241. This is
complicated by the fact that the branching ratio may depend on the incident
neutron energy causing capture.
OpenMC does not currently allow energy-dependent capture branching ratios.
However, the depletion chain file does allow a transmutation reaction to be
listed multiple times with different branching ratios resulting in different
products. Spectrum-averaged capture branching ratios have been computed in LWR
and SFR spectra and are available at https://openmc.org/depletion-chains.
OpenMC's transport solver does not currently allow energy-dependent capture
branching ratios. However, the depletion chain file does allow a transmutation
reaction to be listed multiple times with different branching ratios resulting
in different products. Spectrum-averaged capture branching ratios have been
computed in LWR and SFR spectra and are available at
https://openmc.org/depletion-chains.
Fission Product Yields
----------------------
@ -217,26 +223,31 @@ energies. It is an open question as to what the best way to handle this energy
dependence is. OpenMC includes three methods for treating the energy dependence
of FPY:
1. Use FPY data corresponding to a specified energy.
1. Use FPY data corresponding to a specified energy. This is used by default in
both transport-coupled and transport-independent depletion.
2. Tally fission rates above and below a specified cutoff energy. Assume that
all fissions below the cutoff energy correspond to thermal FPY data and all
fission above the cutoff energy correspond to fast FPY data.
fission above the cutoff energy correspond to fast FPY data. Only applicable
to transport-coupled depletion.
3. Compute the average energy at which fission events occur and use an effective
FPY by linearly interpolating between FPY provided at neighboring energies.
Only applicable to transport-coupled depletion
The method can be selected through the ``fission_yield_mode`` argument to the
:class:`openmc.deplete.Operator` constructor.
The method for transport-coupled depletion can be selected through the
``fission_yield_mode`` argument to the :class:`openmc.deplete.Operator`
constructor.
Power Normalization
-------------------
The reaction rates provided OpenMC are given in units of reactions per source
particle. For depletion, it is necessary to compute an absolute reaction rate in
reactions per second. To do so, the reaction rates are normalized based on a
specified power. A complete description of how this normalization can be
performed is described in :ref:`usersguide_tally_normalization`. Here, we simply
note that the main depletion class, :class:`openmc.deplete.Operator`, allows the
user to choose one of two methods for estimating the heating rate, including:
In transport-coupled depletion, the reaction rates provided OpenMC are given in
units of reactions per source particle. For depletion, it is necessary to
compute an absolute reaction rate in reactions per second. To do so, the
reaction rates are normalized based on a specified power. A complete
description of how this normalization can be performed is described in
:ref:`usersguide_tally_normalization`. Here, we simply note that the main
depletion class, :class:`openmc.deplete.Operator`, allows the user to choose
one of two methods for estimating the heating rate, including:
1. Using fixed Q values from a depletion chain file (useful for comparisons to
other codes that use fixed Q values), or

View file

@ -12,19 +12,20 @@ Primary API
The two primary requirements to perform depletion with :mod:`openmc.deplete`
are:
1) A transport operator
1) A reaction rate operator
2) A time-integration scheme
The former is responsible for executing a transport code, like OpenMC,
and retaining important information required for depletion. The most common examples
are reaction rates and power normalization data. The latter is responsible for
projecting reaction rates and compositions forward in calendar time across
some step size :math:`\Delta t`, and obtaining new compositions given a power
or power density. The :class:`Operator` is provided to handle communicating with
OpenMC. Several classes are provided that implement different time-integration
algorithms for depletion calculations, which are described in detail in Colin
Josey's thesis, `Development and analysis of high order neutron
transport-depletion coupling algorithms <http://hdl.handle.net/1721.1/113721>`_.
The former is responsible for obtaining transmuation reaction rates. The latter
is responsible for projecting reaction rates and compositions forward in
calendar time across some step size :math:`\Delta t`, and obtaining new
compositions given a power or power density. The :class:`Operator` class is
provided to obtain reaction rates via tallies through OpenMC's transport
solver, and the :class:`IndependentOperator` class is provided to obtain
reaction rates from cross-section data. Several classes are provided that
implement different time-integration algorithms for depletion calculations,
which are described in detail in Colin Josey's thesis, `Development and
analysis of high order neutron transport-depletion coupling algorithms
<http://hdl.handle.net/1721.1/113721>`_.
.. autosummary::
:toctree: generated
@ -40,8 +41,8 @@ transport-depletion coupling algorithms <http://hdl.handle.net/1721.1/113721>`_.
SICELIIntegrator
SILEQIIntegrator
Each of these classes expects a "transport operator" to be passed. Operators
specific to OpenMC are available using the following classes:
Each of these classes expects a "reaction rate operator" to be passed. Operators
provided by OpenMC are available using the following classes:
.. autosummary::
:toctree: generated

View file

@ -4,23 +4,55 @@
Depletion and Transmutation
===========================
OpenMC supports coupled depletion, or burnup, calculations through the
:mod:`openmc.deplete` Python module. OpenMC solves the transport equation to
obtain transmutation reaction rates, and then the reaction rates are used to
solve a set of transmutation equations that determine the evolution of nuclide
densities within a material. The nuclide densities predicted as some future time
are then used to determine updated reaction rates, and the process is repeated
for as many timesteps as are requested.
OpenMC supports transport-coupled and transport-independent depletion, or
burnup, calculations through the :mod:`openmc.deplete` Python module. OpenMC
uses transmutation reaction rates to solve a set of transmutation equations
that determine the evolution of nuclide densities within a material. The
nuclide densities predicted as some future time are then used to determine
updated reaction rates, and the process is repeated for as many timesteps as
are requested.
The depletion module is designed such that the flux/reaction rate solution (the
transport "operator") is completely isolated from the solution of the
transmutation equations and the method used for advancing time. At present, the
:mod:`openmc.deplete` module offers a single transport operator,
:class:`openmc.deplete.Operator` (which uses the OpenMC transport solver), but
in principle additional operator classes based on other transport codes could be
implemented and no changes to the depletion solver itself would be needed. The
operator class requires a :class:`~openmc.Model` instance containing
material, geometry, and settings information::
The depletion module is designed such that the reaction rate solution (the
"operator") is completely isolated from the solution of the transmutation
equations and the method used for advancing time.
:mod:`openmc.deplete` supports multiple time-integration methods for determining
material compositions over time. Each method appears as a different class.
For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation
using the CE/CM algorithm (deplete over a timestep using the middle-of-step
reaction rates). An instance of :class:`~openmc.deplete.abc.TransportOperator`
is passed to one of these functions along with the timesteps and power level::
power = 1200.0e6 # watts
timesteps = [10.0, 10.0, 10.0] # days
openmc.deplete.CECMIntegrator(op, timesteps, power, timestep_units='d').integrate()
The depletion problem is executed, and once it is done a
``depletion_results.h5`` file is written. The results can be analyzed using the
:class:`openmc.deplete.Results` class. This class has methods that allow for
easy retrieval of k-effective, nuclide concentrations, and reaction rates over
time::
results = openmc.deplete.Results("depletion_results.h5")
time, keff = results.get_keff()
Note that the coupling between the reaction rate solver and the transmutation
solver happens in-memory rather than by reading/writing files on disk. OpenMC has two categories of
operators for obtaining transmutation reaction rates.
.. _coupled-depletion:
Transport-coupled depletion
===========================
This category of operator solves the transport equation to obtain transmutation
reaction rates. At present, the :mod:`openmc.deplete` module offers a single
transport-coupled operator, :class:`openmc.deplete.Operator` (which uses the
OpenMC transport solver), but in principle additional transport-coupled operator
classes based on other transport codes could be implemented and no changes to
the depletion solver itself would be needed. The
:class:`openmc.deplete.Operator` class requires a :class:`~openmc.Model`
instance containing material, geometry, and settings information::
model = openmc.Model()
...
@ -30,36 +62,14 @@ material, geometry, and settings information::
Any material that contains a fissionable nuclide is depleted by default, but
this can behavior can be changed with the :attr:`Material.depletable` attribute.
.. important:: The volume must be specified for each material that is depleted by
setting the :attr:`Material.volume` attribute. This is necessary
in order to calculate the proper normalization of tally results
based on the source rate.
:mod:`openmc.deplete` supports multiple time-integration methods for determining
material compositions over time. Each method appears as a different class.
For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation
using the CE/CM algorithm (deplete over a timestep using the middle-of-step
reaction rates). An instance of :class:`openmc.deplete.Operator` is passed to
one of these functions along with the timesteps and power level::
power = 1200.0e6 # watts
timesteps = [10.0, 10.0, 10.0] # days
openmc.deplete.CECMIntegrator(op, timesteps, power, timestep_units='d').integrate()
The coupled transport-depletion problem is executed, and once it is done a
``depletion_results.h5`` file is written. The results can be analyzed using the
:class:`openmc.deplete.Results` class. This class has methods that allow for
easy retrieval of k-effective, nuclide concentrations, and reaction rates over
time::
results = openmc.deplete.Results("depletion_results.h5")
time, keff = results.get_keff()
Note that the coupling between the transport solver and the transmutation solver
happens in-memory rather than by reading/writing files on disk.
.. important::
The volume must be specified for each material that is depleted by setting
the :attr:`Material.volume` attribute. This is necessary in order to
calculate the proper normalization of tally results based on the source rate.
Fixed-Source Transmutation
==========================
--------------------------
When the ``power`` or ``power_density`` argument is used for one of the
Integrator classes, it is assumed that OpenMC is running in k-eigenvalue mode,
@ -91,10 +101,12 @@ timestep in the calculation. A zero source rate for a given timestep will result
in a decay-only step, where all reaction rates are zero.
Caveats
=======
-------
.. _energy-deposition:
Energy Deposition
-----------------
~~~~~~~~~~~~~~~~~
The default energy deposition mode, ``"fission-q"``, instructs the
:class:`~openmc.deplete.Operator` to normalize reaction rates using the product
@ -126,7 +138,7 @@ should be, including indirect components. Some examples are provided below::
A more complete way to model the energy deposition is to use the modified
heating reactions described in :ref:`methods_heating`. These values can be used
heating reactions described in :ref:`methods_heating`. These values can be used
to normalize reaction rates instead of using the fission reaction rates with::
op = openmc.deplete.Operator(model, "chain.xml",
@ -137,7 +149,7 @@ of :meth:`openmc.data.IncidentNeutron.from_njoy()`, and will eventually be bundl
into the distributed libraries.
Local Spectra and Repeated Materials
------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is not uncommon to explicitly create a single burnable material across many
locations. From a pure transport perspective, there is nothing wrong with
@ -184,42 +196,81 @@ Transport-independent depletion
.. note::
This feature is still under heavy development. API changes are
possible and likely in the near future.
This feature is still under heavy development and has yet to be verifed
code-to-code . API changes and feature additions are possible and likely in
the near future.
OpenMC supports running depletion calculations independent of the OpenMC
transport solver using the :class:`~openmc.deplete.IndependentOperator` class.
This class supports both constant-flux (``source-rate`` normalization) and
constant-power depletion (``fission-q`` normalization).
This category of operator uses pre-calculated one-group microscopic cross
sections to obtain transmutation reaction rates. OpenMC provides the
:class:`~openmc.deplete.IndependentOperator` for this method of calculation.
While the one-group microscopic cross sections can be calculated using a
transport solver, :class:`~openmc.deplete.IndependentOperator` is not directly
coupled to any transport solver. The
:class:`~openmc.deplete.IndependentOperator` class requires a
:class:`openmc.Materials` object, a :class:`~openmc.deplete.MicroXS` object,
and a path to a depletion chain file::
.. important::
# load in the microscopic cross sections
materials = openmc.Materials()
...
Make sure you set the correct parameter in the :class:`openmc.abc.Integrator`
class. Use the ``source_rates`` parameter when
``normalization_mode == source-rate``, and use ``power`` or ``power_density``
when ``normalization_mode == fission-q``.
micro_xs = openmc.deplete.MicroXS()
...
.. warning::
op = IndependentOperator(materials, micro_xs, chain_file)
The accuracy of results when using ``fission-q`` is entirely dependent on
your depletion chain. Make sure it has sufficient data to resolve the
dynamics of your particular scenario.
.. note::
:class:`~openmc.deplete.IndependentOperator` class uses one-group microscopic cross sections to calculate reaction
rates. Users can generate one-group microscopic cross sections using the
The same statements from :ref:`coupled-depletion` about which
materials are depleted and the requirement for depletable materials to have
a specified volume also apply here.
An alternate constructor,
:meth:`~openmc.deplete.IndependentOperator.from_nuclides`, accepts a volume and
dictionary of nuclide concentrations in place of the :class:`openmc.Materials`
object::
nuclides = {'U234': 8.92e18,
'U235': 9.98e20,
'U238': 2.22e22,
'U236': 4.57e18,
'O16': 4.64e22,
'O17': 1.76e19}
volume = 0.5
op = openmc.deplete.IndependentOperator.from_nuclides(volume,
nuclides,
micro_xs,
chain_file,
nuc_units='atom/cm3')
A user can then define an integrator class as they would for a coupled
transport-depletion calculation and follow the same steps from there.
.. note::
Ideally, one-group cross section data should be available for every
reaction in the depletion chain. If a nuclide that has a reaction
associated with it in the depletion chain is present in the `nuclides`
parameter but not the cross section data, that reaction will not be
simulated.
Generating Microscopic Cross Sections
-------------------------------------
Users can generate the one-group microscopic cross sections needed by
:class:`~openmc.deplete.IndependentOperator` using the
:class:`~openmc.deplete.MicroXS` class::
import openmc
from openmc.deplete import MicroXS
model = openmc.Model.from_xml()
micro_xs = MicroXS.from_model(model, model.materials[0])
micro_xs = openmc.deplete.MicroXS.from_model(model, model.materials[0])
micro_xs.to_csv(micro_xs_path)
:class:`~openmc.deplete.MicroXS` also includes functions to read in cross
section data directly from a ``.csv`` file or from data arrays::
The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a
:class:`~openmc.deplete.MicroXS` object with microscopic cross section data in
units of ``b``, which is what :class:`~openmc.deplete.IndependentOperator`
expects the units to be. The :class:`~openmc.deplete.MicroXS` class also includes functions to read in cross section data directly from a ``.csv`` file or from data arrays::
micro_xs = MicroXS.from_csv(micro_xs_path)
@ -230,32 +281,73 @@ section data directly from a ``.csv`` file or from data arrays::
[0.01, 0.5]])
micro_xs = MicroXS.from_array(nuclides, reactions, data)
:class:`~openmc.deplete.IndependentOperator` has two ways to initialize it:
the default constructor accepts an :class:`openmc.Materials` object and
one-group microscopic cross sections as a :class:`~openmc.deplete.MicroXS`
object, while the :meth:`~openmc.deplete.IndependentOperator.from_nuclides`
method accepts a volume and dictionary of nuclide concentrations in place of the
:class:`openmc.Materials` object in addition to the other parameters::
.. important ::
# load in the microscopic cross sections
op = IndependentOperator(materials, micro_xs, chain_file)
Both :meth:`~openmc.deplete.MicroXS.from_csv()` and
:meth:`~openmc.deplete.MicroXS.from_array()` assume the cross section values
provided are in barns by defualt, but have no way of verifying this. Make
sure your cross sections are in the correct units before passing to a
:class:`~openmc.deplete.IndependentOperator` object.
# alternate construtor
nuclides = {'U234': 8.92e18,
'U235': 9.98e20,
'U238': 2.22e22,
'U236': 4.57e18,
'O16': 4.64e22,
'O17': 1.76e19}
volume = 0.5
op = IndependentOperator.from_nuclides(volume, nuclides, micro_xs,
chain_file, nuc_units='atom/cm3')
Caveats
-------
A user can then define an integrator class as they would for a coupled
transport-depletion calculation and follow the same steps from there.
Reaction Rate Normalization
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note:: Ideally, one-group cross section data should be available for every
reaction in the depletion chain. If a nuclide that has a reaction
associated with it in the depletion chain is present in the `nuclides`
parameter but not the cross section data, that reaction will not be
simulated.
The :class:`~openmc.deplete.IndependentOperator` class supports two methods for
normalizing reaction rates:
.. important::
Make sure you set the correct parameter in the :class:`openmc.abc.Integrator`
class. Use the ``source_rates`` parameter when
``normalization_mode == source-rate``, and use ``power`` or ``power_density``
when ``normalization_mode == fission-q``.
1. ``soure-rate`` normalization, which assumes the ``source-rate`` provided by
the time integrator is a flux, and obtains the reaction rates by multiplying
the cross-sections by the ``source-rate``.
2. ``fission-q`` normalization, which assumes the ``source-rate`` provided by
the time integrator is a power, and obtains the reaction rates by computing a
value for the flux based on this power. The general equation for the flux is
.. math::
\phi = \frac{P}{V \cdot \sum_i (Q_i \cdot \Sigma^f_i \cdot \rho_i)}
where :math:`\sum_i` is the sum over all nuclides :math:`i`. This equation
makes the same assumptions and issues as discussed in
:ref:`energy-deposition`. Unfortunately, the proposed solution in that
section does not apply here since we are decoupled from transport code.
However, there is a method to converge to a more accurate value for flux by
using substeps during time integration.
`This paper <https://doi.org/10.1016/j.anucene.2016.05.031>`_ provides a
good discussion of this method. Hopefully such a method will be implemented
in OpenMC in the near future.
.. warning::
The accuracy of results when using ``fission-q`` is entirely dependent on
your depletion chain. Make sure it has sufficient data to resolve the
dynamics of your particular scenario.
Multiple Materials
~~~~~~~~~~~~~~~~~~
Running a depletion simulation with multiple materials using the
``source-rate`` normalization method treats each material as completely
separate with respect to reaction rates. This can be useful for running many
different cases of a particular scenario. However, running a depletion
simulation with multiple materials using the ``fission-q`` normalization method
treats each material as part of the same "reactor" due to how ``fission-q``
normalization conglomerates energy values from each material to a single value.
This behavior may change in the future.
Time integration
~~~~~~~~~~~~~~~~
The one-group microscopic cross sections passed to
:class:`openmc.deplete.IndependentOperator` are fixed values for the entire
depletion simulation. This implicit assumption may produce inaccurate results
for certain scenarios.