Combing to replace Splitting-Roulette for fission site sampling in "synchronize_bank()"
Description
Currently, OpenMC uses uniform Splitting-Roulette with fix-up for fission site sampling in synchronize_bank(). The fix-up is needed to exactly produce the targeted sample size; however, the fix-up introduces bias (even though negligible if the particle size is sufficiently large). This PR replaces the current fission site sampling with uniform Combing, which is unbiased and exactly produces the targeted sample size. The implementation maintains the reproducibility and scalability of synchronize_bank().
This PR changes the simulation random number stream, so a revision of regression test answer keys would be needed. The plan is to group this PR along with other PRs that also change the simulation random number stream: #2898.
cc: @paulromano
Splitting-Roulette and the fix-up
For k-eigenvalue simulation, OpenMC currently uses the uniform Splitting-Roulette technique followed by a fix-up to ensure exactly settings::n_particles are sampled.
The uniform Splitting-Roulette: https://github.com/openmc-dev/openmc/blob/cfe210da22367ce5cf928482e7b74e48c909a7ee/src/eigenvalue.cpp#L158-L177
The fix-up: https://github.com/openmc-dev/openmc/blob/cfe210da22367ce5cf928482e7b74e48c909a7ee/src/eigenvalue.cpp#L200-L223
The uniform Splitting-Roulette is unbiased and introduces minimum variance to the sampling process [Ref. 1]. However, Splitting-Roulette does not exactly produce the targeted population size. Since OpenMC requires each generation to run exactly with settings::n_particles, the fix-up is performed. This fix-up, however, introduces bias, even though negligible if the particle size is sufficiently large.
(Note that the fix-up is unnecessary if OpenMC allows changing particle sizes in a simulation. Also, it is worth noting that the population control itself is not strictly necessary, but it helps ensure that the particle population does not wildly vary in the early generations, especially if we have a poor initial guess.)
Alternative techniques
Two other population control techniques, Combing and Duplicate-Discard [Ref 1], are also unbiased and introduce minimum variance in the sampling process. However, unlike Splitting-Roulette, they produce exactly the targeted size. Among the two, Combing is simpler to implement and faster to perform (see [Ref 2] for a study on their implementations in OpenMC).
Combing may suffer from unwanted behavior due to possible correlation in the particle order in the bank. However, other than in contrived demonstrations, such unwanted behavior has not been reported in practice in multiple implementations of Combing in time-dependent Monte Carlo applications. In static simulations like k-eigenvalue calculation, the unwanted behavior becomes less relevant (it may increase the tally variance, but such evidence is lacking, as shown in [Ref 2]).
Test
The OPR benchmark was run with 1M particles in 200/500 inactive/active batches on 8 MPI processes, each with 72 threads.
With the current Splitting-Roulette with fix-up: k = 1.07473 +- 4.18987e-05 Total runtime = 277.428 s Site sampling runtime = 16.5646 s
With the proposed Combing: k = 1.07466 +- 4.1204e-05 Total runtime = 275.814 s Site sampling runtime = 17.1973 s
For a more extensive test, see [Ref 2].
Future plan
This fission site sampling is essentially population control [Ref 1], which can also be used in time-censussed particles in time-dependent simulations. The plan is to make the procedure a function so that it can be used in both eigenvalue and time-dependent fixed source simulations.
If it is desirable to support different population control techniques that the user can choose from, we can create a population control class like the one in https://github.com/ilhamv/openmc/tree/population_control.
Checklist
- [x] I have performed a self-review of my own code
- [x] I have run clang-format (version 15) on any C++ source files (if applicable)
- [x] I have followed the style guidelines for Python source files (if applicable)
- [x] I have made corresponding changes to the documentation (if applicable)
- [x] I have added tests that prove my fix is effective or that my feature works (if applicable)