Repository navigation
IB: size the ownership hand-off arrays by the neighborhood radius - #1944
sbryngelson wants to merge 2 commits into
Conversation
s_handoff_ib_ownership hard-coded max_nbrs = 26, but its send/receive loops visit all (2R+1)^num_dims - 1 neighbor offsets (124 for R = 2, 342 for R = 3 in 3-D), so requests, recv_neighbor_list and recv_bufs overflowed for ib_neighborhood_radius >= 2. Allocate them from the actual radius. The per-neighbor receive buffer was also sized for num_local_ibs_max (~5 MB per neighbor); a rank can hand off at most every global patch, so size it by min(num_local_ibs_max, num_gbl_ibs). Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The corrected multi-rank radius-dependent path needs an automated regression test.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Fixes moving-IB ownership hand-off buffer overruns for neighborhood radii greater than one.
Changes:
- Dynamically sizes neighbor/request arrays from radius and dimensionality.
- Reduces per-neighbor buffer capacity using the global IB count.
- Reuses the computed neighbor count during unpacking.
| File | Description |
|---|---|
src/simulation/m_ibm.fpp |
Corrects MPI hand-off array and buffer sizing. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| max_nbrs = (2*ib_neighborhood_radius + 1)**num_dims - 1 | ||
| allocate (send_buf(buf_size), recv_bufs(buf_size, max_nbrs), requests(2*max_nbrs), recv_neighbor_list(max_nbrs)) |
There was a problem hiding this comment.
Added in 29de766: 3D -> 2 MPI Ranks -> IBM Moving Sphere -> ib_neighborhood_radius=2 (2440B4AE, ppn=2). It is the existing 2-rank IB sphere with moving_ibm = 1, vel(1) = 0.01 (under 1% of a cell over 50 steps, so no cell crosses the surface) and ib_neighborhood_radius = 2. The golden is GNU 12.3 + MPI, Release, generated on a Frontier CPU compute node.
Evidence:
- This branch passes in both Release and Debug (
-fcheck=all). masterin Debug aborts withm_ibm.fpp:1782: Index '27' of dimension 1 of array 'recv_neighbor_list' above upper bound of 26.masterin Release passes: at 2 ranks the overrun is silent. So the test catches a regression in bounds-checked builds (the CI GNUreldebuglanes use-fcheck=bounds,pointer), and is coverage of the R>1 path otherwise.
Add "3D -> 2 MPI Ranks -> IBM Moving Sphere -> ib_neighborhood_radius=2" (2440B4AE). The ownership hand-off loops over all 124 radius-2 offsets on any multi-rank run, so two ranks exercise the radius-sized neighbor arrays. The sphere moves < 1% of a cell, so no cell crosses its surface. Golden generated with GNU 12.3, MPI, Release. On master a bounds-checked build aborts: Index '27' of array 'recv_neighbor_list' above upper bound of 26. Co-Authored-By: Claude <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1944 +/- ##
==========================================
+ Coverage 62.64% 62.98% +0.34%
==========================================
Files 86 86
Lines 22425 22426 +1
Branches 3325 3325
==========================================
+ Hits 14048 14126 +78
+ Misses 6119 6018 -101
- Partials 2258 2282 +24 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|

Description
s_handoff_ib_ownership(src/simulation/m_ibm.fpp) overruns its neighbor arrays whenib_neighborhood_radius >= 2, which crashes multi-node runs with a moving IB in 3D.Root cause.
max_nbrs = 26is a hard-coded parameter, andrequests(2*max_nbrs),recv_neighbor_list(max_nbrs)andrecv_bufs(:, max_nbrs)are sized from it. The receive loop, though, visits all(2R+1)^num_dims - 1offsets (124 for R = 2, 342 for R = 3 in 3D) and writesrecv_neighbor_list(nbr_idx)andrequests(nreqs)for each one. The per-neighbor tags were already widened for R > 1, but the arrays were not. Separately, each receive buffer is sized fornum_local_ibs_maxpatches (about 5 MB per neighbor), so every step posts megabytes ofMPI_PACKEDreceives even when the sizes are legal.Fix.
requests,recv_neighbor_listandrecv_bufsfrommax_nbrs = (2R+1)**num_dims - 1, and reusemax_nbrsin the unpack loop.min(num_local_ibs_max, num_gbl_ibs)patches. A rank can hand off at most every global patch.Behavior is unchanged for R = 1, apart from the smaller buffers. CFD results are unchanged.
Verification
This was run in production on OLCF Frontier (CCE 19, OpenACC GPU build,
--case-optimization) with the same patch applied to3dc5b2f, which is the currentmaster:ib_neighborhood_radius = 3. The run aborted in the first steps after about 65,000cxil_map: write errorlines, then failed with:MPI_Irecv(buf=..., count=5120004, MPI_PACKED, src=31, tag=216, ...) failed ... OFI tagged recv failed (Invalid argument).The out-of-bounds writes happen on any multi-rank run with R >= 2, because
recv_neighbor_list(nbr_idx)is written for every offset, includingMPI_PROC_NULLones. With few ranks, though, they usually corrupt memory silently instead of crashing. The production crash needed many real neighbors (64 ranks across 8 nodes).Regression test (added):
3D -> 2 MPI Ranks -> IBM Moving Sphere -> ib_neighborhood_radius=2(2440B4AE),ppn = 2. It is the existing2 MPI Ranks -> IBM Spheresetup (30x30x50 cells), with the sphere given a prescribed velocity (moving_ibm = 1,vel(1) = 0.01) so the hand-off runs every step, andib_neighborhood_radius = 2. The sphere moves less than 1% of a cell in 50 steps, so no cell crosses its surface and the golden is not sensitive to roundoff. The golden was generated on a Frontier CPU compute node with GNU 12.3 (gcc-native/12.3) + Cray MPICH, MPI, Release, matching the existing2 MPI Ranksgoldens. Results:-fcheck=all)master(m_ibm.fppat3dc5b2f)-fcheck=all)At line 1782 of m_ibm.fpp: Index '27' of dimension 1 of array 'recv_neighbor_list' above upper bound of 26masterSo, to be explicit: this test guards the fix only in bounds-checked builds. The CI
reldebugGNU lanes compile with-fcheck=bounds,pointer, which would catch a regression. In Release builds it is coverage of the R > 1 multi-rank hand-off path. The existing testsAFBACA70(2-rank IB sphere),CE232828(3D 2 ranks) andD7E7DE04(moving IB, pitch ramp) still pass.simulationalso builds with CCE 19 on CPU. Precheck passes apart from twotest_thermochemcases that fail on the Frontier login node because they compile with the system/usr/bin/gfortran(addressed by #1943).Contribution Policy
We do not accept pull requests generated primarily by AI without genuine understanding or real-world usage context.
All contributions are expected to demonstrate:
If these expectations are not met, we would prefer to implement the changes ourselves rather than spend time reviewing low-effort submissions.
Acknowledgement
This PR was prepared with the assistance of an AI tool (Claude Code). The bug was found, and the fix exercised, in multi-node production runs on Frontier.
PR template credit: junegunn