Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3059aa0
Bootstrap material-wise MGXS with weight windows; fix two random ray …
Jun 9, 2026
54021ec
Add shielded-pocket example and MGXS bootstrap regression test
Jun 10, 2026
5b9a294
Compare quantitative results in MGXS bootstrap regression test
Jun 10, 2026
a3c64bd
Make full bootstrap test chain bit-reproducible; use NNDC references
Jun 10, 2026
d548bd2
Add relative dead band to weight window comparisons
Jun 10, 2026
1e7659c
Harden weight window dead band; move tolerance to constants.h
Jun 10, 2026
524ac6c
Polish for review: versionadded, comment wording, clang-format
Jun 10, 2026
4760553
Simplify bootstrap regression test to the standard harness pattern
Jun 10, 2026
cf21021
Test the complete bootstrap workflow; center the example sphere
Jun 10, 2026
ed7093b
Enclose example sphere in a vacuum box for uniform ray sampling
Jun 10, 2026
eaec54a
Slim unit tests to argument validation; fix comment grammar
Jun 10, 2026
af37735
Remove unit tests for weight_windows_file argument validation
Jun 10, 2026
ae6a54f
docs edits
jtramm Jun 10, 2026
0ec75ce
fixed ww unit test that used weight windows. Changed seed to prevent …
Jun 10, 2026
b162a03
Merge branch 'develop' into pr/jtramm/3965
paulromano Jul 2, 2026
3d9e3ae
Small updates
paulromano Jul 2, 2026
b0febed
Allow passing a Settings object to convert_to_multigroup
Jul 2, 2026
e405b74
Rework convert_to_multigroup settings customization; address review c…
Jul 2, 2026
edb836a
Remove redundant weight windows path handling in convert_to_multigroup
Jul 7, 2026
60ba8a9
Remove weight_windows_file argument in favor of settings.weight_windo…
Jul 8, 2026
e75a461
Drop redundant method= from doc examples (material_wise is the default)
Jul 8, 2026
550fe2b
Default convert_to_multigroup method to the one its settings were bui…
Jul 8, 2026
37d15f6
Declare the recorded MGXS generation method in Settings.__init__
Jul 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/pythonapi/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Simple Models
:template: myfunction.rst

openmc.examples.slab_mg
openmc.examples.sphere_with_shielded_pocket

Reactor Models
--------------
Expand Down
125 changes: 93 additions & 32 deletions docs/source/usersguide/random_ray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -642,13 +642,11 @@ model to use these multigroup cross sections. An example is given below::
model.convert_to_multigroup(
method="material_wise",
groups="CASMO-2",
nparticles=2000,
overwrite_mgxs_library=False,
mgxs_path="mgxs.h5",
correction=None,
source_energy=None,
temperatures=None,
temperature_settings=None
temperatures=None
)

The most important parameter to set is the ``method`` parameter, which can be
Expand All @@ -672,7 +670,9 @@ of these methods is given below:
both spatial and resonance self shielding effects
- * Potentially slower as the full geometry must be run
* If a material is only present far from the source and doesn't get tallied
to in the CE simulation, the MGXS will be zero for that material.
to in the CE simulation, the MGXS will be zero for that material. This
can be mitigated by supplying weight windows via the generation
settings (see :ref:`mgxs_bootstrap`).
* - ``stochastic_slab``
- * Medium Fidelity
* Runs a CE simulation with a greatly simplified geometry, where materials
Expand All @@ -693,12 +693,30 @@ of these methods is given below:

When selecting a non-default energy group structure, you can manually define
group boundaries or specify the name of a known group structure (a list of which
can be found at :data:`openmc.mgxs.GROUP_STRUCTURES`). The ``nparticles``
parameter can be adjusted upward to improve the fidelity of the generated cross
section library. The ``correction`` parameter can be set to ``"P0"`` to enable
P0 transport correction. The ``overwrite_mgxs_library`` parameter can be set to
``True`` to overwrite an existing MGXS library file, or ``False`` to skip
generation and use an existing library file.
can be found at :data:`openmc.mgxs.GROUP_STRUCTURES`). The ``correction``
parameter can be set to ``"P0"`` to enable P0 transport correction. The
``overwrite_mgxs_library`` parameter can be set to ``True`` to overwrite an
existing MGXS library file, or ``False`` to skip generation and use an existing
library file.

The continuous energy simulations used to generate the cross section library
can be customized via the ``settings`` parameter. To do so, start from the
default settings returned by :meth:`openmc.Model.mgxs_generation_settings`,
modify them as desired, and pass the result back. For example, the number of
particles per batch (2,000 by default) can be increased to improve the fidelity
of the generated cross section library as::

settings = model.mgxs_generation_settings()
settings.particles = 100_000
model.convert_to_multigroup(settings=settings)

The settings returned by :meth:`openmc.Model.mgxs_generation_settings` record
the method they were generated for, so a non-default method only needs to be
given once::

settings = model.mgxs_generation_settings("stochastic_slab")
settings.particles = 100_000
model.convert_to_multigroup(settings=settings)

.. note::
MGXS transport correction (via setting the ``correction`` parameter in the
Expand Down Expand Up @@ -739,12 +757,10 @@ The ``temperatures`` parameter can be provided if temperature-dependent
multi-group cross sections are desired for multi-physics simulations. An
individual cross section generation calculation is run for each temperature
provided, where the materials in the model are set to the temperature. The
temperature settings used during cross section generation can be specified with the
``temperature_settings`` parameter. If no ``temperature_settings`` are provided,
the settings contained in the model will be used. The valid keys and values in the
``temperature_settings`` dictionary are identical to
:attr:`openmc.Settings.temperature_settings`; more information can be found in
:class:`openmc.Settings` . This approach yields isothermal cross section interpolation
temperature settings used during cross section generation default to those
contained in the model and can be customized by setting
:attr:`openmc.Settings.temperature` on the object passed via the ``settings``
parameter. This approach yields isothermal cross section interpolation
tables, which can be inaccurate for systems with large differences between temperatures
in each material (often the case in fission reactors). If a more sophisticated
temperature-dependence is required, we recommend generating cross sections manually.
Expand All @@ -757,6 +773,51 @@ simulation, and if more fidelity is needed the user may wish to follow the
instructions below or experiment with transport correction techniques to improve
the fidelity of the generated MGXS data.

.. _mgxs_bootstrap:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Bootstrapping Material-Wise MGXS with Weight Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``"material_wise"`` method runs a continuous energy simulation of the
original geometry, so it produces the highest fidelity cross sections of the
three methods. However, it has a notable weakness: if a material only appears
far from the source (for example, a detector or structural material located
outside a thick shield), an analog continuous energy simulation may be unable to
transport any particles to that material. No tallies are scored there, and the
resulting cross sections for that material are zero. This situation is common in
shielding problems.

This limitation can be overcome by "bootstrapping" the cross section generation
with weight windows. The idea is to first cheaply produce a set of weight
windows that cover the entire problem and then reuse them to push particles into
the far regions during the higher fidelity ``"material_wise"`` solve. The weight
windows are generated using the ``"stochastic_slab"`` method (which produces
cross sections for *all* materials regardless of their location) together with
the random ray solver and a :class:`~openmc.WeightWindowGenerator`, exactly as
described in the :ref:`FW-CADIS user guide <usersguide_fw_cadis>`. The resulting
``weight_windows.h5`` file is then supplied to a second, higher fidelity
``"material_wise"`` cross section generation by setting ``weight_windows_file``
on the generation settings::

# First, generate weight windows with the stochastic slab method and random
# ray (see the FW-CADIS user guide), producing a weight_windows.h5 file.
...

# Then, bootstrap a higher fidelity material-wise library, applying those
# weight windows during the continuous energy solve so that particles can
# reach materials far from the source.
settings = model.mgxs_generation_settings()
settings.weight_windows_file = "weight_windows.h5"
model.convert_to_multigroup(settings=settings, overwrite_mgxs_library=True)

A weight windows file on the generation settings is only used with the
``"material_wise"`` method, as the ``"stochastic_slab"`` and
``"infinite_medium"`` methods use simplified surrogate geometries that are
incompatible with a weight window mesh defined over the original geometry (and
do not need weight windows, since they already tally all materials). A warning
is issued and the file is ignored if it is supplied to another method.

~~~~~~~~~~~~
The Hard Way
~~~~~~~~~~~~
Expand Down Expand Up @@ -1075,9 +1136,9 @@ 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 if there are
no user-specified adjoint sources present, followed by an adjoint transport
simulation. Fixed adjoint sources can be specified on the
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
Expand All @@ -1090,21 +1151,21 @@ simulation. Fixed adjoint sources can be specified on the
energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths)

adj_source = openmc.IndependentSource(
energy=energy_distribution,
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
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. When an initial forward solve is performed (i.e., when no
user-specified adjoint source is present), its output files are also written to
disk with a ``forward`` infix, so they are not overwritten by the subsequent
Expand All @@ -1116,10 +1177,10 @@ generating FW-CADIS weight windows, no weight window file is written for the
forward solve, as only the final adjoint-derived weight windows are meaningful.

.. note::
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
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.

---------------------------------------
Expand Down
13 changes: 13 additions & 0 deletions include/openmc/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ constexpr double ZERO_FLUX_CUTOFF {1e-22};
// value will be converted to pure void.
constexpr double MINIMUM_MACRO_XS {1e-6};

// Relative dead band applied to weight window comparisons: particles split
// only above upper * (1 + tol) and roulette only below lower * (1 - tol).
// Weight window arithmetic can land a particle's weight exactly back on a
// bound value (e.g., a roulette survivor is assigned survival_ratio * lower
// and a later split divides that back down), in which case the branch taken
// would be decided by the last ulp of the bound. Since window data carries
// ulp-level noise from non-associative parallel reductions in the solver that
// generated it, transport results would otherwise be chaotically sensitive to
// bit-level differences in the weight window file. Treating weights within
// the band as inside the window is statistically negligible, and weight
// window games are unbiased regardless of where the thresholds sit.
constexpr double WEIGHT_WINDOW_REL_TOL {1e-9};

// ============================================================================
// MATH AND PHYSICAL CONSTANTS

Expand Down
Loading
Loading