Variance Reduction - Weight Windows#

Creating and utilizing a weight window to accelerate deep shielding simulations#

This example simulates a shield room / bunker with corridor entrance and a neutron source in the center of the room. This example implements a single step of the Magic method of weight window generation.

In this tutorial we shall focus on generating a weight window to accelerate the simulation of particles through a shield.

Weight Windows are found using the MAGIC method and used to accelerate the simulation.

The variance reduction method used for this simulation is well documented in the OpenMC documentation https://docs.openmc.org/en/stable/methods/neutron_physics.html

The MAGIC method is well described in the original publication https://scientific-publications.ukaea.uk/wp-content/uploads/Published/INTERN1.pdf

First we import openmc and other packages needed for the example and configure the nuclear data path

import time  # used to time the simulation
import numpy as np

from matplotlib import pyplot as plt
from matplotlib.colors import LogNorm  # used for plotting log scale graphs

import openmc
from pathlib import Path
# Setting the cross section path to the correct location in the docker image.
# If you are running this outside the docker image you will have to change this path to your local cross section path.
openmc.config['cross_sections'] = Path.home() / 'nuclear_data' / 'cross_sections.xml'

We create a couple of materials for the simulation

mat_air = openmc.Material(name="Air")
mat_air.add_element("N", 0.784431)
mat_air.add_element("O", 0.210748)
mat_air.add_element("Ar", 0.0046)
mat_air.set_density("g/cc", 0.001205)

mat_concrete = openmc.Material()
mat_concrete.add_element("H",0.168759)
mat_concrete.add_element("C",0.001416)
mat_concrete.add_element("O",0.562524)
mat_concrete.add_element("Na",0.011838)
mat_concrete.add_element("Mg",0.0014)
mat_concrete.add_element("Al",0.021354)
mat_concrete.add_element("Si",0.204115)
mat_concrete.add_element("K",0.005656)
mat_concrete.add_element("Ca",0.018674)
mat_concrete.add_element("Fe",0.00426)
mat_concrete.set_density("g/cm3", 2.3)

materials = openmc.Materials([mat_air, mat_concrete])

Now we define and plot the geometry. This geometry is defined by parameters for every width and height. The parameters input into the geometry in a stacked manner so they can easily be adjusted to change the geometry without creating overlapping cells.

width_a = 100
width_b = 100
width_c = 500
width_d = 100
width_e = 100
width_f = 100
width_g = 100

depth_a = 100
depth_b = 100
depth_c = 700
depth_d = 600
depth_e = 100
depth_f = 100

height_j = 100
height_k = 500
height_l = 100

xplane_0 = openmc.XPlane(x0=0, boundary_type="vacuum")
xplane_1 = openmc.XPlane(x0=xplane_0.x0 + width_a)
xplane_2 = openmc.XPlane(x0=xplane_1.x0 + width_b)
xplane_3 = openmc.XPlane(x0=xplane_2.x0 + width_c)
xplane_4 = openmc.XPlane(x0=xplane_3.x0 + width_d)
xplane_5 = openmc.XPlane(x0=xplane_4.x0 + width_e)
xplane_6 = openmc.XPlane(x0=xplane_5.x0 + width_f)
xplane_7 = openmc.XPlane(x0=xplane_6.x0 + width_g, boundary_type="vacuum")

yplane_0 = openmc.YPlane(y0=0, boundary_type="vacuum")
yplane_1 = openmc.YPlane(y0=yplane_0.y0 + depth_a)
yplane_2 = openmc.YPlane(y0=yplane_1.y0 + depth_b)
yplane_3 = openmc.YPlane(y0=yplane_2.y0 + depth_c)
yplane_4 = openmc.YPlane(y0=yplane_3.y0 + depth_d)
yplane_5 = openmc.YPlane(y0=yplane_4.y0 + depth_e)
yplane_6 = openmc.YPlane(y0=yplane_5.y0 + depth_f, boundary_type="vacuum")

zplane_1 = openmc.ZPlane(z0=0, boundary_type="vacuum")
zplane_2 = openmc.ZPlane(z0=zplane_1.z0 + height_j)
zplane_3 = openmc.ZPlane(z0=zplane_2.z0 + height_k)
zplane_4 = openmc.ZPlane(z0=zplane_3.z0 + height_l, boundary_type="vacuum")

outside_left_region = +xplane_0 & -xplane_1 & +yplane_1 & -yplane_5 & +zplane_1 & -zplane_4
wall_left_region = +xplane_1 & -xplane_2 & +yplane_2 & -yplane_4 & +zplane_2 & -zplane_3
wall_right_region = +xplane_5 & -xplane_6 & +yplane_2 & -yplane_5 & +zplane_2 & -zplane_3
wall_top_region = +xplane_1 & -xplane_4 & +yplane_4 & -yplane_5 & +zplane_2 & -zplane_3
outside_top_region = +xplane_0 & -xplane_7 & +yplane_5 & -yplane_6 & +zplane_1 & -zplane_4
wall_bottom_region = +xplane_1 & -xplane_6 & +yplane_1 & -yplane_2 & +zplane_2 & -zplane_3
outside_bottom_region = +xplane_0 & -xplane_7 & +yplane_0 & -yplane_1 & +zplane_1 & -zplane_4
wall_middle_region = +xplane_3 & -xplane_4 & +yplane_3 & -yplane_4 & +zplane_2 & -zplane_3
outside_right_region = +xplane_6 & -xplane_7 & +yplane_1 & -yplane_5 & +zplane_1 & -zplane_4

room_region = +xplane_2 & -xplane_3 & +yplane_2 & -yplane_4 & +zplane_2 & -zplane_3
gap_region = +xplane_3 & -xplane_4 & +yplane_2 & -yplane_3 & +zplane_2 & -zplane_3
corridor_region = +xplane_4 & -xplane_5 & +yplane_2 & -yplane_5 & +zplane_2 & -zplane_3

roof_region = +xplane_1 & -xplane_6 & +yplane_1 & -yplane_5 & +zplane_1 & -zplane_2
floor_region = +xplane_1 & -xplane_6 & +yplane_1 & -yplane_5 & +zplane_3 & -zplane_4

outside_left_cell = openmc.Cell(region=outside_left_region, fill=mat_air)
outside_right_cell = openmc.Cell(region=outside_right_region, fill=mat_air)
outside_top_cell = openmc.Cell(region=outside_top_region, fill=mat_air)
outside_bottom_cell = openmc.Cell(region=outside_bottom_region, fill=mat_air)
wall_left_cell = openmc.Cell(region=wall_left_region, fill=mat_concrete)
wall_right_cell = openmc.Cell(region=wall_right_region, fill=mat_concrete)
wall_top_cell = openmc.Cell(region=wall_top_region, fill=mat_concrete)
wall_bottom_cell = openmc.Cell(region=wall_bottom_region, fill=mat_concrete)
wall_middle_cell = openmc.Cell(region=wall_middle_region, fill=mat_concrete)
room_cell = openmc.Cell(region=room_region, fill=mat_air)
gap_cell = openmc.Cell(region=gap_region, fill=mat_air)
corridor_cell = openmc.Cell(region=corridor_region, fill=mat_air)

roof_cell = openmc.Cell(region=roof_region, fill=mat_concrete)
floor_cell = openmc.Cell(region=floor_region, fill=mat_concrete)

geometry = openmc.Geometry(
    [
        outside_bottom_cell,
        outside_top_cell,
        outside_left_cell,
        outside_right_cell,
        wall_left_cell,
        wall_right_cell,
        wall_top_cell,
        wall_bottom_cell,
        wall_middle_cell,
        room_cell,
        gap_cell,
        corridor_cell,
        roof_cell,
        floor_cell,
    ]
)

Now we plot the geometry and color by materials.

plot = geometry.plot(basis='xz',  color_by='material')
plot.figure.savefig('geometry_top_down_view.png', bbox_inches="tight")
../../_images/4fa4a7f518558555651a14383a19ecb25f895db1bf7c1ef631421234e2160c8f.png

