Severity: medium · Category: memory-ub · Fix order: 13 of 29 — fix this 13th.
Filenames are numbered in reverse fix order: 001 = fix last, 029 = fix first. This file is 017.
Location: src/incflo_apply_corrector.cpp:183
Based on commit 7307d872 (line numbers refer to that tree).
The defect
What is wrong — With MOL advection and no EB, u_mac/v_mac/w_mac are defined with nghost_mac()==0 ghost cells, but evolveTracerParticles -> incflo_PC::AdvectWithFlow requires >=1 ghost face (it asserts nGrow()>=1, and mac_interpolate reads transverse-neighbor faces outside the valid box).
Why it matters
advection_type=MOL, non-EB build with INCFLO_USE_PARTICLES and incflo.use_tracer_particles=1: debug builds abort on the AMREX_ASSERT in incflo_PCEvolve.cpp:36; release builds read out-of-bounds face data for particles in cells bordering grid edges, giving garbage particle velocities or crashes.
Suggested fix
In both ApplyPredictor and ApplyCorrector (the allocation is twinned at incflo_apply_predictor.cpp:88-98), allocate u_mac/v_mac/w_mac with at least one ghost face whenever m_use_tracer_particles is set. incflo_PC::AdvectWithFlow asserts nGrow() >= 1 because AMReX's linear_interpolate_to_particle reads the two faces bracketing the particle in each direction without clamping, so faces one cell outside the valid box must exist and hold neighbor data. Allocation alone is not enough: the umac FillPatch in compute_convective_term (incflo_compute_advection_term.cpp:244) is gated on nghost_mac() > 0 and never runs for MOL, so a FillBoundary(geom[lev].periodicity()) on each MAC component before evolveTracerParticles is needed to populate interior ghost faces. Maintainer decision: FillBoundary leaves fine-level ghost faces at coarse-fine boundaries at their setBndry(0) value; if particles near those boundaries matter, reuse the FillPatchSingleLevel/FillPatchTwoLevels path already used for Godunov (e.g., gate on the actual nGrow) instead.
--- a/src/incflo_apply_corrector.cpp
+++ b/src/incflo_apply_corrector.cpp
@@ -76,7 +76,11 @@
// Allocate space for the MAC velocities
// *************************************************************************************
Vector<MultiFab> AMREX_D_DECL(u_mac(finest_level+1), v_mac(finest_level+1), w_mac(finest_level+1));
int ngmac = nghost_mac();
+#ifdef INCFLO_USE_PARTICLES
+ // Tracer particle advection requires at least one ghost face for interpolation
+ if (m_use_tracer_particles && ngmac < 1) { ngmac = 1; }
+#endif
for (int lev = 0; lev <= finest_level; ++lev) {
AMREX_D_TERM(u_mac[lev].define(amrex::convert(grids[lev],IntVect::TheDimensionVector(0)), dmap[lev],
@@ -179,8 +183,15 @@
#ifdef INCFLO_USE_PARTICLES
// **************************************************************************************
// Update the particle positions
// **************************************************************************************
+ if (m_use_tracer_particles) {
+ for (int lev = 0; lev <= finest_level; ++lev) {
+ AMREX_D_TERM(u_mac[lev].FillBoundary(geom[lev].periodicity());,
+ v_mac[lev].FillBoundary(geom[lev].periodicity());,
+ w_mac[lev].FillBoundary(geom[lev].periodicity()););
+ }
+ }
evolveTracerParticles(AMREX_D_DECL(GetVecOfConstPtrs(u_mac), GetVecOfConstPtrs(v_mac),
GetVecOfConstPtrs(w_mac)));
#endif
}
Allocates MAC velocities with >=1 ghost face when tracer particles are active (satisfies the nGrow>=1 assert in incflo_PCEvolve.cpp), then FillBoundary before evolveTracerParticles so mac_interpolate reads valid interior/periodic ghost faces. Physical-domain ghost faces stay 0.0 from the existing setBndry; maintainer may prefer replicating the IncfloVelFill FillPatch from incflo_compute_advection_term.cpp for inflow/outflow boundaries.
Diff(s) are against 7307d872, written from the current source and verified only with git apply --check — never compiled, never run, never applied to the tree. Treat them as precise intent, not tested patches.
Verification evidence
F054 — confirmed (one verifier lens)
Lens 1 (refutation attempt): incflo.H:800-802: nghost_mac() returns (m_advection_type == "MOL") ? 0 : 1 (non-EB); apply_corrector.cpp:82-87 defines u_mac with that ngmac and line 183 passes it to evolveTracerParticles; incflo_PCEvolve.cpp:36 asserts a_umac[0].nGrow() >= 1; AMReX linear_interpolate_to_particle uses l - 0.5, floor, and reads i0..i0+1 unclamped, so grid-edge particles index outside a 0-ghost face FAB. No guard forbids MOL + incflo.use_tracer_particles; no fix in git history.
Based on commit 7307d872, which is also the tree the audit verified against. From an automated audit of src/. Audit finding id: F054. Reviewer unit(s): theme:restart-regrid. Nothing here was compiled or run — the failure scenarios are code reasoning, so the reaching configuration above is the cheapest way to confirm or refute it.
Severity: medium · Category: memory-ub · Fix order: 13 of 29 — fix this 13th.
Filenames are numbered in reverse fix order:
001= fix last,029= fix first. This file is017.Location:
src/incflo_apply_corrector.cpp:183Based on commit
7307d872(line numbers refer to that tree).The defect
What is wrong — With MOL advection and no EB, u_mac/v_mac/w_mac are defined with nghost_mac()==0 ghost cells, but evolveTracerParticles -> incflo_PC::AdvectWithFlow requires >=1 ghost face (it asserts nGrow()>=1, and mac_interpolate reads transverse-neighbor faces outside the valid box).
Why it matters
advection_type=MOL, non-EB build with INCFLO_USE_PARTICLES and incflo.use_tracer_particles=1: debug builds abort on the AMREX_ASSERT in incflo_PCEvolve.cpp:36; release builds read out-of-bounds face data for particles in cells bordering grid edges, giving garbage particle velocities or crashes.
Suggested fix
In both ApplyPredictor and ApplyCorrector (the allocation is twinned at incflo_apply_predictor.cpp:88-98), allocate u_mac/v_mac/w_mac with at least one ghost face whenever m_use_tracer_particles is set. incflo_PC::AdvectWithFlow asserts nGrow() >= 1 because AMReX's linear_interpolate_to_particle reads the two faces bracketing the particle in each direction without clamping, so faces one cell outside the valid box must exist and hold neighbor data. Allocation alone is not enough: the umac FillPatch in compute_convective_term (incflo_compute_advection_term.cpp:244) is gated on nghost_mac() > 0 and never runs for MOL, so a FillBoundary(geom[lev].periodicity()) on each MAC component before evolveTracerParticles is needed to populate interior ghost faces. Maintainer decision: FillBoundary leaves fine-level ghost faces at coarse-fine boundaries at their setBndry(0) value; if particles near those boundaries matter, reuse the FillPatchSingleLevel/FillPatchTwoLevels path already used for Godunov (e.g., gate on the actual nGrow) instead.
Allocates MAC velocities with >=1 ghost face when tracer particles are active (satisfies the nGrow>=1 assert in incflo_PCEvolve.cpp), then FillBoundary before evolveTracerParticles so mac_interpolate reads valid interior/periodic ghost faces. Physical-domain ghost faces stay 0.0 from the existing setBndry; maintainer may prefer replicating the IncfloVelFill FillPatch from incflo_compute_advection_term.cpp for inflow/outflow boundaries.
Diff(s) are against
7307d872, written from the current source and verified only withgit apply --check— never compiled, never run, never applied to the tree. Treat them as precise intent, not tested patches.Verification evidence
F054— confirmed (one verifier lens)Lens 1 (refutation attempt): incflo.H:800-802:
nghost_mac()returns(m_advection_type == "MOL") ? 0 : 1(non-EB); apply_corrector.cpp:82-87 defines u_mac with that ngmac and line 183 passes it to evolveTracerParticles; incflo_PCEvolve.cpp:36 assertsa_umac[0].nGrow() >= 1; AMReX linear_interpolate_to_particle usesl - 0.5, floor, and reads i0..i0+1 unclamped, so grid-edge particles index outside a 0-ghost face FAB. No guard forbids MOL + incflo.use_tracer_particles; no fix in git history.Based on commit
7307d872, which is also the tree the audit verified against. From an automated audit ofsrc/. Audit finding id: F054. Reviewer unit(s): theme:restart-regrid. Nothing here was compiled or run — the failure scenarios are code reasoning, so the reaching configuration above is the cheapest way to confirm or refute it.