Local adjoint source for Random Ray (#3717)

This commit is contained in:
Jack Fletcher 2026-04-28 17:10:03 -04:00 committed by GitHub
parent 1116c4bdc0
commit 368ea069ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 2663 additions and 462 deletions

View file

@ -597,7 +597,7 @@ found in the :ref:`random ray user guide <random_ray>`.
*Default*: None
:source:
:ray_source:
Specifies the starting ray distribution, and follows the format for
:ref:`source_element`. It must be uniform in space and angle and cover the
full domain. It does not represent a physical neutron or photon source -- it
@ -605,6 +605,35 @@ found in the :ref:`random ray user guide <random_ray>`.
*Default*: None
:adjoint_source:
Specifies an adjoint fixed source for adjoint transport simulations, and
follows the format for :ref:`source_element`. The distributions which make
up the adjoint source are subject to the same restrictions as forward
fixed sources in Random Ray mode.
*Default*: None
:adjoint:
Specifies whether to perform adjoint transport. The default is 'False',
corresponding to forward transport.
*Default*: None
:volume_estimator:
Specifies choice of volume estimator for the random ray solver. Options
are 'naive', 'simulation_averaged', or 'hybrid'. The default is 'hybrid'.
*Default*: None
:volume_normalized_flux_tallies:
Specifies whether to normalize flux tallies by volume (bool). The
default is 'False'. When enabled, flux tallies will be reported in units
of cm/cm^3. When disabled, flux tallies will be reported in units of cm
(i.e., total distance traveled by neutrons in the spatial tally
region).
*Default*: None
:sample_method:
Specifies the method for sampling the starting ray distribution. This
element can be set to "prng" or "halton".
@ -1696,6 +1725,14 @@ mesh-based weight windows.
The ratio of the lower to upper weight window bounds.
*Default*: 5.0
For FW-CADIS:
:targets:
A sequence of IDs corresponding to the tallies which cover phase
space regions of interest for local variance reduction.
*Default*: None
---------------------------------------
``<weight_window_checkpoints>`` Element

View file

@ -1081,28 +1081,32 @@ lifetimes.
In OpenMC, the random ray adjoint solver is implemented simply by transposing
the scattering matrix, swapping :math:`\nu\Sigma_f` and :math:`\chi`, and then
running a normal transport solve. When no external fixed source is present, no
additional changes are needed in the transport process. However, if an external
fixed forward source is present in the simulation problem, then an additional
step is taken to compute the accompanying fixed adjoint source. In OpenMC, the
adjoint flux does *not* represent a response function for a particular detector
region. Rather, the adjoint flux is the global response, making it appropriate
for use with weight window generation schemes for global variance reduction.
Thus, if using a fixed source, the external source for the adjoint mode is
simply computed as being :math:`1 / \phi`, where :math:`\phi` is the forward
scalar flux that results from a normal forward solve (which OpenMC will run
first automatically when in adjoint mode). The adjoint external source will be
computed for each source region in the simulation mesh, independent of any
tallies. The adjoint external source is always flat, even when a linear
scattering and fission source shape is used. When in adjoint mode, all reported
results (e.g., tallies, eigenvalues, etc.) are derived from the adjoint flux,
even when the physical meaning is not necessarily obvious. These values are
still reported, though we emphasize that the primary use case for adjoint mode
is for producing adjoint flux tallies to support subsequent perturbation studies
and weight window generation.
running a normal transport solve. When no external fixed forward source is
present, or if an adjoint fixed source is specifically provided, no additional
changes are needed in the transport process. This adjoint source can
correspond, for example, to a detector response function in a particular
region. However, if an external fixed forward source is present in the
simulation problem without an adjoint fixed source, an additional step is taken
to compute the accompanying forward-weighted adjoint source. In this case, the
adjoint flux does *not* represent the importance of locations in phase space to
detector response; rather, the "response" in question is a uniform distribution
of Monte Carlo particle density, making the importance provided by the adjoint
flux appropriate for use with weight window generation schemes for global
variance reduction. Thus, if using a fixed source, the forward-weighted
external source for adjoint mode is simply computed as being :math:`1 / \phi`,
where :math:`\phi` is the forward scalar flux that results from a normal
forward solve (which OpenMC will run first automatically when in adjoint mode).
The adjoint external source will be computed for each source region in the
simulation mesh, independent of any tallies. The adjoint external source is
always flat, even when a linear scattering and fission source shape is used.
Note that the adjoint :math:`k_{eff}` is statistically the same as the forward
:math:`k_{eff}`, despite the flux distributions taking different shapes.
When in adjoint mode, all reported results (e.g., tallies, eigenvalues, etc.)
are derived from the adjoint flux, even when the physical meaning is not
necessarily obvious. These values are still reported, though we emphasize that
the primary use case for adjoint mode is for producing adjoint flux tallies to
support subsequent perturbation studies and weight window generation. Note
however that the adjoint :math:`k_{eff}` is statistically the same as the
forward :math:`k_{eff}`, despite the flux distributions taking different shapes.
---------------------------
Fundamental Sources of Bias

View file

@ -82,8 +82,8 @@ where it was born from.
The Forward-Weighted Consistent Adjoint Driven Importance Sampling method, or
`FW-CADIS method <https://doi.org/10.13182/NSE12-33>`_, produces weight windows
for global variance reduction given adjoint flux information throughout the
entire domain. The weight window lower bound is defined in Equation
for global or local variance reduction given adjoint flux information throughout
the entire domain. The weight window lower bound is defined in Equation
:eq:`fw_cadis`, and also involves a normalization step not shown here.
.. math::
@ -135,6 +135,18 @@ aware of this.
\text{FOM} = \frac{1}{\text{Time} \times \sigma^2}
Finally, one unique capability of the FW-CADIS weight window generator is to
produce weight windows for local variance reduction, given a list of the
responses of interest. This is controlled by optionally specifying target
tallies from the :class:`openmc.model.Model` to the
:class:`openmc.WeightWindowGenerator`, as illustrated in the
:ref:`user guide<variance_reduction>`. If target tallies for local variance
reduction are supplied, then the adjoint sources are only populated after the
initial forward simulation in the source regions associated with those tallies.
In other regions, the adjoint source term is instead set to zero. The Random
Ray solver then determines the adjoint flux map used to generate FW-CADIS
weight windows following the usual technique.
.. _methods_source_biasing:
--------------

View file

@ -944,6 +944,8 @@ as::
which will greatly improve the quality of the linear source term in 2D
simulations.
.. _usersguide_random_ray_run_modes:
---------------------------------
Fixed Source and Eigenvalue Modes
---------------------------------
@ -1073,22 +1075,47 @@ The adjoint flux random ray solver mode can be enabled as::
settings.random_ray['adjoint'] = True
When enabled, OpenMC will first run a forward transport simulation followed by
an adjoint transport simulation. The purpose of the forward solve is to compute
the adjoint external source when an external source is present in the
simulation. Simulation settings (e.g., number of rays, batches, etc.) will be
identical for both simulations. At the conclusion of the run, all results (e.g.,
tallies, plots, etc.) will be derived from the adjoint flux rather than the
forward flux but are not labeled any differently. The initial forward flux
solution will not be stored or available in the final statepoint file. Those
wishing to do analysis requiring both the forward and adjoint solutions will
need to run two separate simulations and load both statepoint files.
When enabled, OpenMC will first run a forward transport simulation if there are
no user-specified adjoint sources present, followed by an adjoint transport
simulation. Fixed adjoint sources can be specified on the
:attr:`openmc.Settings.random_ray` dictionary as follows::
# Geometry definition
...
detector_cell = openmc.Cell(fill=detector_mat, name='cell where detector will be')
...
# Define fixed adjoint neutron source
strengths = [1.0]
midpoints = [1.0e-4]
energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths)
adj_source = openmc.IndependentSource(
energy=energy_distribution,
constraints={'domains': [detector_cell]}
)
# Add to random_ray dict
settings.random_ray['adjoint_source'] = adj_source
The same constraints apply to the user-defined adjoint source as to the forward
source, described in the :ref:`Fixed Source and Eigenvalue section
<usersguide_random_ray_run_modes>`. If this source is not provided, a forward
solve must take place to compute the adjoint external source when a forward
external source is present in the problem. Simulation settings (e.g., number of
rays, batches, etc.) will be identical for both calculations. At the
conclusion of the run, all results (e.g., tallies, plots, etc.) will be
derived from the adjoint flux rather than the forward flux but are not labeled
any differently. The initial forward flux solution will not be stored or
available in the final statepoint file. Those wishing to do analysis requiring
both the forward and adjoint solutions will need to run two separate
simulations and load both statepoint files.
.. note::
When adjoint mode is selected, OpenMC will always perform a full forward
solve and then run a full adjoint solve immediately afterwards. Statepoint
and tally results will be derived from the adjoint flux, but will not be
labeled any differently.
Use of the automated
:ref:`FW-CADIS weight window generator<usersguide_fw_cadis>` is not
currently compatible with user-defined adjoint sources. Instead, the
initial forward calculation is used to assign "forward-weighted" adjoint
sources to the tally regions of interest.
---------------------------------------
Putting it All Together: Example Inputs

View file

@ -4,26 +4,27 @@
Variance Reduction
==================
Global variance reduction in OpenMC is accomplished by weight windowing
or source biasing techniques, the latter of which additionally provides a
local variance reduction capability. OpenMC is capable of generating weight
windows using either the MAGIC or FW-CADIS methods. Both techniques will
produce a ``weight_windows.h5`` file that can be loaded and used later on. In
Global and local variance reduction are possible in OpenMC through both weight
windowing and source biasing techniques. OpenMC is capable of generating weight
windows using either the MAGIC or FW-CADIS methods, the latter with an optional
capability for local variance reduction. Both techniques will produce a
``weight_windows.h5`` file that can be loaded and used later on. In
this section, we first break down the steps required to generate and apply
weight windows, then describe how source biasing may be applied.
.. _ww_generator:
------------------------------------
Generating Weight Windows with MAGIC
------------------------------------
-------------------------------------------
Generating Global Weight Windows with MAGIC
-------------------------------------------
As discussed in the :ref:`methods section <methods_variance_reduction>`, MAGIC
is an iterative method that uses flux tally information from a Monte Carlo
simulation to produce weight windows for a user-defined mesh. While generating
the weight windows, OpenMC is capable of applying the weight windows generated
from a previous batch while processing the next batch, allowing for progressive
improvement in the weight window quality across iterations.
simulation to produce weight windows for a user-defined mesh with the objective
of global variance reduction. While generating the weight windows, OpenMC is
capable of applying the weight windows generated from a previous batch while
processing the next batch, allowing for progressive improvement in the weight
window quality across iterations.
The typical way of generating weight windows is to define a mesh and then add an
:class:`openmc.WeightWindowGenerator` object to an :attr:`openmc.Settings`
@ -71,15 +72,20 @@ At the end of the simulation, a ``weight_windows.h5`` file will be saved to disk
for later use. Loading it in another subsequent simulation will be discussed in
the "Using Weight Windows" section below.
------------------------------------------------------
Generating Weight Windows with FW-CADIS and Random Ray
------------------------------------------------------
.. _usersguide_fw_cadis:
----------------------------------------------------------------------
Generating Global or Local Weight Windows with FW-CADIS and Random Ray
----------------------------------------------------------------------
Weight window generation with FW-CADIS and random ray in OpenMC uses the same
exact strategy as with MAGIC. An :class:`openmc.WeightWindowGenerator` object is
added to the :attr:`openmc.Settings` object, and a ``weight_windows.h5`` will be
generated at the end of the simulation. The only difference is that the code
must be run in random ray mode. A full description of how to enable and setup
exact strategy as with MAGIC. Using FW-CADIS, however, also enables
local variance reduction in fixed source problems through the :attr:`targets`
attribute, which is described later in this section. To enable FW-CADIS, an
:class:`openmc.WeightWindowGenerator` object is added to the
:attr:`openmc.Settings` object, and a ``weight_windows.h5`` will be generated
at the end of the simulation. The only procedural difference is that the code
must be run in random ray mode. A full description of how to enable and setup
random ray mode can be found in the :ref:`Random Ray User Guide <random_ray>`.
.. note::
@ -90,7 +96,7 @@ random ray mode can be found in the :ref:`Random Ray User Guide <random_ray>`.
ray solver. A high level overview of the current workflow for generation of
weight windows with FW-CADIS using random ray is given below.
1. Begin by making a deepy copy of your continuous energy Python model and then
1. Begin by making a deep copy of your continuous energy Python model and then
convert the copy to be multigroup and use the random ray transport solver.
The conversion process can largely be automated as described in more detail
in the :ref:`random ray quick start guide <quick_start>`, summarized below::
@ -148,7 +154,53 @@ random ray mode can be found in the :ref:`Random Ray User Guide <random_ray>`.
assigning to ``model.settings.random_ray['source_region_meshes']``) and for
weight window generation.
3. When running your multigroup random ray input deck, OpenMC will automatically
3. (Optional) If local variance reduction is desired in a fixed-source problem,
populate the :attr:`targets` attribute with an :class:`openmc.Tallies`
instance or an iterable of tally IDs indicating the tallies of interest for
variance reduction::
# Build a new example and WWG for local variance reduction
from openmc.examples import random_ray_three_region_cube_with_detectors
new_model = random_ray_three_region_cube_with_detectors()
ww_mesh = openmc.RegularMesh()
n = 7
width = 35.0
ww_mesh.dimension = (n, n, n)
ww_mesh.lower_left = (0.0, 0.0, 0.0)
ww_mesh.upper_right = (width, width, width)
wwg = openmc.WeightWindowGenerator(
method="fw_cadis",
mesh=ww_mesh,
max_realizations=new_model.settings.batches
)
new_model.settings.weight_window_generators = wwg
new_model.settings.random_ray['volume_estimator'] = 'naive'
# Get the tallies of interest
target_tallies = openmc.Tallies()
for tally in list(new_model.tallies):
if tally.name in {"Detector 1 Tally", "Detector 2 Tally"}:
target_tallies.append(tally)
# Add to WeightWindowGenerator
wwg.targets = target_tallies
.. warning::
The tallies designated as FW-CADIS targets to the
:class:`~openmc.WeightWindowGenerator` must be present under the
:class:`~openmc.model.Model.tallies` attribute of the
:class:`~openmc.model.Model` as well in order to be recognized as valid
local variance reduction targets. This check is performed when the
:func:`openmc.model.Model.export_to_model_xml` or
:func:`openmc.model.Model.export_to_xml` functions are called, meaning
that the standalone :func:`openmc.Settings.export_to_xml` and
:func:`openmc.Tallies.export_to_xml` methods should not be used with
FW-CADIS local variance reduction.
4. When running your multigroup random ray input deck, OpenMC will automatically
run a forward solve followed by an adjoint solve, with a
``weight_windows.h5`` file generated at the end. The ``weight_windows.h5``
file will contain FW-CADIS generated weight windows. This file can be used in