Next we create a point source, this also uses the same geometry parameters to place in the center of the room regardless of the values of the parameters.

# location of the point source
source_x = width_a + width_b + width_c * 0.5
source_y = depth_a + depth_b + depth_c * 0.75
source_z = height_j + height_k * 0.5
space = openmc.stats.Point((source_x, source_y, source_z))

angle = openmc.stats.Isotropic()

# all (100%) of source particles are 2.5MeV energy
energy = openmc.stats.Discrete([2.5e6], [1.0])

source = openmc.IndependentSource(space=space, angle=angle, energy=energy)
source.particle = "neutron"

Next we create a mesh that encompasses the entire geometry and scores neutron flux

mesh = openmc.RegularMesh().from_domain(geometry)
mesh.dimension = (500, 500, 1)

mesh_filter = openmc.MeshFilter(mesh, filter_id=1)
particle_filter = openmc.ParticleFilter('neutron', filter_id=2)

flux_tally = openmc.Tally(name="flux tally")
flux_tally.filters = [mesh_filter, particle_filter]
flux_tally.scores = ["flux"]
flux_tally.id = 42  # we set the ID because we need to access this later

tallies = openmc.Tallies([flux_tally])

Creates the simulation settings

settings = openmc.Settings()

settings.run_mode = "fixed source"
settings.source = source
settings.particles = 80000
settings.batches = 5
# no need to write the tallies.out file which saves space and time when large meshes are used
settings.output = {'tallies': False}

Creates and exports the model

model = openmc.Model(geometry, materials, settings, tallies)

We are going to plot the mesh results with and without weight windows so lets write a function for the plotting

def run_and_plot(model: openmc.Model, image_filename: str) -> openmc.StatePoint:

    for f in Path('.').glob('*.h5'):
        f.unlink(missing_ok=True)
    sp_filename = model.run()

    with openmc.StatePoint(sp_filename) as sp:
        flux_tally = sp.get_tally(name="flux tally")

    mesh_extent = mesh.bounding_box.extent['xy']

    # create a plot of the mean flux values
    flux_mean = flux_tally.get_reshaped_data(value='mean', expand_dims=True).squeeze()

    fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 5))
    ax1.imshow(
        flux_mean.T,
        origin="lower",
        extent=mesh_extent,
        norm=LogNorm(),
    )

    ax1 = model.plot(
        outline='only',
        extent=model.bounding_box.extent['xz'],
        axes=ax1,  # Use the same axis as ax1\n",
        pixels=10_000_000,  #avoids rounded corners on outline
        color_by='material',
    )
    ax1.set_title("Flux Mean")

    # create a plot of the flux relative error
    flux_std_dev = flux_tally.get_reshaped_data(value='std_dev', expand_dims=True).squeeze()
    ax2.imshow(
        flux_std_dev.T,
        origin="lower",
        extent=mesh_extent,
        norm=LogNorm(),
    )

    ax2 = model.plot(
        outline='only',
        extent=model.bounding_box.extent['xz'],
        axes=ax2,  # Use the same axis as ax2\n",
        pixels=10_000_000,  #avoids rounded corners on outline
        color_by='material',
    )
    ax2.set_title("Flux Std. Dev.")

    plt.savefig(image_filename)
    return sp

Now we run the model without weight windows

# this helps time the simulation
t0 = time.time()

# delete the old summary file if it exists
Path('summary.h5').unlink(missing_ok=True)

run_and_plot(model, 'no_ww_statepoint_filename.png')

print(f'total time without weight windows {int(time.time()-t0)}s')
                                %%%%%%%%%%%%%%%
                           %%%%%%%%%%%%%%%%%%%%%%%%
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                    %%%%%%%%%%%%%%%%%%%%%%%%
                                     %%%%%%%%%%%%%%%%%%%%%%%%
                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%
                ##################     %%%%%%%%%%%%%%%%%%%%%%%
                ###################     %%%%%%%%%%%%%%%%%%%%%%%
                ####################     %%%%%%%%%%%%%%%%%%%%%%
                #####################     %%%%%%%%%%%%%%%%%%%%%
                ######################     %%%%%%%%%%%%%%%%%%%%
                #######################     %%%%%%%%%%%%%%%%%%
                 #######################     %%%%%%%%%%%%%%%%%
                 ######################     %%%%%%%%%%%%%%%%%
                  ####################     %%%%%%%%%%%%%%%%%
                    #################     %%%%%%%%%%%%%%%%%
                     ###############     %%%%%%%%%%%%%%%%
                       ############     %%%%%%%%%%%%%%%
                          ########     %%%%%%%%%%%%%%
                                      %%%%%%%%%%%

                 | The OpenMC Monte Carlo Code
       Copyright | 2011-2026 MIT, UChicago Argonne LLC, and contributors
         License | https://docs.openmc.org/en/latest/license.html
         Version | 0.15.3-dev607
     Commit Hash | ead172c9bcce5f4fdc3e7a672a9641c78f44a720
       Date/Time | 2026-08-07 16:33:39
  OpenMP Threads | 4

 Reading model XML file 'model.xml' ...
 Reading cross sections XML file...
 Reading N14 from /home/runner/nuclear_data/neutron/N14.h5
 Reading N15 from /home/runner/nuclear_data/neutron/N15.h5
 Reading O16 from /home/runner/nuclear_data/neutron/O16.h5
 Reading O17 from /home/runner/nuclear_data/neutron/O17.h5
 Reading O18 from /home/runner/nuclear_data/neutron/O18.h5
 Reading Ar36 from /home/runner/nuclear_data/neutron/Ar36.h5
 WARNING: Negative value(s) found on probability table for nuclide Ar36 at 294K
 Reading Ar38 from /home/runner/nuclear_data/neutron/Ar38.h5
 Reading Ar40 from /home/runner/nuclear_data/neutron/Ar40.h5
 Reading H1 from /home/runner/nuclear_data/neutron/H1.h5
 Reading H2 from /home/runner/nuclear_data/neutron/H2.h5
 Reading C12 from /home/runner/nuclear_data/neutron/C12.h5
 Reading C13 from /home/runner/nuclear_data/neutron/C13.h5
 Reading Na23 from /home/runner/nuclear_data/neutron/Na23.h5
 Reading Mg24 from /home/runner/nuclear_data/neutron/Mg24.h5
 Reading Mg25 from /home/runner/nuclear_data/neutron/Mg25.h5
 Reading Mg26 from /home/runner/nuclear_data/neutron/Mg26.h5
 Reading Al27 from /home/runner/nuclear_data/neutron/Al27.h5
 Reading Si28 from /home/runner/nuclear_data/neutron/Si28.h5
 Reading Si29 from /home/runner/nuclear_data/neutron/Si29.h5
 Reading Si30 from /home/runner/nuclear_data/neutron/Si30.h5
 Reading K39 from /home/runner/nuclear_data/neutron/K39.h5
 Reading K40 from /home/runner/nuclear_data/neutron/K40.h5
 Reading K41 from /home/runner/nuclear_data/neutron/K41.h5
 Reading Ca40 from /home/runner/nuclear_data/neutron/Ca40.h5
 Reading Ca42 from /home/runner/nuclear_data/neutron/Ca42.h5
 Reading Ca43 from /home/runner/nuclear_data/neutron/Ca43.h5
 Reading Ca44 from /home/runner/nuclear_data/neutron/Ca44.h5
 Reading Ca46 from /home/runner/nuclear_data/neutron/Ca46.h5
 Reading Ca48 from /home/runner/nuclear_data/neutron/Ca48.h5
 Reading Fe54 from /home/runner/nuclear_data/neutron/Fe54.h5
 Reading Fe56 from /home/runner/nuclear_data/neutron/Fe56.h5
 Reading Fe57 from /home/runner/nuclear_data/neutron/Fe57.h5
 Reading Fe58 from /home/runner/nuclear_data/neutron/Fe58.h5
 Minimum neutron data temperature: 294 K
 Maximum neutron data temperature: 294 K
 Preparing distributed cell instances...
 Writing summary.h5 file...
 Maximum neutron transport energy: 20000000 eV for N15

 ===============>     FIXED SOURCE TRANSPORT SIMULATION     <===============

 Simulating batch 1
 Simulating batch 2
 Simulating batch 3
 Simulating batch 4
 Simulating batch 5
 Creating state point statepoint.5.h5...

 =======================>     TIMING STATISTICS     <=======================

 Total time for initialization     = 3.1273e+00 seconds
   Reading cross sections          = 3.1078e+00 seconds
 Total time in simulation          = 4.1961e+01 seconds
   Time in transport only          = 4.1947e+01 seconds
   Time in active batches          = 4.1961e+01 seconds
   Time accumulating tallies       = 7.3055e-04 seconds
   Time writing statepoints        = 1.1839e-02 seconds
 Total time for finalization       = 7.8100e-07 seconds
 Total time elapsed                = 4.5095e+01 seconds
 Calculation Rate (active)         = 9532.65 particles/second

 ============================>     RESULTS     <============================

 Leakage Fraction            = 0.00190 +/- 0.00007
total time without weight windows 49s
../../_images/0d2698b86c4b1f65cd9f2434628082aab48f5c920f1641bd84971c20de7382f9.png

Now we want to run the same model but with weight windows.

We make use of openmc WeightWindowGenerator to make a WeightWindows object

https://docs.openmc.org/en/stable/pythonapi/generated/openmc.WeightWindows.html https://docs.openmc.org/en/latest/pythonapi/generated/openmc.WeightWindowGenerator.html

wwg = openmc.WeightWindowGenerator(
    mesh=mesh,  # this is the mesh that covers the geometry
    energy_bounds=np.linspace(0.0, 2.5e6, 10),  # 10 energy bins from 0 to max source energy
    particle_type='neutron',
)

# The simulation with Weight Windows takes more time per particle because particles are splitting
# and take more time from birth to termination for the particle including all the split particles
# we are reducing the number of particles so this simulation takes a similar amount of time
# to the previous simulation that didn't use weight windows. So we can make a fair comparison
model.settings.particles = 4900
model.settings.max_history_splits = 1_000  # controls the maximum partile splits over the entire lifetime of the particle
model.settings.weight_window_generators = wwg

Now we run the model with Weight Windows enabled and being generated during the simulation.

# this helps time the simulation
t0 = time.time()

run_and_plot(model, 'ww.png')

print(f'total time with weight windows {int(time.time()-t0)}s')
                                %%%%%%%%%%%%%%%
                           %%%%%%%%%%%%%%%%%%%%%%%%
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                    %%%%%%%%%%%%%%%%%%%%%%%%
                                     %%%%%%%%%%%%%%%%%%%%%%%%
                 ###############      %%%%%%%%%%%%%%%%%%%%%%%%
                ##################     %%%%%%%%%%%%%%%%%%%%%%%
                ###################     %%%%%%%%%%%%%%%%%%%%%%%
                ####################     %%%%%%%%%%%%%%%%%%%%%%
                #####################     %%%%%%%%%%%%%%%%%%%%%
                ######################     %%%%%%%%%%%%%%%%%%%%
                #######################     %%%%%%%%%%%%%%%%%%
                 #######################     %%%%%%%%%%%%%%%%%
                 ######################     %%%%%%%%%%%%%%%%%
                  ####################     %%%%%%%%%%%%%%%%%
                    #################     %%%%%%%%%%%%%%%%%
                     ###############     %%%%%%%%%%%%%%%%
                       ############     %%%%%%%%%%%%%%%
                          ########     %%%%%%%%%%%%%%
                                      %%%%%%%%%%%

                 | The OpenMC Monte Carlo Code
       Copyright | 2011-2026 MIT, UChicago Argonne LLC, and contributors
         License | https://docs.openmc.org/en/latest/license.html
         Version | 0.15.3-dev607
     Commit Hash | ead172c9bcce5f4fdc3e7a672a9641c78f44a720
       Date/Time | 2026-08-07 16:34:28
  OpenMP Threads | 4

 Reading model XML file 'model.xml' ...
 Reading cross sections XML file...
 Reading N14 from /home/runner/nuclear_data/neutron/N14.h5
 Reading N15 from /home/runner/nuclear_data/neutron/N15.h5
 Reading O16 from /home/runner/nuclear_data/neutron/O16.h5
 Reading O17 from /home/runner/nuclear_data/neutron/O17.h5
 Reading O18 from /home/runner/nuclear_data/neutron/O18.h5
 Reading Ar36 from /home/runner/nuclear_data/neutron/Ar36.h5
 WARNING: Negative value(s) found on probability table for nuclide Ar36 at 294K
 Reading Ar38 from /home/runner/nuclear_data/neutron/Ar38.h5
 Reading Ar40 from /home/runner/nuclear_data/neutron/Ar40.h5
 Reading H1 from /home/runner/nuclear_data/neutron/H1.h5
 Reading H2 from /home/runner/nuclear_data/neutron/H2.h5
 Reading C12 from /home/runner/nuclear_data/neutron/C12.h5
 Reading C13 from /home/runner/nuclear_data/neutron/C13.h5
 Reading Na23 from /home/runner/nuclear_data/neutron/Na23.h5
 Reading Mg24 from /home/runner/nuclear_data/neutron/Mg24.h5
 Reading Mg25 from /home/runner/nuclear_data/neutron/Mg25.h5
 Reading Mg26 from /home/runner/nuclear_data/neutron/Mg26.h5
 Reading Al27 from /home/runner/nuclear_data/neutron/Al27.h5
 Reading Si28 from /home/runner/nuclear_data/neutron/Si28.h5
 Reading Si29 from /home/runner/nuclear_data/neutron/Si29.h5
 Reading Si30 from /home/runner/nuclear_data/neutron/Si30.h5
 Reading K39 from /home/runner/nuclear_data/neutron/K39.h5
 Reading K40 from /home/runner/nuclear_data/neutron/K40.h5
 Reading K41 from /home/runner/nuclear_data/neutron/K41.h5
 Reading Ca40 from /home/runner/nuclear_data/neutron/Ca40.h5
 Reading Ca42 from /home/runner/nuclear_data/neutron/Ca42.h5
 Reading Ca43 from /home/runner/nuclear_data/neutron/Ca43.h5
 Reading Ca44 from /home/runner/nuclear_data/neutron/Ca44.h5
 Reading Ca46 from /home/runner/nuclear_data/neutron/Ca46.h5
 Reading Ca48 from /home/runner/nuclear_data/neutron/Ca48.h5
 Reading Fe54 from /home/runner/nuclear_data/neutron/Fe54.h5
 Reading Fe56 from /home/runner/nuclear_data/neutron/Fe56.h5
 Reading Fe57 from /home/runner/nuclear_data/neutron/Fe57.h5
 Reading Fe58 from /home/runner/nuclear_data/neutron/Fe58.h5
 Minimum neutron data temperature: 294 K
 Maximum neutron data temperature: 294 K
 Preparing distributed cell instances...
 Writing summary.h5 file...
 Maximum neutron transport energy: 20000000 eV for N15

 ===============>     FIXED SOURCE TRANSPORT SIMULATION     <===============

 Simulating batch 1
  Primary source          particles: 4900
  Secondary generation 1     tracks: 0
 Simulating batch 2
  Primary source          particles: 4900
  Secondary generation 1     tracks: 67879
  Secondary generation 2     tracks: 281640
  Secondary generation 3     tracks: 410735
  Secondary generation 4     tracks: 299338
  Secondary generation 5     tracks: 208679
  Secondary generation 6     tracks: 166829
  Secondary generation 7     tracks: 131993
  Secondary generation 8     tracks: 102781
  Secondary generation 9     tracks: 79963
  Secondary generation 10    tracks: 61874
  Secondary generation 11    tracks: 45363
  Secondary generation 12    tracks: 35136
  Secondary generation 13    tracks: 28211
  Secondary generation 14    tracks: 21410
  Secondary generation 15    tracks: 14865
  Secondary generation 16    tracks: 10739
  Secondary generation 17    tracks: 7991
  Secondary generation 18    tracks: 5293
  Secondary generation 19    tracks: 4601
  Secondary generation 20    tracks: 4020
  Secondary generation 21    tracks: 2415
  Secondary generation 22    tracks: 1514
  Secondary generation 23    tracks: 1615
  Secondary generation 24    tracks: 1303
  Secondary generation 25    tracks: 882
  Secondary generation 26    tracks: 390
  Secondary generation 27    tracks: 313
  Secondary generation 28    tracks: 399
  Secondary generation 29    tracks: 266
  Secondary generation 30    tracks: 296
  Secondary generation 31    tracks: 218
  Secondary generation 32    tracks: 193
  Secondary generation 33    tracks: 164
  Secondary generation 34    tracks: 115
  Secondary generation 35    tracks: 131
  Secondary generation 36    tracks: 126
  Secondary generation 37    tracks: 60
  Secondary generation 38    tracks: 54
  Secondary generation 39    tracks: 32
  Secondary generation 40    tracks: 42
  Secondary generation 41    tracks: 26
  Secondary generation 42    tracks: 1
  Secondary generation 43    tracks: 3
  Secondary generation 44    tracks: 0
 Simulating batch 3
  Primary source          particles: 4900
  Secondary generation 1     tracks: 68272
  Secondary generation 2     tracks: 284609
  Secondary generation 3     tracks: 412241
  Secondary generation 4     tracks: 302470
  Secondary generation 5     tracks: 218528
  Secondary generation 6     tracks: 176912
  Secondary generation 7     tracks: 137522
  Secondary generation 8     tracks: 108475
  Secondary generation 9     tracks: 86422
  Secondary generation 10    tracks: 67288
  Secondary generation 11    tracks: 48942
  Secondary generation 12    tracks: 36994
  Secondary generation 13    tracks: 27912
  Secondary generation 14    tracks: 22322
  Secondary generation 15    tracks: 15947
  Secondary generation 16    tracks: 12288
  Secondary generation 17    tracks: 11080
  Secondary generation 18    tracks: 9788
  Secondary generation 19    tracks: 7273
  Secondary generation 20    tracks: 4618
  Secondary generation 21    tracks: 4192
  Secondary generation 22    tracks: 2990
  Secondary generation 23    tracks: 1892
  Secondary generation 24    tracks: 1391
  Secondary generation 25    tracks: 1259
  Secondary generation 26    tracks: 1091
  Secondary generation 27    tracks: 1130
  Secondary generation 28    tracks: 713
  Secondary generation 29    tracks: 286
  Secondary generation 30    tracks: 144
  Secondary generation 31    tracks: 198
  Secondary generation 32    tracks: 160
  Secondary generation 33    tracks: 83
  Secondary generation 34    tracks: 17
  Secondary generation 35    tracks: 0
 Simulating batch 4
  Primary source          particles: 4900
  Secondary generation 1     tracks: 68374
  Secondary generation 2     tracks: 286402
  Secondary generation 3     tracks: 419657
  Secondary generation 4     tracks: 307221
  Secondary generation 5     tracks: 221023
  Secondary generation 6     tracks: 178405
  Secondary generation 7     tracks: 139346
  Secondary generation 8     tracks: 112302
  Secondary generation 9     tracks: 87731
  Secondary generation 10    tracks: 67877
  Secondary generation 11    tracks: 50507
  Secondary generation 12    tracks: 36459
  Secondary generation 13    tracks: 27609
  Secondary generation 14    tracks: 19884
  Secondary generation 15    tracks: 15593
  Secondary generation 16    tracks: 13513
  Secondary generation 17    tracks: 8458
  Secondary generation 18    tracks: 6069
  Secondary generation 19    tracks: 4466
  Secondary generation 20    tracks: 2937
  Secondary generation 21    tracks: 2609
  Secondary generation 22    tracks: 1993
  Secondary generation 23    tracks: 1343
  Secondary generation 24    tracks: 466
  Secondary generation 25    tracks: 574
  Secondary generation 26    tracks: 487
  Secondary generation 27    tracks: 273
  Secondary generation 28    tracks: 158
  Secondary generation 29    tracks: 104
  Secondary generation 30    tracks: 179
  Secondary generation 31    tracks: 104
  Secondary generation 32    tracks: 53
  Secondary generation 33    tracks: 74
  Secondary generation 34    tracks: 30
  Secondary generation 35    tracks: 11
  Secondary generation 36    tracks: 6
  Secondary generation 37    tracks: 0
 Simulating batch 5
  Primary source          particles: 4900
  Secondary generation 1     tracks: 68683
  Secondary generation 2     tracks: 287381
  Secondary generation 3     tracks: 417448
  Secondary generation 4     tracks: 307211
  Secondary generation 5     tracks: 223951
  Secondary generation 6     tracks: 184647
  Secondary generation 7     tracks: 144824
  Secondary generation 8     tracks: 114446
  Secondary generation 9     tracks: 91466
  Secondary generation 10    tracks: 70586
  Secondary generation 11    tracks: 53789
  Secondary generation 12    tracks: 38299
  Secondary generation 13    tracks: 26909
  Secondary generation 14    tracks: 21351
  Secondary generation 15    tracks: 17157
  Secondary generation 16    tracks: 12674
  Secondary generation 17    tracks: 8813
  Secondary generation 18    tracks: 6071
  Secondary generation 19    tracks: 4619
  Secondary generation 20    tracks: 3321
  Secondary generation 21    tracks: 2353
  Secondary generation 22    tracks: 1488
  Secondary generation 23    tracks: 1189
  Secondary generation 24    tracks: 830
  Secondary generation 25    tracks: 671
  Secondary generation 26    tracks: 556
  Secondary generation 27    tracks: 359
  Secondary generation 28    tracks: 387
  Secondary generation 29    tracks: 142
  Secondary generation 30    tracks: 56
  Secondary generation 31    tracks: 20
  Secondary generation 32    tracks: 0
 Creating state point statepoint.5.h5...
 Exporting weight windows to weight_windows.h5...

 =======================>     TIMING STATISTICS     <=======================

 Total time for initialization     = 3.2073e+00 seconds
   Reading cross sections          = 3.1800e+00 seconds
 Total time in simulation          = 7.8917e+01 seconds
   Time in transport only          = 7.8785e+01 seconds
   Time in active batches          = 7.8917e+01 seconds
   Time accumulating tallies       = 9.3445e-03 seconds
   Time writing statepoints        = 6.4760e-02 seconds
 Total time for finalization       = 9.5346e-03 seconds
 Total time elapsed                = 8.2146e+01 seconds
 Calculation Rate (active)         = 310.453 particles/second
 Track Rate (active)               = 105096 tracks/second

 ============================>     RESULTS     <============================

 Leakage Fraction            = 0.00213 +/- 0.00012
 WARNING: The maximum number of specified tally realizations (1) is greater than
          the number of active batches (0).
 WARNING: The maximum number of specified tally realizations (1) is greater than
          the number of active batches (0).
total time with weight windows 86s
../../_images/0dc9efd9549434f317b92bdfe11d3448562374b41705dd6f2eba59e1317cc866.png

You might have to fine tune the particle numbers to get the two simulations taking exactly the same amount of time to make it a fair test.

However on this laptop both simulations took 30 seconds and it is clear from the two images that the weight window simulation was more efficient at getting particles through the shielding.

Weight windows can be fine tuned for a specific problem to improve their performance.

openmc.lib allows fine control over the weight window creation and that is covered in the next notebooks.