mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 22:26:08 -04:00
Merge branch 'develop' into reduced-absorption-xs
This commit is contained in:
commit
c5a5a3b9a6
48 changed files with 3426 additions and 1084 deletions
|
|
@ -103,16 +103,17 @@ 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 +170,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 +188,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 +208,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 +224,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.CoupledOperator`
|
||||
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.CoupledOperator`, 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
|
||||
|
|
@ -244,4 +256,4 @@ user to choose one of two methods for estimating the heating rate, including:
|
|||
energy-dependent estimate of the true heating rate.
|
||||
|
||||
The method for normalization can be chosen through the ``normalization_mode``
|
||||
argument to the :class:`openmc.deplete.Operator` class.
|
||||
argument to the :class:`openmc.deplete.CoupledOperator` class.
|
||||
|
|
|
|||
|
|
@ -61,11 +61,13 @@ Core Functions
|
|||
|
||||
atomic_mass
|
||||
atomic_weight
|
||||
combine_distributions
|
||||
decay_constant
|
||||
dose_coefficients
|
||||
gnd_name
|
||||
half_life
|
||||
isotopes
|
||||
kalbach_slope
|
||||
linearize
|
||||
thin
|
||||
water_density
|
||||
|
|
|
|||
|
|
@ -15,16 +15,18 @@ are:
|
|||
1) A transport 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 calculating 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:`CoupledOperator` 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,18 +42,20 @@ transport-depletion coupling algorithms <http://hdl.handle.net/1721.1/113721>`_.
|
|||
SICELIIntegrator
|
||||
SILEQIIntegrator
|
||||
|
||||
Each of these classes expects a "transport operator" to be passed. An operator
|
||||
specific to OpenMC is available using the following class:
|
||||
Each of these classes expects a "transport operator" to be passed. OpenMC
|
||||
provides The following classes implementing transpor operators:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: mycallable.rst
|
||||
|
||||
Operator
|
||||
CoupledOperator
|
||||
IndependentOperator
|
||||
|
||||
The :class:`Operator` must also have some knowledge of how nuclides transmute
|
||||
and decay. This is handled by the :class:`Chain`.
|
||||
The :class:`CoupledOperator` and :class:`IndependentOperator` classes must also
|
||||
have some knowledge of how nuclides transmute and decay. This is handled by the
|
||||
:class:`Chain`.
|
||||
|
||||
Minimal Example
|
||||
---------------
|
||||
|
|
@ -64,11 +68,12 @@ A minimal example for performing depletion would be:
|
|||
>>> import openmc.deplete
|
||||
>>> geometry = openmc.Geometry.from_xml()
|
||||
>>> settings = openmc.Settings.from_xml()
|
||||
>>> model = openmc.model.Model(geometry, settings)
|
||||
|
||||
# Representation of a depletion chain
|
||||
>>> chain_file = "chain_casl.xml"
|
||||
>>> operator = openmc.deplete.Operator(
|
||||
... geometry, settings, chain_file)
|
||||
>>> operator = openmc.deplete.CoupledOperator(
|
||||
... model, chain_file)
|
||||
|
||||
# Set up 5 time steps of one day each
|
||||
>>> dt = [24 * 60 * 60] * 5
|
||||
|
|
@ -131,6 +136,7 @@ data, such as number densities and reaction rates for each material.
|
|||
:template: myclass.rst
|
||||
|
||||
AtomNumber
|
||||
MicroXS
|
||||
OperatorResult
|
||||
ReactionRates
|
||||
Results
|
||||
|
|
@ -172,7 +178,7 @@ with :func:`cram.CRAM48` being the default.
|
|||
:class:`multiprocessing.pool.Pool` class. If set to ``None`` (default), the
|
||||
number returned by :func:`os.cpu_count` is used.
|
||||
|
||||
The following classes are used to help the :class:`openmc.deplete.Operator`
|
||||
The following classes are used to help the :class:`openmc.deplete.CoupledOperator`
|
||||
compute quantities like effective fission yields, reaction rates, and
|
||||
total system energy.
|
||||
|
||||
|
|
@ -189,14 +195,45 @@ total system energy.
|
|||
helpers.FissionYieldCutoffHelper
|
||||
helpers.FluxCollapseHelper
|
||||
|
||||
The :class:`openmc.deplete.IndependentOperator` uses inner classes subclassed
|
||||
from those listed above to perform similar calculations.
|
||||
|
||||
Intermediate Classes
|
||||
--------------------
|
||||
|
||||
Specific implementations of abstract base classes may utilize some of
|
||||
the same methods and data structures. These methods and data are stored
|
||||
in intermediate classes.
|
||||
|
||||
Methods common to tally-based implementation of :class:`FissionYieldHelper`
|
||||
are stored in :class:`helpers.TalliedFissionYieldHelper`
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
helpers.TalliedFissionYieldHelper
|
||||
|
||||
Methods common to OpenMC-specific implementations of :class:`TransportOperator`
|
||||
are stored in :class:`openmc_operator.OpenMCOperator`
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: mycallable.rst
|
||||
|
||||
openmc_operator.OpenMCOperator
|
||||
|
||||
|
||||
Abstract Base Classes
|
||||
---------------------
|
||||
|
||||
A good starting point for extending capabilities in :mod:`openmc.deplete` is
|
||||
to examine the following abstract base classes. Custom classes can
|
||||
inherit from :class:`abc.TransportOperator` to implement alternative
|
||||
schemes for collecting reaction rates and other data from a transport code
|
||||
prior to depleting materials
|
||||
schemes for collecting reaction rates and other data prior to depleting
|
||||
materials
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
|
|
@ -206,7 +243,9 @@ prior to depleting materials
|
|||
abc.TransportOperator
|
||||
|
||||
The following classes are abstract classes used to pass information from
|
||||
OpenMC simulations back on to the :class:`abc.TransportOperator`
|
||||
transport simulations (in the case of transport-coupled depletion) or to
|
||||
simply calculate these quantities directly (in the case of
|
||||
transport-independent depletion) back on to the :class:`abc.TransportOperator`
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
|
|
@ -216,7 +255,6 @@ OpenMC simulations back on to the :class:`abc.TransportOperator`
|
|||
abc.NormalizationHelper
|
||||
abc.FissionYieldHelper
|
||||
abc.ReactionRateHelper
|
||||
abc.TalliedFissionYieldHelper
|
||||
|
||||
Custom integrators or depletion solvers can be developed by subclassing from
|
||||
the following abstract base classes:
|
||||
|
|
|
|||
|
|
@ -4,50 +4,30 @@
|
|||
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 at 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
|
||||
The depletion module is designed such that the 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.Geometry` instance and a
|
||||
:class:`openmc.Settings` instance::
|
||||
|
||||
geom = openmc.Geometry()
|
||||
settings = openmc.Settings()
|
||||
...
|
||||
|
||||
op = openmc.deplete.Operator(geom, settings)
|
||||
|
||||
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.
|
||||
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.Operator` is passed to
|
||||
one of these functions along with the timesteps and power level::
|
||||
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 coupled transport-depletion problem is executed, and once it is done a
|
||||
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
|
||||
|
|
@ -56,11 +36,41 @@ 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.
|
||||
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 transport 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.CoupledOperator` (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.CoupledOperator` class requires a :class:`~openmc.Model`
|
||||
instance containing material, geometry, and settings information::
|
||||
|
||||
model = openmc.Model()
|
||||
...
|
||||
|
||||
op = openmc.deplete.CoupledOperator(model)
|
||||
|
||||
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.
|
||||
|
||||
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,
|
||||
|
|
@ -77,11 +87,11 @@ using the :attr:`Material.depletable` attribute::
|
|||
mat = openmc.Material()
|
||||
mat.depletable = True
|
||||
|
||||
When constructing the :class:`~openmc.deplete.Operator`, you should indicate
|
||||
that normalization of tally results will be done based on the source rate rather
|
||||
than a power or power density::
|
||||
When constructing the :class:`~openmc.deplete.CoupledOperator`, you should
|
||||
indicate that normalization of tally results will be done based on the source
|
||||
rate rather than a power or power density::
|
||||
|
||||
op = openmc.deplete.Operator(geometry, settings, normalization_mode='source-rate')
|
||||
op = openmc.deplete.CoupledOperator(model, normalization_mode='source-rate')
|
||||
|
||||
Finally, when creating a depletion integrator, use the ``source_rates`` argument::
|
||||
|
||||
|
|
@ -92,19 +102,22 @@ 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
|
||||
of fission reaction rates and fission Q values taken from the depletion chain.
|
||||
This approach does not consider indirect contributions to energy deposition,
|
||||
such as neutron heating and energy from secondary photons. In doing this, the
|
||||
energy deposited during a transport calculation will be lower than expected.
|
||||
This causes the reaction rates to be over-adjusted to hit the user-specific
|
||||
power, or power density, leading to an over-depletion of burnable materials.
|
||||
:class:`~openmc.deplete.CoupledOperator` to normalize reaction rates using the
|
||||
product of fission reaction rates and fission Q values taken from the depletion
|
||||
chain. This approach does not consider indirect contributions to energy
|
||||
deposition, such as neutron heating and energy from secondary photons. In doing
|
||||
this, the energy deposited during a transport calculation will be lower than
|
||||
expected. This causes the reaction rates to be over-adjusted to hit the
|
||||
user-specific power, or power density, leading to an over-depletion of burnable
|
||||
materials.
|
||||
|
||||
There are some remedies. First, the fission Q values can be directly set in a
|
||||
variety of ways. This requires knowing what the total fission energy release
|
||||
|
|
@ -113,29 +126,32 @@ should be, including indirect components. Some examples are provided below::
|
|||
# use a dictionary of fission_q values
|
||||
fission_q = {"U235": 202e+6} # energy in eV
|
||||
|
||||
# create a Model object
|
||||
model = openmc.Model(geometry, settings)
|
||||
|
||||
# create a modified chain and write it to a new file
|
||||
chain = openmc.deplete.Chain.from_xml("chain.xml", fission_q)
|
||||
chain.export_to_xml("chain_mod_q.xml")
|
||||
op = openmc.deplete.Operator(geometry, setting, "chain_mod_q.xml")
|
||||
op = openmc.deplete.CoupledOperator(model, "chain_mod_q.xml")
|
||||
|
||||
# alternatively, pass the modified fission Q directly to the operator
|
||||
op = openmc.deplete.Operator(geometry, setting, "chain.xml",
|
||||
op = openmc.deplete.CoupledOperator(model, "chain.xml",
|
||||
fission_q=fission_q)
|
||||
|
||||
|
||||
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(geometry, settings, "chain.xml",
|
||||
op = openmc.deplete.CoupledOperator(model, "chain.xml",
|
||||
normalization_mode="energy-deposition")
|
||||
|
||||
These modified heating libraries can be generated by running the latest version
|
||||
of :meth:`openmc.data.IncidentNeutron.from_njoy`, and will eventually be bundled
|
||||
of :meth:`openmc.data.IncidentNeutron.from_njoy()`, and will eventually be bundled
|
||||
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
|
||||
|
|
@ -160,7 +176,7 @@ the next transport step.
|
|||
This can be countered by instructing the operator to treat repeated instances
|
||||
of the same material as a unique material definition with::
|
||||
|
||||
op = openmc.deplete.Operator(geometry, settings, chain_file,
|
||||
op = openmc.deplete.CoupledOperator(model, chain_file,
|
||||
diff_burnable_mats=True)
|
||||
|
||||
For our example problem, this would deplete fuel on the outer region of the
|
||||
|
|
@ -177,3 +193,164 @@ across all material instances.
|
|||
This will increase the total memory usage and run time due to an increased
|
||||
number of tallies and material definitions.
|
||||
|
||||
Transport-independent depletion
|
||||
===============================
|
||||
|
||||
.. warning::
|
||||
|
||||
This feature is still under heavy development and has yet to be rigorously
|
||||
verified. API changes and feature additions are possible and likely in
|
||||
the near future.
|
||||
|
||||
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::
|
||||
|
||||
# load in the microscopic cross sections
|
||||
materials = openmc.Materials()
|
||||
...
|
||||
|
||||
micro_xs = openmc.deplete.MicroXS.from_csv(micro_xs_path)
|
||||
op = openmc.deplete.IndependentOperator(materials, micro_xs, chain_file)
|
||||
|
||||
.. note::
|
||||
|
||||
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
|
||||
|
||||
model = openmc.Model.from_xml()
|
||||
|
||||
micro_xs = openmc.deplete.MicroXS.from_model(model,
|
||||
model.materials[0],
|
||||
chain_file)
|
||||
|
||||
The :meth:`~openmc.deplete.MicroXS.from_model()` method will produce a
|
||||
:class:`~openmc.deplete.MicroXS` object with microscopic cross section data in
|
||||
units of barns, 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)
|
||||
|
||||
nuclides = ['U234', 'U235', 'U238']
|
||||
reactions = ['fission', '(n,gamma)']
|
||||
data = np.array([[0.1, 0.2],
|
||||
[0.3, 0.4],
|
||||
[0.01, 0.5]])
|
||||
micro_xs = MicroXS.from_array(nuclides, reactions, data)
|
||||
|
||||
.. important::
|
||||
|
||||
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.
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
Reaction Rate Normalization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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. ``source-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 uses the ``power`` or ``power_density``
|
||||
provided by the time integrator to obtain 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.
|
||||
|
||||
.. 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 accumulates 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