Skip to content

MOL + tracer particles: MAC velocities have 0 ghost faces, AdvectWithFlow reads out of bounds #183

Description

@WeiqunZhang

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions