From e4c074476027154ac615fbe1bf2a7219f647e665 Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:01:24 -0500 Subject: [PATCH 1/3] Fix the two-component estimator. --- src/eigenvalue.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp index bc8dcc9ea77..cbdc017a343 100644 --- a/src/eigenvalue.cpp +++ b/src/eigenvalue.cpp @@ -568,17 +568,26 @@ int openmc_get_keff(double* k_combined) // These equations are derived analogously to that done in the paper by // Urbatsch, but are simpler than for the three estimators case since the // block matrices of the three estimator equations reduces to scalars here + // See LA-12658-MS, Eqs. 36 and 40. - // Store the commonly used term - double f = kv[i] - kv[j]; - double g = cov(i, i) + cov(j, j) - 2.0 * cov(i, j); + // We can use variance/covariances for the mean as the division by (n - 1) + // cancels. + const double f = cov(i, i) + cov(j, j) - 2.0 * cov(i, j); + const double w_1 = (cov(j, j) - cov(i, j)) / f; + const double w_2 = (cov(i, i) - cov(i, j)) / f; - // Calculate combined estimate of k-effective - k_combined[0] = kv[i] - (cov(i, i) - cov(i, j)) / g * f; + k_combined[0] = kv[i] * w_1 + kv[j] * w_2; - // Calculate standard deviation of combined estimate - k_combined[1] = (cov(i, i) * cov(j, j) - cov(i, j) * cov(i, j)) * - (g + n * f * f) / (n * (n - 2) * g * g); + // We must use the sums of squares for the variance as the division by + // (n - 1) does not cancel. + const double s_ii = cov(i, i) * (n - 1); + const double s_jj = cov(j, j) * (n - 1); + const double s_ij = cov(i, j) * (n - 1); + + const double g = s_ii - (s_ii - s_ij) * (s_ii - s_ij) / (f * (n - 1)); + const double h = 1.0 / n + (kv[i] - kv[j]) * (kv[i] - kv[j]) / (f * (n - 1)); + + k_combined[1] = 1.0 / (n - 2) * g * h; k_combined[1] = std::sqrt(k_combined[1]); } return 0; From dad594879d39843f6d7d7d048ec0d2a7aa072e5b Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:06:57 -0500 Subject: [PATCH 2/3] Regold MG survival biasing test for the 2-component fix. --- src/eigenvalue.cpp | 4 ++-- tests/regression_tests/mg_survival_biasing/results_true.dat | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp index cbdc017a343..fe39dc01689 100644 --- a/src/eigenvalue.cpp +++ b/src/eigenvalue.cpp @@ -570,7 +570,7 @@ int openmc_get_keff(double* k_combined) // block matrices of the three estimator equations reduces to scalars here // See LA-12658-MS, Eqs. 36 and 40. - // We can use variance/covariances for the mean as the division by (n - 1) + // We can use the \Sigma matrix for the mean as the division by (n - 1) // cancels. const double f = cov(i, i) + cov(j, j) - 2.0 * cov(i, j); const double w_1 = (cov(j, j) - cov(i, j)) / f; @@ -578,7 +578,7 @@ int openmc_get_keff(double* k_combined) k_combined[0] = kv[i] * w_1 + kv[j] * w_2; - // We must use the sums of squares for the variance as the division by + // We must use the S matrix for the variance as the division by // (n - 1) does not cancel. const double s_ii = cov(i, i) * (n - 1); const double s_jj = cov(j, j) * (n - 1); diff --git a/tests/regression_tests/mg_survival_biasing/results_true.dat b/tests/regression_tests/mg_survival_biasing/results_true.dat index 4b26978ada6..4f14ad167a1 100644 --- a/tests/regression_tests/mg_survival_biasing/results_true.dat +++ b/tests/regression_tests/mg_survival_biasing/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.889968E-01 9.144186E-03 +9.889968E-01 1.823442E-02 From 62e74daa0cf03d991cf228545ddea9d4ae2f9c11 Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:09:00 -0500 Subject: [PATCH 3/3] Style changes. --- src/eigenvalue.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp index fe39dc01689..bde357721c7 100644 --- a/src/eigenvalue.cpp +++ b/src/eigenvalue.cpp @@ -585,7 +585,8 @@ int openmc_get_keff(double* k_combined) const double s_ij = cov(i, j) * (n - 1); const double g = s_ii - (s_ii - s_ij) * (s_ii - s_ij) / (f * (n - 1)); - const double h = 1.0 / n + (kv[i] - kv[j]) * (kv[i] - kv[j]) / (f * (n - 1)); + const double h = + 1.0 / n + (kv[i] - kv[j]) * (kv[i] - kv[j]) / (f * (n - 1)); k_combined[1] = 1.0 / (n - 2) * g * h; k_combined[1] = std::sqrt(k_combined[1]);