mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Merge pull request #1545 from paulromano/doc-updates
Various updates in documentation
This commit is contained in:
commit
ac8b5e574f
27 changed files with 508 additions and 73 deletions
|
|
@ -255,6 +255,7 @@ napoleon_use_ivar = True
|
|||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3', None),
|
||||
'numpy': ('https://docs.scipy.org/doc/numpy/', None),
|
||||
'scipy': ('https://docs.scipy.org/doc/scipy/reference', None),
|
||||
'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None),
|
||||
'matplotlib': ('https://matplotlib.org/', None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -600,67 +600,6 @@ attributes/sub-elements:
|
|||
|
||||
*Default*: false
|
||||
|
||||
.. _custom_source:
|
||||
|
||||
Custom Sources
|
||||
++++++++++++++
|
||||
|
||||
It is often the case that one may wish to simulate a complex source
|
||||
distribution, which may include physics not present within OpenMC or to be phase
|
||||
space complex. It is possible to define a complex source with an externally
|
||||
defined source function that is loaded at runtime. A simple example source is
|
||||
shown below.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/source.h"
|
||||
#include "openmc/particle.h"
|
||||
|
||||
// you must have external C linkage here
|
||||
extern "C" openmc::Particle::Bank sample_source(uint64_t* seed) {
|
||||
openmc::Particle::Bank particle;
|
||||
// weight
|
||||
particle.particle = openmc::Particle::Type::neutron;
|
||||
particle.wgt = 1.0;
|
||||
// position
|
||||
double angle = 2.0 * M_PI * openmc::prn(seed);
|
||||
double radius = 3.0;
|
||||
particle.r.x = radius * std::cos(angle);
|
||||
particle.r.y = radius * std::sin(angle);
|
||||
particle.r.z = 0.0;
|
||||
// angle
|
||||
particle.u = {1.0, 0.0, 0.0};
|
||||
particle.E = 14.08e6;
|
||||
particle.delayed_group = 0;
|
||||
return particle;
|
||||
}
|
||||
|
||||
The above source, creates 14.08 MeV neutrons, with an istropic direction
|
||||
vector but distributed in a ring with a 3 cm radius. This routine is
|
||||
not particularly complex, but should serve as an example upon which to build
|
||||
more complicated sources.
|
||||
|
||||
.. note:: The function signature must be declared to be extern "C".
|
||||
|
||||
.. note:: You should only use the openmc::prn() random number generator
|
||||
|
||||
In order to build your external source, you will need to link it against the
|
||||
OpenMC shared library. This can be done by writing a CMakeLists.txt file:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
||||
project(openmc_sources CXX)
|
||||
add_library(source SHARED source_ring.cpp)
|
||||
find_package(OpenMC REQUIRED HINTS <path to openmc>)
|
||||
target_link_libraries(source OpenMC::libopenmc)
|
||||
|
||||
After running ``cmake`` and ``make``, you will have a libsource.so (or .dylib)
|
||||
file in your build directory. Setting the :attr:`openmc.Source.library`
|
||||
attribute to the path of this shared library will indicate that it should be
|
||||
used for sampling source particles at runtime.
|
||||
|
||||
.. _univariate:
|
||||
|
||||
Univariate Probability Distributions
|
||||
|
|
|
|||
248
docs/source/methods/depletion.rst
Normal file
248
docs/source/methods/depletion.rst
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
.. _methods_depletion:
|
||||
|
||||
=========
|
||||
Depletion
|
||||
=========
|
||||
|
||||
When materials in a system are subject to irradiation over a long period of
|
||||
time, nuclides within the material will transmute due to nuclear reactions as
|
||||
well as spontaneous radioactive decay. The time-dependent process by which
|
||||
nuclides transmute under irradiation is known as *depletion* or *burnup*. To
|
||||
accurately analyze nuclear systems, it is often necessary to predict how the
|
||||
composition of materials will change since this change results in a
|
||||
corresponding change in the solution of the transport equation. The equation
|
||||
that governs the transmutation and decay of nuclides inside of an irradiated
|
||||
environment can be written as
|
||||
|
||||
.. math::
|
||||
|
||||
\begin{aligned} \frac{dN_i(t)}{dt} = &\sum\limits_j
|
||||
\underbrace{\left [ \underbrace{f_{j \rightarrow i} \int_0^\infty dE \;
|
||||
\sigma_j (E, t) \phi(E,t)}_\text{transmutation} +
|
||||
\underbrace{\lambda_{j\rightarrow i}}_\text{decay} \right ]
|
||||
N_j(t)}_{\text{Production of nuclide }i\text{ from nuclide }j} \\
|
||||
&- \underbrace{\left [\underbrace{\int_0^\infty dE \; \sigma_i
|
||||
(E,t) \phi(E,t)}_\text{transmutation} +
|
||||
\underbrace{\sum\limits_j \lambda_{i\rightarrow j}}_\text{decay} \right ]
|
||||
N_i(t)}_{\text{Loss of nuclide }i} \end{aligned}
|
||||
|
||||
where :math:`N_i` is the density of nuclide :math:`i` at time :math:`t`,
|
||||
:math:`\sigma_i` is the transmutation cross section for nuclide :math:`i` at
|
||||
energy :math:`E`, :math:`f_{j \rightarrow i}` is the fraction of transmutation
|
||||
reactions in nuclide :math:`j` that produce nuclide :math:`i`, and
|
||||
:math:`\lambda_{j \rightarrow i}` is the decay constant for decay modes in
|
||||
nuclide :math:`j` that produce nuclide :math:`i`. Note that we have not included
|
||||
the spatial dependence of the flux or cross sections. As one can see, the
|
||||
equation simply states that the rate of change of :math:`N_i` is equal to the
|
||||
production rate minus the loss rate. Because the equation for nuclide :math:`i`
|
||||
depends on the nuclide density for possibly many other nuclides, we have a
|
||||
system of first-order differential equations. To form a proper initial value
|
||||
problem, we also need the nuclide densities at time 0:
|
||||
|
||||
.. math::
|
||||
|
||||
N_i(0) = N_{i,0}.
|
||||
|
||||
These equations can be written more compactly in matrix notation as
|
||||
|
||||
.. math::
|
||||
:label: depletion-matrix
|
||||
|
||||
\frac{d\mathbf{n}}{dt} = \mathbf{A}(\mathbf{n},t)\mathbf{n}, \quad \mathbf{n}(0) =
|
||||
\mathbf{n}_0
|
||||
|
||||
where :math:`\mathbf{n} \in \mathbb{R}^n` is the nuclide density vector,
|
||||
:math:`\mathbf{A}(\mathbf{n},t) \in \mathbb{R}^{n\times n}` is the burnup matrix
|
||||
containing the decay and transmutation coefficients, and :math:`\mathbf{n}_0` is
|
||||
the initial density vector. Note that the burnup matrix depends on
|
||||
:math:`\mathbf{n}` because the solution to the transport equation depends on the
|
||||
nuclide densities.
|
||||
|
||||
.. _methods_depletion_integration:
|
||||
|
||||
---------------------
|
||||
Numerical Integration
|
||||
---------------------
|
||||
|
||||
A variety of numerical methods exist for solving Eq. :eq:`depletion-matrix`. The
|
||||
simplest such method, known as the "predictor" method, is to divide the overall
|
||||
time interval of interest :math:`[0,t]` into smaller timesteps over which it is
|
||||
assumed that the burnup matrix is constant. Let :math:`t \in [t_i, t_i + h]` be
|
||||
one such timestep. Over the timestep, the solution to Eq. :eq:`depletion-matrix`
|
||||
can be written analytically using the matrix exponential
|
||||
|
||||
.. math::
|
||||
|
||||
\mathbf{A}_i = \mathbf{A}(\mathbf{n}_i, t_i) \\
|
||||
|
||||
\mathbf{n}_{i+1} = e^{\mathbf{A}_i h} \mathbf{n}_i
|
||||
|
||||
where :math:`\mathbf{n}_i \equiv \mathbf{n}(t_i)`. The exponential of a matrix
|
||||
:math:`\mathbf{X}` is defined by the power series expansion
|
||||
|
||||
.. math::
|
||||
|
||||
e^{\mathbf{X}} = \sum\limits_{k=0}^\infty \frac{1}{k!} \left ( \mathbf{X}
|
||||
\right )^k
|
||||
|
||||
where :math:`\mathbf{X}^0 = \mathbf{I}`. A series of so-called
|
||||
predictor-corrector methods that use multiple stages offer improved accuracy
|
||||
over the predictor method. The simplest of these methods, the CE/CM algorithm,
|
||||
is defined as
|
||||
|
||||
.. math::
|
||||
|
||||
\mathbf{n}_{i+1/2} = e^{\frac{h}{2}\mathbf{A}(\mathbf{n}_i, t_i)} \mathbf{n}_i \\
|
||||
\mathbf{n}_{i+1} = e^{h \mathbf{A}(\mathbf{n}_{i+1/2},t_{i+1/2})} \mathbf{n}_i
|
||||
|
||||
Here, the value of :math:`\mathbf{n}` at the midpoint is estimated using
|
||||
:math:`\mathbf{A}` evaluated at the beginning of the timestep. Then,
|
||||
:math:`\mathbf{A}` is evaluated using the densities at the midpoint and used to
|
||||
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
|
||||
<http://dspace.mit.edu/handle/1721.1/7582>`_.
|
||||
|
||||
OpenMC does not rely on a single time integration method but rather has several
|
||||
classes that implement different algorithms. For example, the
|
||||
:class:`openmc.deplete.PredictorIntegrator` class implements the predictor
|
||||
method, and the :class:`openmc.deplete.CECMIntegrator` class implements the
|
||||
CE/CM method. A full list of the integrator classes available can be found in
|
||||
the documentation for the :mod:`openmc.deplete` module.
|
||||
|
||||
------------------
|
||||
Matrix Exponential
|
||||
------------------
|
||||
|
||||
As we saw in the :ref:`previous section <methods_depletion_integration>`,
|
||||
numerically integrating Eq. :eq:`depletion-matrix` requires evaluating one or
|
||||
more matrix exponentials. OpenMC uses the Chebyshev rational approximation
|
||||
method (CRAM), which was introduced in a series of papers by Pusa (`1
|
||||
<https://doi.org/10.13182/NSE09-14>`_, `2
|
||||
<https://doi.org/10.13182/NSE10-81>`_), to evaluate matrix exponentials. In
|
||||
particular, OpenMC utilizes an `incomplete partial fraction <cram_ipf>`_ (IPF)
|
||||
form of CRAM that provides a good balance of numerical stability and efficiency.
|
||||
In this representation the matrix exponential is approximated as
|
||||
|
||||
.. math::
|
||||
|
||||
e^{\mathbf{A}t} \approx \alpha_0 \prod\limits_{\ell=1}^{k/2} \left (
|
||||
\mathbf{I} + 2 \text{Re} \left ( \widetilde{\alpha}_\ell \left (\mathbf{A}t
|
||||
- \theta_\ell \mathbf{I} \right )^{-1} \right ) \right )
|
||||
|
||||
where :math:`k` is the order of the approximation and :math:`\alpha_0`,
|
||||
:math:`\widetilde{\alpha}_\ell`, and :math:`\theta_\ell` are coefficients that
|
||||
have been tabulated for orders up to :math:`k=48`. Rather than computing the
|
||||
full approximation and then multiplying it by a vector, the following algorithm
|
||||
is used to incrementally apply the terms within the product (note that the
|
||||
original description of the algorithm presented by `Pusa <cram_ipf>`_ contains a
|
||||
typo):
|
||||
|
||||
1. :math:`\mathbf{n} \gets \mathbf{n_0}`
|
||||
2. For :math:`\ell = 1, 2, \dots, k/2`
|
||||
|
||||
- :math:`\mathbf{n} \gets \mathbf{n} + 2\text{Re}(\widetilde{\alpha}_\ell
|
||||
(\mathbf{A}t - \theta_\ell)^{-1})\mathbf{n}`
|
||||
|
||||
3. :math:`\mathbf{n} \gets \alpha_0 \mathbf{n}`
|
||||
|
||||
The :math:`k`\ th order approximation for CRAM requires solving :math:`k/2`
|
||||
sparse linear systems. OpenMC relies on functionality from
|
||||
:mod:`scipy.sparse.linalg` for solving the linear systems.
|
||||
|
||||
.. _cram_ipf: https://doi.org/10.13182/NSE15-26
|
||||
|
||||
-------------------
|
||||
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:
|
||||
|
||||
- What transmutation reactions are possible, their Q values, and their products;
|
||||
- If a nuclide is not stable, what decay modes are possible, their branching
|
||||
ratios, and their products; and
|
||||
- If a nuclide is fissionable, the fission products yields at any number of
|
||||
incident neutron energies.
|
||||
|
||||
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
|
||||
https://openmc.org include the following transmutation reactions: fission, (n,\
|
||||
:math:`\gamma`\ ), (n,2n), (n,3n), (n,4n), (n,p), and (n,\ :math:`\alpha`\ ).
|
||||
|
||||
Capture Branching Ratios
|
||||
------------------------
|
||||
|
||||
Some (n,\ :math:`\gamma`\ ) reactions may result in a product being in either the
|
||||
ground or a metastable state. The most well-known example is capture in Am241,
|
||||
which can produce either Am242 or Am242m. Because the metastable state of Am242m
|
||||
has a significantly longer half-life than the ground state, it is important to
|
||||
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.
|
||||
|
||||
Fission Product Yields
|
||||
----------------------
|
||||
|
||||
Fission product yields (FPY) are also energy-dependent in general. ENDF fission
|
||||
product yield sublibraries typically include yields tabulated at 2 or 3
|
||||
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.
|
||||
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.
|
||||
3. Compute the average energy at which fission events occur and use an effective
|
||||
FPY by linearly interpolating between FPY provided at neighboring energies.
|
||||
|
||||
The method 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:
|
||||
|
||||
1. Using fixed Q values from a depletion chain file (useful for comparisons to
|
||||
other codes that use fixed Q values), or
|
||||
2. Using the ``heating`` or ``heating-local`` scores to obtain an nuclide- and
|
||||
energy-dependent estimate of the true heating rate.
|
||||
|
||||
The method for normalization can be chosen through the ``energy_mode`` argument
|
||||
to the :class:`openmc.deplete.Operator` class.
|
||||
|
|
@ -16,6 +16,7 @@ Theory and Methodology
|
|||
photon_physics
|
||||
tallies
|
||||
eigenvalue
|
||||
depletion
|
||||
energy_deposition
|
||||
parallelization
|
||||
cmfd
|
||||
energy_deposition
|
||||
|
|
|
|||
|
|
@ -113,6 +113,19 @@ Boolean operators ``&`` (intersection), ``|`` (union), and ``~`` (complement)::
|
|||
>>> type(northern_hemisphere)
|
||||
<class 'openmc.region.Intersection'>
|
||||
|
||||
The ``&`` operator can be thought of as a logical AND, the ``|`` operator as a
|
||||
logical OR, and the ``~`` operator as a logical NOT. Thus, if you wanted to
|
||||
create a region that consists of the space for which :math:`-4 < z < -3` or
|
||||
:math:`3 < z < 4`, a union could be used::
|
||||
|
||||
>>> region_bottom = +openmc.ZPlane(-4) & -openmc.ZPlane(-3)
|
||||
>>> region_top = +openmc.ZPlane(3) & -openmc.ZPlane(4)
|
||||
>>> combined_region = region_bottom | region_top
|
||||
|
||||
Half-spaces and the objects resulting from taking the intersection, union,
|
||||
and/or complement or half-spaces are all considered *regions* that can be
|
||||
assigned to :ref:`cells <usersguide_cells>`.
|
||||
|
||||
For many regions, a bounding-box can be determined automatically::
|
||||
|
||||
>>> northern_hemisphere.bounding_box
|
||||
|
|
|
|||
|
|
@ -110,13 +110,24 @@ The spatial distribution can be set equal to a sub-class of
|
|||
:class:`openmc.stats.Spatial`; common choices are :class:`openmc.stats.Point` or
|
||||
:class:`openmc.stats.Box`. To independently specify distributions in the
|
||||
:math:`x`, :math:`y`, and :math:`z` coordinates, you can use
|
||||
:class:`openmc.stats.CartesianIndependent`.
|
||||
:class:`openmc.stats.CartesianIndependent`. To independently specify
|
||||
distributions using spherical or cylindrical coordinates, you can use
|
||||
:class:`openmc.stats.SphericalIndependent` or
|
||||
:class:`openmc.stats.CylindricalIndependent`, respectively.
|
||||
|
||||
The angular distribution can be set equal to a sub-class of
|
||||
:class:`openmc.stats.UnitSphere` such as :class:`openmc.stats.Isotropic`,
|
||||
:class:`openmc.stats.Monodirectional`, or
|
||||
:class:`openmc.stats.PolarAzimuthal`. By default, if no angular distribution is
|
||||
specified, an isotropic angular distribution is used.
|
||||
:class:`openmc.stats.Monodirectional`, or :class:`openmc.stats.PolarAzimuthal`.
|
||||
By default, if no angular distribution is specified, an isotropic angular
|
||||
distribution is used. As an example of a non-trivial angular distribution, the
|
||||
following code would create a conical distribution with an aperture of 30
|
||||
degrees pointed in the positive x direction::
|
||||
|
||||
from math import pi, cos
|
||||
aperture = 30.0
|
||||
mu = openmc.stats.Uniform(cos(aperture/2), 1.0)
|
||||
phi = openmc.stats.Uniform(0.0, 2*pi)
|
||||
angle = openmc.stats.PolarAzimuthal(mu, phi, reference_uvw=(1., 0., 0.))
|
||||
|
||||
The energy distribution can be set equal to any univariate probability
|
||||
distribution. This could be a probability mass function
|
||||
|
|
@ -164,6 +175,66 @@ following would generate a photon source::
|
|||
For a full list of all classes related to statistical distributions, see
|
||||
:ref:`pythonapi_stats`.
|
||||
|
||||
.. _custom_source:
|
||||
|
||||
Custom Sources
|
||||
--------------
|
||||
|
||||
It is often the case that one may wish to simulate a complex source distribution
|
||||
that is not possible to represent with the classes described above. For these
|
||||
situations, it is possible to define a complex source with an externally defined
|
||||
source function that is loaded at runtime. A simple example source is shown
|
||||
below.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include "openmc/random_lcg.h"
|
||||
#include "openmc/source.h"
|
||||
#include "openmc/particle.h"
|
||||
|
||||
// you must have external C linkage here
|
||||
extern "C" openmc::Particle::Bank sample_source(uint64_t* seed) {
|
||||
openmc::Particle::Bank particle;
|
||||
// weight
|
||||
particle.particle = openmc::Particle::Type::neutron;
|
||||
particle.wgt = 1.0;
|
||||
// position
|
||||
double angle = 2.0 * M_PI * openmc::prn(seed);
|
||||
double radius = 3.0;
|
||||
particle.r.x = radius * std::cos(angle);
|
||||
particle.r.y = radius * std::sin(angle);
|
||||
particle.r.z = 0.0;
|
||||
// angle
|
||||
particle.u = {1.0, 0.0, 0.0};
|
||||
particle.E = 14.08e6;
|
||||
particle.delayed_group = 0;
|
||||
return particle;
|
||||
}
|
||||
|
||||
The above source creates monodirectional 14.08 MeV neutrons that are distributed
|
||||
in a ring with a 3 cm radius. This routine is not particularly complex, but
|
||||
should serve as an example upon which to build more complicated sources.
|
||||
|
||||
.. note:: The function signature must be declared ``extern "C"``.
|
||||
|
||||
.. note:: You should only use the openmc::prn() random number generator
|
||||
|
||||
In order to build your external source, you will need to link it against the
|
||||
OpenMC shared library. This can be done by writing a CMakeLists.txt file:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
||||
project(openmc_sources CXX)
|
||||
add_library(source SHARED source_ring.cpp)
|
||||
find_package(OpenMC REQUIRED HINTS <path to openmc>)
|
||||
target_link_libraries(source OpenMC::libopenmc)
|
||||
|
||||
After running ``cmake`` and ``make``, you will have a libsource.so (or .dylib)
|
||||
file in your build directory. Setting the :attr:`openmc.Source.library`
|
||||
attribute to the path of this shared library will indicate that it should be
|
||||
used for sampling source particles at runtime.
|
||||
|
||||
---------------
|
||||
Shannon Entropy
|
||||
---------------
|
||||
|
|
|
|||
|
|
@ -308,3 +308,65 @@ The following tables show all valid scores:
|
|||
| |particle. This corresponds to MT=444 produced by |
|
||||
| |NJOY's HEATR module. |
|
||||
+----------------------+---------------------------------------------------+
|
||||
|
||||
.. _usersguide_tally_normalization:
|
||||
|
||||
------------------------------
|
||||
Normalization of Tally Results
|
||||
------------------------------
|
||||
|
||||
As described in :ref:`usersguide_scores`, all tally scores are normalized per
|
||||
source particle simulated. However, for analysis of a given system, we usually
|
||||
want tally scores in a more natural unit. For example, neutron flux is often
|
||||
reported in units of particles/cm\ :sup:`2`\ -s. For a fixed source simulation,
|
||||
it is usually straightforward to convert units if the source rate is known. For
|
||||
example, if the system being modeled includes a source that is emitting 10\
|
||||
:sup:`4` neutrons per second, the tally results just need to be multipled by 10\
|
||||
:sup:`4`. This can either be done manually or using the
|
||||
:attr:`openmc.Source.strength` attribute.
|
||||
|
||||
For a :math:`k`\ -eigenvalue calculation, normalizing tally results is not as
|
||||
simple because the source rate is not actually known. Instead, we typically know
|
||||
the system power, :math:`P`, which represents how much energy is deposited per
|
||||
unit time. Most of this energy originates from fission, but a small percentage
|
||||
also results from other reactions (e.g., photons emitted from :math:`(n,\gamma)`
|
||||
reactions). The most rigorous method to normalize tally results is to run a
|
||||
coupled neutron-photon calculation and tally the ``heating`` score over the
|
||||
entire system. This score provides the heating rate in units of [eV/source],
|
||||
which we'll denote :math:`H`. Then, calculate the heating rate in J/source as
|
||||
|
||||
.. math::
|
||||
|
||||
H' = 1.602\times10^{-19} \left [ \frac{\text{J}}{\text{eV}} \right ] \cdot H
|
||||
\left [\frac{\text{eV}}{\text{source}} \right ].
|
||||
|
||||
Dividing the power by the observed heating rate then gives us a normalization
|
||||
factor that can be applied to other tallies:
|
||||
|
||||
.. math::
|
||||
|
||||
f = \frac{P}{H'} = \frac{[\text{J}/\text{s}]}{[\text{J}/\text{source}]} =
|
||||
\left [ \frac{\text{source}}{\text{s}} \right ].
|
||||
|
||||
With this normalization factor, we can then get the flux in typical units:
|
||||
|
||||
.. math::
|
||||
|
||||
\phi' = \frac{\phi}{fV} = \frac{[\text{particle-cm}/\text{source}]}
|
||||
{[\text{source}/\text{s}][\text{cm}^3]} = \left [
|
||||
\frac{\text{particle}}{\text{cm}^2\cdot\text{s}} \right ]
|
||||
|
||||
There are several slight variations on this procedure:
|
||||
|
||||
- Run a neutron-only calculation and estimate the total heating using the
|
||||
``heating-local`` score (this requires that your nuclear data has local
|
||||
heating data available, such as in the official data library at
|
||||
https://openmc.org. See :ref:`methods_heating` for more information.)
|
||||
- Run a neutron-only calculation and use the ``kappa-fission`` or
|
||||
``fission-q-recoverable`` scores along with an estimate of the extra heating
|
||||
due to neutron capture reactions.
|
||||
- Calculate the overall fission rate and then used a fixed Q value to estimate
|
||||
the heating rate.
|
||||
|
||||
Note that the only difference between these and the above procedures is in how
|
||||
:math:`H'` is estimated.
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ class Cell(IDManagerMixin):
|
|||
present in the cell, or in all of its instances for a 'distribmat'
|
||||
fill. For example, {'U235': 1.0e22, 'U238': 5.0e22, ...}.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
"""
|
||||
|
||||
next_id = 1
|
||||
|
|
@ -654,7 +656,7 @@ class Cell(IDManagerMixin):
|
|||
|
||||
Returns
|
||||
-------
|
||||
Cell
|
||||
openmc.Cell
|
||||
Cell instance
|
||||
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -31,8 +31,9 @@ class DataLibrary(EqualityMixin):
|
|||
name : str
|
||||
Name of material, e.g. 'Am241'
|
||||
data_type : str
|
||||
Name of data type, e.g. 'neutron', 'photon', 'wmp',
|
||||
or 'thermal'
|
||||
Name of data type, e.g. 'neutron', 'photon', 'wmp', or 'thermal'
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ class PredictorIntegrator(Integrator):
|
|||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
|
|
@ -143,6 +145,8 @@ class CECMIntegrator(Integrator):
|
|||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
|
|
@ -240,6 +244,8 @@ class CF4Integrator(Integrator):
|
|||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
|
|
@ -354,6 +360,8 @@ class CELIIntegrator(Integrator):
|
|||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
|
|
@ -455,6 +463,8 @@ class EPCRK4Integrator(Integrator):
|
|||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
|
|
@ -576,6 +586,8 @@ class LEQIIntegrator(Integrator):
|
|||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
operator : openmc.deplete.TransportOperator
|
||||
|
|
@ -693,6 +705,8 @@ class SICELIIntegrator(SIIntegrator):
|
|||
seconds, 'min' means minutes, 'h' means hours, and 'MWd/kg' indicates
|
||||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
n_steps : int, optional
|
||||
Number of stochastic iterations per depletion interval.
|
||||
Must be greater than zero. Default : 10
|
||||
|
|
@ -801,6 +815,8 @@ class SILEQIIntegrator(SIIntegrator):
|
|||
seconds, 'min' means minutes, 'h' means hours, and 'MWd/kg' indicates
|
||||
that the values are given in burnup (MW-d of energy deposited per
|
||||
kilogram of initial heavy metal).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
n_steps : int, optional
|
||||
Number of stochastic iterations per depletion interval.
|
||||
Must be greater than zero. Default : 10
|
||||
|
|
|
|||
|
|
@ -470,6 +470,8 @@ class FissionYieldDistribution(Mapping):
|
|||
def restrict_products(self, possible_products):
|
||||
"""Return a new distribution with select products
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
possible_products : iterable of str
|
||||
|
|
|
|||
|
|
@ -113,11 +113,15 @@ class Operator(TransportOperator):
|
|||
reduce_chain : bool, optional
|
||||
If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the
|
||||
depletion chain up to ``reduce_chain_level``. Default is False.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
reduce_chain_level : int, optional
|
||||
Depth of the search when reducing the depletion chain. Only used
|
||||
if ``reduce_chain`` evaluates to true. The default value of
|
||||
``None`` implies no limit on the depth.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Attributes
|
||||
----------
|
||||
geometry : openmc.Geometry
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ class ResultsList(list):
|
|||
"""Get number of nuclides over time from a single material
|
||||
|
||||
.. note::
|
||||
|
||||
Initial values for some isotopes that do not appear in
|
||||
initial concentrations may be non-zero, depending on the
|
||||
value of :class:`openmc.deplete.Operator` ``dilute_initial``.
|
||||
|
|
@ -59,10 +58,14 @@ class ResultsList(list):
|
|||
Nuclide name to evaluate
|
||||
nuc_units : {"atoms", "atom/b-cm", "atom/cm3"}, optional
|
||||
Units for the returned concentration. Default is ``"atoms"``
|
||||
|
||||
.. versionadded:: 0.12
|
||||
time_units : {"s", "min", "h", "d"}, optional
|
||||
Units for the returned time array. Default is ``"s"`` to
|
||||
return the value in seconds.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Returns
|
||||
-------
|
||||
time : numpy.ndarray
|
||||
|
|
|
|||
|
|
@ -59,9 +59,13 @@ class Element(str):
|
|||
enriched U. Default is None (natural composition).
|
||||
enrichment_target: str, optional
|
||||
Single nuclide name to enrich from a natural composition (e.g., 'O16')
|
||||
|
||||
.. versionadded:: 0.12
|
||||
enrichment_type: {'ao', 'wo'}, optional
|
||||
'ao' for enrichment as atom percent and 'wo' for weight percent.
|
||||
Default is: 'ao' for two-isotope enrichment; 'wo' for U enrichment
|
||||
|
||||
.. versionadded:: 0.12
|
||||
cross_sections : str, optional
|
||||
Location of cross_sections.xml file. Default is None.
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ def run(particles=None, threads=None, geometry_debug=False,
|
|||
event_based : bool, optional
|
||||
Turns on event-based parallelism, instead of default history-based
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Raises
|
||||
------
|
||||
subprocess.CalledProcessError
|
||||
|
|
|
|||
|
|
@ -530,6 +530,8 @@ class CellInstanceFilter(Filter):
|
|||
instances by default) and allows instances from different cells to be
|
||||
specified in a single filter.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bins : iterable of 2-tuples or numpy.ndarray
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ class Geometry:
|
|||
Whether or not to remove redundant surfaces from the geometry when
|
||||
exporting
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
"""
|
||||
# Find and remove redundant surfaces from the geometry
|
||||
if remove_surfs:
|
||||
|
|
@ -389,7 +391,9 @@ class Geometry:
|
|||
return surfaces
|
||||
|
||||
def get_redundant_surfaces(self):
|
||||
"""Return all of the topologically redundant surface ids
|
||||
"""Return all of the topologically redundant surface IDs
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
|
|||
|
|
@ -489,10 +489,14 @@ class Material(IDManagerMixin):
|
|||
Default is None (natural composition).
|
||||
enrichment_target: str, optional
|
||||
Single nuclide name to enrich from a natural composition (e.g., 'O16')
|
||||
|
||||
.. versionadded:: 0.12
|
||||
enrichment_type: {'ao', 'wo'}, optional
|
||||
'ao' for enrichment as atom percent and 'wo' for weight percent.
|
||||
Default is: 'ao' for two-isotope enrichment; 'wo' for U enrichment
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Notes
|
||||
-----
|
||||
General enrichment procedure is allowed only for elements composed of
|
||||
|
|
@ -561,6 +565,8 @@ class Material(IDManagerMixin):
|
|||
enrichment_target=None, enrichment_type=None):
|
||||
"""Add a elements from a chemical formula to the material.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
formula : str
|
||||
|
|
@ -694,6 +700,8 @@ class Material(IDManagerMixin):
|
|||
def get_elements(self):
|
||||
"""Returns all elements in the material
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Returns
|
||||
-------
|
||||
elements : list of str
|
||||
|
|
@ -981,6 +989,8 @@ class Material(IDManagerMixin):
|
|||
def mix_materials(cls, materials, fracs, percent_type='ao', name=None):
|
||||
"""Mix materials together based on atom, weight, or volume fractions
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
materials : Iterable of openmc.Material
|
||||
|
|
|
|||
|
|
@ -595,6 +595,8 @@ class RectilinearMesh(MeshBase):
|
|||
class UnstructuredMesh(MeshBase):
|
||||
"""A 3D unstructured mesh
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
|
|
|
|||
|
|
@ -201,6 +201,10 @@ class Model:
|
|||
"""Creates the XML files, runs OpenMC, and returns the path to the last
|
||||
statepoint file generated.
|
||||
|
||||
.. versionchanged:: 0.12
|
||||
Instead of returning the final k-effective value, this function now
|
||||
returns the path to the final statepoint written.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
**kwargs
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ class ZernikeRadial(Polynomial):
|
|||
The radial only Zernike polynomials are defined as in
|
||||
:class:`ZernikeRadialFilter`.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coef : Iterable of float
|
||||
|
|
@ -85,6 +87,8 @@ class Zernike(Polynomial):
|
|||
|
||||
The azimuthal Zernike polynomials are defined as in :class:`ZernikeFilter`.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coef : Iterable of float
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ class Region(ABC):
|
|||
def remove_redundant_surfaces(self, redundant_surfaces):
|
||||
"""Recursively remove all redundant surfaces referenced by this region
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
redundant_surfaces : dict
|
||||
|
|
@ -272,6 +274,8 @@ class Region(ABC):
|
|||
memo=None):
|
||||
r"""Rotate surface by angles provided or by applying matrix directly.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rotation : 3-tuple of float, or 3x3 iterable
|
||||
|
|
@ -587,6 +591,8 @@ class Complement(Region):
|
|||
def remove_redundant_surfaces(self, redundant_surfaces):
|
||||
"""Recursively remove all redundant surfaces referenced by this region
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
redundant_surfaces : dict
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ class Settings:
|
|||
Indicate whether to scale the fission photon yield by (EGP + EGD)/EGP
|
||||
where EGP is the energy release of prompt photons and EGD is the energy
|
||||
release of delayed photons.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
electron_treatment : {'led', 'ttb'}
|
||||
Whether to deposit all energy from electrons locally ('led') or create
|
||||
secondary bremsstrahlung photons ('ttb').
|
||||
|
|
@ -61,12 +63,18 @@ class Settings:
|
|||
event_based : bool
|
||||
Indicate whether to use event-based parallelism instead of the default
|
||||
history-based parallelism.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
generations_per_batch : int
|
||||
Number of generations per batch
|
||||
max_lost_particles : int
|
||||
Maximum number of lost particles
|
||||
|
||||
.. versionadded:: 0.12
|
||||
rel_max_lost_particles : int
|
||||
Maximum number of lost particles, relative to the total number of particles
|
||||
|
||||
.. versionadded:: 0.12
|
||||
inactive : int
|
||||
Number of inactive batches
|
||||
keff_trigger : dict
|
||||
|
|
@ -80,9 +88,13 @@ class Settings:
|
|||
material_cell_offsets : bool
|
||||
Generate an "offset table" for material cells by default. These tables
|
||||
are necessary when a particular instance of a cell needs to be tallied.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
max_particles_in_flight : int
|
||||
Number of neutrons to run concurrently when using event-based
|
||||
parallelism.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
max_order : None or int
|
||||
Maximum scattering order to apply globally when in multi-group mode.
|
||||
no_reduce : bool
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ class Source:
|
|||
Source file from which sites should be sampled
|
||||
library : str
|
||||
Path to a custom source library
|
||||
|
||||
.. versionadded:: 0.12
|
||||
strength : float
|
||||
Strength of the source
|
||||
particle : {'neutron', 'photon'}
|
||||
|
|
|
|||
|
|
@ -378,6 +378,8 @@ class SphericalIndependent(Spatial):
|
|||
:math:`\theta`, and :math:`\phi` components are sampled independently from
|
||||
one another and centered on the coordinates (x0, y0, z0).
|
||||
|
||||
.. versionadded: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
r : openmc.stats.Univariate
|
||||
|
|
@ -498,6 +500,8 @@ class CylindricalIndependent(Spatial):
|
|||
one another and in a reference frame whose origin is specified by the
|
||||
coordinates (x0, y0, z0).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
r : openmc.stats.Univariate
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ def _future_kwargs_warning_helper(cls, *args, **kwargs):
|
|||
def get_rotation_matrix(rotation, order='xyz'):
|
||||
r"""Generate a 3x3 rotation matrix from input angles
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rotation : 3-tuple of float
|
||||
|
|
@ -266,6 +268,8 @@ class Surface(IDManagerMixin, ABC):
|
|||
def normalize(self, coeffs=None):
|
||||
"""Normalize coefficients by first nonzero value
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coeffs : tuple, optional
|
||||
|
|
@ -347,6 +351,8 @@ class Surface(IDManagerMixin, ABC):
|
|||
def rotate(self, rotation, pivot=(0., 0., 0.), order='xyz', inplace=False):
|
||||
r"""Rotate surface by angles provided or by applying matrix directly.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rotation : 3-tuple of float, or 3x3 iterable
|
||||
|
|
@ -1223,6 +1229,8 @@ class Cylinder(QuadricMixin, Surface):
|
|||
def from_points(cls, p1, p2, r=1., **kwargs):
|
||||
"""Return a cylinder given points that define the axis and a radius.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p1, p2 : 3-tuples
|
||||
|
|
@ -2294,6 +2302,8 @@ class Halfspace(Region):
|
|||
memo=None):
|
||||
r"""Rotate surface by angles provided or by applying matrix directly.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rotation : 3-tuple of float, or 3x3 iterable
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@ class VolumeCalculation:
|
|||
Lower-left coordinates of bounding box used to sample points
|
||||
upper_right : Iterable of float
|
||||
Upper-right coordinates of bounding box used to sample points
|
||||
threshold : float
|
||||
Threshold for the maximum standard deviation of volume in the calculation
|
||||
atoms : dict
|
||||
Dictionary mapping unique IDs of domains to a mapping of nuclides to
|
||||
total number of atoms for each nuclide present in the domain. For
|
||||
|
|
@ -58,11 +56,17 @@ class VolumeCalculation:
|
|||
Dictionary mapping unique IDs of domains to estimated volumes in cm^3.
|
||||
threshold : float
|
||||
Threshold for the maxmimum standard deviation of volumes.
|
||||
|
||||
.. versionadded:: 0.12
|
||||
trigger_type : {'variance', 'std_dev', 'rel_err'}
|
||||
Value type used to halt volume calculation
|
||||
|
||||
.. versionadded:: 0.12
|
||||
iterations : int
|
||||
Number of iterations over samples (for calculations with a trigger).
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
"""
|
||||
def __init__(self, domains, samples, lower_left=None, upper_right=None):
|
||||
self._atoms = {}
|
||||
|
|
@ -225,6 +229,8 @@ class VolumeCalculation:
|
|||
def set_trigger(self, threshold, trigger_type):
|
||||
"""Set a trigger on the voulme calculation
|
||||
|
||||
.. versionadded:: 0.12
|
||||
|
||||
Parameters
|
||||
----------
|
||||
threshold : float
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue