mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Adjust docpages to accomodate new transport-independent depletion
scheme.
This commit is contained in:
parent
3e827530ba
commit
ea1e2d02c4
3 changed files with 248 additions and 144 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue