From 20b6c6fd8ddd066b46f58963ba98050ed4ea8cc4 Mon Sep 17 00:00:00 2001 From: DavidA Date: Fri, 21 Aug 2026 03:12:34 +0100 Subject: [PATCH] Fix Mgxs::get_xs CHI_DELAYED indexing the wrong tensor when gout is null MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gout == nullptr branches of the CHI_DELAYED case summed delayed_nu_fission instead of chi_delayed: - delayed_nu_fission is rank 3, [angle][delayed group][incoming group] (xsdata.cpp), but was indexed with four indices. tensor::Tensor's operator() performs no rank check, so the four-index read walks past the stride vector and reads out of bounds. - With dg == nullptr, the inner loop bound used delayed_nu_fission.shape(3), which is 0 for a rank-3 tensor, so the branch silently returned 0. Both branches are meant to return chi_delayed summed over outgoing groups; they now read chi_delayed with its actual shape [angle][delayed group][incoming group][outgoing group]. The chi_delayed dimension comment in xsdata.h documented the layout as [angle][in][out][delayed group] and is corrected to match the allocation in xsdata.cpp. No current caller reaches the fixed branches: the only external CHI_DELAYED caller (random_ray/flat_source_domain.cpp) always passes a non-null gout, so this produces no behavior change today — but any new caller would have hit silent out-of-bounds reads or a silent zero. Co-Authored-By: Claude Fable 5 --- include/openmc/xsdata.h | 2 +- src/mgxs.cpp | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/openmc/xsdata.h b/include/openmc/xsdata.h index c9dbde986b2..548430f1791 100644 --- a/include/openmc/xsdata.h +++ b/include/openmc/xsdata.h @@ -87,7 +87,7 @@ class XsData { // [angle][incoming group][outgoing group] tensor::Tensor chi_prompt; // chi_delayed has the following dimensions: - // [angle][incoming group][outgoing group][delayed group] + // [angle][delayed group][incoming group][outgoing group] tensor::Tensor chi_delayed; // scatter has the following dimensions: [angle] vector> scatter; diff --git a/src/mgxs.cpp b/src/mgxs.cpp index 1dc090ab969..0c94a4846b3 100644 --- a/src/mgxs.cpp +++ b/src/mgxs.cpp @@ -490,16 +490,19 @@ double Mgxs::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu, val = xs_t->chi_delayed(a, 0, gin, *gout); } } else { + // sum of chi_delayed over outgoing groups; chi_delayed has shape + // [angle][delayed group][in group][out group] (the previous code + // indexed the rank-3 delayed_nu_fission tensor with four indices) if (dg != nullptr) { val = 0.; - for (int g = 0; g < xs_t->delayed_nu_fission.shape(2); g++) { - val += xs_t->delayed_nu_fission(a, *dg, gin, g); + for (int g = 0; g < xs_t->chi_delayed.shape(3); g++) { + val += xs_t->chi_delayed(a, *dg, gin, g); } } else { val = 0.; - for (int g = 0; g < xs_t->delayed_nu_fission.shape(2); g++) { - for (int d = 0; d < xs_t->delayed_nu_fission.shape(3); d++) { - val += xs_t->delayed_nu_fission(a, d, gin, g); + for (int d = 0; d < xs_t->chi_delayed.shape(1); d++) { + for (int g = 0; g < xs_t->chi_delayed.shape(3); g++) { + val += xs_t->chi_delayed(a, d, gin, g); } } }