Skip to content

Commit 300cae0

Browse files
jtrammshimwelljon-proximafusion
committed
Turn the weight window game off for a zero or negative lower bound
A weight window lower bound of zero means no weight window information exists there (MCNP wwinp files use a zero lower bound to turn the game off in a cell), and weight window generators mark such cells with -1. Treat a non-positive lower bound as "no window" in is_valid() so no weight window game is played, making zero and negative bounds equivalent. Previously a zero lower bound made the split branch demand a split at every checkpoint (weight over zero, clamped to max_split), multiplying the particle population until the split or weight cutoff limits stopped it. Split out of openmc-dev#3968 for focused review. Co-authored-by: shimwell <mail@jshimwell.com> Co-authored-by: jon-proxima <jon@proximafusion.com>
1 parent d06fdee commit 300cae0

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

include/openmc/weight_windows.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ struct WeightWindow {
5252
double weight_cutoff {DEFAULT_WEIGHT_CUTOFF};
5353
int max_split {10};
5454

55-
//! Whether the weight window is in a valid state
56-
bool is_valid() const { return lower_weight >= 0.0; }
55+
//! Whether the weight window is in a valid state. A non-positive lower
56+
//! bound indicates that no weight window information exists at this
57+
//! location (generators mark such cells with -1, and a lower bound of zero
58+
//! conventionally turns the weight window game off in a cell, as in MCNP
59+
//! wwinp files), in which case no weight window game is played.
60+
bool is_valid() const { return lower_weight > 0.0; }
5761

5862
//! Adjust the weight window by a constant factor
5963
void scale(double factor)

tests/regression_tests/weightwindows/test.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,61 @@ def test_weightwindows(shared_secondary, subdir):
119119
test.main()
120120

121121

122+
def test_zero_bound_windows_play_no_game(tmp_path):
123+
# A weight window lower bound of zero means no weight window information
124+
# exists there (MCNP wwinp files use zero to turn the game off in a cell),
125+
# so transport must proceed as if weight windows were disabled. Previously,
126+
# zero-bound windows demanded a split at every checkpoint (weight/0 ->
127+
# max_split), multiplying the particle population until terminated by the
128+
# split or weight cutoff limits.
129+
model = build_model(False)
130+
for ww in model.settings.weight_windows:
131+
ww.lower_ww_bounds = np.zeros_like(ww.lower_ww_bounds)
132+
ww.upper_ww_bounds = np.zeros_like(ww.upper_ww_bounds)
133+
sp_zero = model.run(cwd=tmp_path / 'zero_windows')
134+
135+
model.settings.weight_windows_on = False
136+
sp_off = model.run(cwd=tmp_path / 'windows_off')
137+
138+
with openmc.StatePoint(sp_zero) as sp:
139+
flux_zero = list(sp.tallies.values())[0].mean
140+
with openmc.StatePoint(sp_off) as sp:
141+
flux_off = list(sp.tallies.values())[0].mean
142+
143+
np.testing.assert_allclose(flux_zero, flux_off, rtol=1e-12)
144+
145+
146+
def test_zero_and_negative_bounds_equivalent(tmp_path):
147+
# Zero and negative lower bounds both mean that no weight window
148+
# information exists in a cell (generators mark such cells with -1, and
149+
# MCNP wwinp files use zero), so they must produce identical transport.
150+
# Unlike the all-zero case above, here particles are born under valid
151+
# windows and encounter the no-information region in flight; previously a
152+
# zero lower bound in that situation demanded a split at every checkpoint
153+
# in the cell (weight/0 -> max_split), multiplying the particle population,
154+
# while -1 played no game.
155+
def run_with(bound_value, subdir):
156+
model = build_model(False)
157+
for ww in model.settings.weight_windows:
158+
lb = np.array(ww.lower_ww_bounds, copy=True)
159+
ub = np.array(ww.upper_ww_bounds, copy=True)
160+
lb[3:, :, :, :] = bound_value
161+
ub[3:, :, :, :] = bound_value
162+
ww.lower_ww_bounds = lb
163+
ww.upper_ww_bounds = ub
164+
return model.run(cwd=tmp_path / subdir)
165+
166+
sp_zero = run_with(0.0, 'zero_region')
167+
sp_negative = run_with(-1.0, 'negative_region')
168+
169+
with openmc.StatePoint(sp_zero) as sp:
170+
flux_zero = list(sp.tallies.values())[0].mean
171+
with openmc.StatePoint(sp_negative) as sp:
172+
flux_negative = list(sp.tallies.values())[0].mean
173+
174+
np.testing.assert_allclose(flux_zero, flux_negative, rtol=1e-12)
175+
176+
122177
def test_wwinp_cylindrical():
123178

124179
ww = openmc.WeightWindowsList.from_wwinp('ww_n_cyl.txt')[0]

0 commit comments

Comments
 (0)