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

@ -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.