Skip to content

Naive Flux Linear Source Consistency Fix - #4111

Open
jtramm wants to merge 5 commits into
openmc-dev:developfrom
jtramm:ls_flux_consistency
Open

Naive Flux Linear Source Consistency Fix#4111
jtramm wants to merge 5 commits into
openmc-dev:developfrom
jtramm:ls_flux_consistency

Conversation

@jtramm

@jtramm jtramm commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR fixes a statistical inconsistency in the linear source flux update. Basically, the naive estimator currently uses per-batch "naive" volumes, but simulation-averaged centroids.

The naive volume treatment updates the flux from a single batch's rays, but the linear source is anchored to the simulation-averaged centroid, so the two halves of the update describe different sets of tracks. The difference (the source gradient dotted with the batch's centroid fluctuation) was silently absorbed by the flux estimate as noise, which breaks the exactness the naive treatment promises and can ignite negative fluxes in optically thin scatter-fed regions. About 15 lines of logic that affect linear source mode only.

Independent of the adaptive volume estimator PR (#4110), and reviewable in either order. That said, as I developed PR #4110 first and it also improves performance, I measure results against a "baseline" value generated by the PR #4110 branch, which is where the auto results below come from.

The fix

For source regions using the naive flux estimator, the flux update now adds back the source as the batch's tracks actually integrated it, evaluated at the batch centroid rather than the accumulated one. The term is applied only when a region updates with its own batch (naive) volume, which is exactly where it makes the update an exact per-batch track identity (the flux inherits the sign of the angular fluxes it averages). Regions updating with the simulation-averaged volume keep the original treatment, which already correctly matches the simulation-averaged volume with a simulation-averaged centroid.

Results

Stability on the shielding test problem (the "irradiation vault hall" problem from #4110, naive estimator, linear sources, 2,000 rays, 100 inactive and 100 active batches), negative slow-group bins of 85,750 and worst amplitude:

negative bins worst amplitude
before 5,724 −3.8e-1
after 72 −2.7e-3

Accuracy on the C5G7 overlay-mesh eigenvalue case (linear_xy, 200 rays, 102x102 mesh), where the naive estimator's linear-mode noise was previously severe:

k dev (pcm) AAPE
naive, before −5,514 4.09%
naive, after −3,524 1.58%
auto (default), before +45 0.65%
auto (default), after +45 0.65%

The high error on C5G7 is expected as the naive estimator is being used. For accurate results, the simulation averaged, hybrid, or adaptive estimators are far better. However, these results do demonstrate that the naive estimator becomes much more accurate, which is the goal, and does allow for hybrid/adaptive estimators to maintain accuracy in cases where more cells are demoted under low ray density conditions etc.

The auto rows were measured with this fix combined with the adaptive estimator PR: the default path is untouched at measurement precision, since under the adaptive family the term only fires in the rare batch where a transiently hit-starved region still carries its fitted gradients. Pinned naive and hybrid linear runs see the full correction.

Compatibility and testing

  • Flat source mode is bit-for-bit unaffected (the term is identically zero), and the simulation-averaged linear reference results are untouched byte for byte, confirming the original arithmetic survives where the term does not apply.
  • Reference results are regenerated for the linear-mode tests whose estimators receive the term (naive, and hybrid through its external-source and hit-starved regions). A new random_ray_linear_source_stability regression test pins the fix on a starved naive linear configuration.
  • The methods documentation gains one paragraph deriving the batch-sampled source and stating the pairing rule.

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format (version 18) on any C++ source files (if applicable)
  • I have followed the style guidelines for Python source files (if applicable)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

John Tramm and others added 5 commits July 23, 2026 02:36
The transport sweep evaluates each region's linear source against the
accumulated centroid, but a batch's tracks average that source at their
own track-length-weighted centroid, which fluctuates about the
accumulated one as rays sample the region unevenly. The flux update
added back only the flat source, so the difference -- the source
gradient dotted with the per-batch centroid fluctuation -- was silently
absorbed by the flux estimate as zero-mean noise with no flat-source
counterpart. This broke, in linear source mode only, the defining
property of a naive-volume update: that it adds no noise of its own
beyond the angular fluxes it averages (its error being ratio bias
alone). In near-cancellation regions (scattering ratio near one), where
the reduced source approximately equals the flux, the absorbed noise
can exceed the flux itself at modest hit counts and ignite
self-sustaining negativity that should be structurally impossible.

The update now adds back the source as actually integrated by the
batch's tracks, weighted by the ratio of the batch volume to the volume
in use. Under the batch (naive) volume the weight is one and the update
becomes an exact per-batch track identity, so the flux inherits the
sign of the angular fluxes; under the simulation-averaged volume the
weight prevents the correlation between batch volume and batch centroid
(sampled by the same rays) from becoming a systematic gradient-aligned
bias in cut regions. Flat source solves are unaffected.

On a fixed-source shielding reproducer (near-void hall with scattering
ratio 0.99, naive estimator, 2,000 rays), the fix reduces negative flux
bins from 5,788 (amplitudes up to 70% of the peak flux) to 21 (0.05% of
peak). Linear source test golds are regenerated, and a new regression
test pins the previously unstable naive-plus-linear regime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restrict the batch-sampled gradient term to regions updating with their
own batch (naive) volume, where adding it back makes the update an
exact per-batch track identity that inherits the sign of the angular
fluxes it averages. Regions updating with the simulation-averaged
volume keep the original update form. The omitted term cannot bias
their accumulated results, since the accumulated centroid is built from
the same batch centroids and the deviations sum to exactly zero, and
the original form samples the residual between the angular flux and the
linear source model, which carries less noise than the direct form
wherever the model tracks the field. The estimator matrix agrees: the
term is transformative for naive-volume updates and only adds variance
under simulation-averaged ones (e.g., 0.5% average pin power error on
C5G7 with the hybrid estimator at a 3.7% miss rate).

The simulation-averaged reference results are untouched by this commit,
confirming the original arithmetic survives bit for bit. The adaptive
family shifts slightly: a transiently hit-starved region carries its
fitted gradients for one batch before the flat fallback catches up, and
now receives the consistent update in that batch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9rxXRzNh13xQBGzePHEeK
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P9rxXRzNh13xQBGzePHEeK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant