Fixed periodic 2:1 coupled backend — bounded implementation, 2026-10-13

Decision: A, directional arrival override between coarse pull and collision.
Implemented and locally checked; no Simulation/Jet/general-AMR integration.
Default single-grid source files, existing geometry and all prior evidence are
unchanged. This increment adds 312 production lines and 222 test lines only.

A/B comparison against the active tree
  OneStep currently pulls, applies channel BC, computes moments, collides, and
  stores. LBMStepper runs Curved before OneStep, immediately swaps after launch,
  then runs force/sensor readers. LBMField macros/snapshot read current data;
  checkpoint saves BOTH current and spare buffers without a phase guard.
  All-FLUID flags do not remove OneStep's y=1/NY-2 wall correction. InitTubeFlow
  reconstructs channel flags. Reserved bits in active core/flags.cuh are only
  reservations: is_fluid does not exclude AMR and no skip-collision contract
  exists in init, body overlays or checkpoint. No old clone behavior was assumed.

  A keeps coarse source G immutable and replaces local incoming components.
  It needs the existing compact target/children tables (sorted together at
  upload), no source backup or full coarse override array. Only boundary-ring
  targets binary-search this table; performance optimization is not claimed.

  B could map incoming (q,K) to source (q,K-cq) because periodic pull is a
  bijection for each q. It is algebraically valid even for the eight corner-pass
  links, whose sources are UNCOVERED. But these overwritten source vectors no
  longer form consistent postcollision G. A safe B needs sparse backups (100
  floats for this patch), source-slot indices, exclusion of all macro, donor,
  snapshot, checkpoint and BC readers, same-stream scatter AFTER Curved and
  before OneStep, restoration to the captured old allocation before reuse or
  publication, and a failed-state policy if asynchronous errors prevent restore.
  Swapping pointers does not remove contamination from checkpoint's spare read.
  B also still needs true periodic and covered-cell behavior. A is clearer here.

Implementation and ownership
  src/CelerisLab/lbm/refinement_stepper.py: PeriodicPatchStepper(cfg, bounds,
      context=caller_owned_CudaContext), initialize(coarse_g,fine_g), step(n),
      download(), close(). Use its context-manager scope before closing context.
  src/CelerisLab/lbm/kernels/refinement.cu: separate compile entry, reusing active
      layout, pull, macro/equilibrium and unforced SRT operators. No channel
      kernels, physical flags, Curved, body, force or sensor dispatch.

  Each level owns two FP32 Q-major (9,ny,nx) arrays and its own module with fixed
  dimensions and omega. Both d_params force vectors and n_objects are zero.
  Coarse/fine viscosity gives tau .8/1.1 here; configs are copied, modules are
  separate, so async parameter mutation is unnecessary. One caller-owned CUDA
  context, one backend-owned stream; private compiler directories are removed
  after module loading. Allocations and modules are released on close; partial
  construction preserves the original exception while attempting cleanup.

  Explicit initial G arrays define the periodic state. initialize does NOT
  collide, invent channel flags, or run a channel initializer. The test constructs
  G0=C(F0) once. Each interval is:
    explode original coarse G into ALL fine halo once;
    fine pull + ACTIVE collision; inner halo only pulls, outer becomes NaN;
    fine pull + ACTIVE collision again; same halo policy;
    coarse periodic pull + ALL specified arrival overrides + ACTIVE collision;
    synchronize, publish coarse buffer swap and completed step count.
  The backend alone updates ghosts. At the second fine output, active cells hold
  G while inner ghosts retain F2 for coalescence. Some inner-ghost directions
  are legitimately invalid; all actual coalescence reads must be valid. Public
  downloads mask every halo cell back to NaN and return synchronized leaf G.
  No time-interpolated ghosts or nonequilibrium transfer scaling were added.

  Covered coarse cells are skipped and permanently NaN in BOTH buffers.
  Every uncovered arrival whose donor was covered is overridden before moments;
  the closed map also replaces eight grazing-corner links with uncovered donors.
  Explosion parents lie outside the patch. No BC/donor reader accesses covered
  values; this backend exposes no old LBMField macro/cache/checkpoint interface.
  Public arrays mark non-leaves NaN. There is no claim of complete multilevel
  restart, snapshot, object coupling or a ready Simulation adapter.

  Methods serialize via a lock. A failed interval can have overwritten fine G:
  no transactional rollback is claimed. The instance becomes failed, rejects
  download/step/initialize, and must be closed/recreated. Publishing happens only
  after stream synchronization. Cleanup tries all allocations even after an
  earlier free fails and does not replace a preexisting operation exception.

Reference basis
  Pinned CPUREF-0.3, tests/validation/multigrid/cpu_reference.py:
    SHA256 bba2a06a9f6517b32079ffff15e4060d8c3b7ed35f16ca134e1877226c9e4e1e.
    Its stored phase is arrival_f. Test-only C(F_ref) is compared to production G;
    that observation conversion is not an additional production collision.
  ref/lbmpy/src/lbmpy/relaxationrates.py:61 confirms acoustic tau scaling.
  ref/palabos/src/multiGrid/multiGridGenerator2D.hh:190 uses two fine substeps
    and distinct interface processing. Its interpolation/rescaling is a different
    method and was not imported into the pinned volumetric algorithm.
  Applied local .github/skills/lbm-ref-architecture-guard/SKILL.md: reference
    search, actual data-path map and scope were completed before editing.
  Independent local agent /root/coupling_review found no numerical-path blocker.
    Its cleanup and partial-failure test suggestions were implemented. This does
    not replace Claude/Grok/TRON review; Claude's earlier local_stress code review
    remains incomplete.

Validation plan fixed before running
  No force/objects, double periodic 16x16 coarse, [4,12)^2 patch, 24x24 fine
  including halo4, SRT tau .8/1.1. FP32 GPU (existing fast_math/FMA) versus FP64
  pinned reference. Rest and seed1 nonequilibrium (u=.03,-.02, relative random
  perturbation amplitude 1e-3) each <=8 coarse steps. Populations/corner packets
  max absolute tolerance 3e-6, leaf mass/momentum absolute drift AND reference
  discrepancy 2e-4. No tolerance was changed after results.
  Actual device-write instrumentation checks collision count per leaf, zero
  halo/covered collision, explosion per ghost and per-slot coalescence ownership.
  The audit entry defines one diagnostic macro in a PRIVATE build and includes
  the real refinement.cu; ordinary compile entry is separately smoke-tested.
  No old 7x32 matrix, Jet replay, physical stability sweep or large datasets.

Observed results
  CPU geometry: 9/9 pass under 256MiB address-space/2MiB file/core0 limits.
  CPU cleanup fault-injection: 1/1 pass under the same limits.
  GPU audit, rest 8 steps:
    max population error 2.11927626e-7
    max leaf drift 4.43765894e-5; max leaf reference error 4.62839387e-5
    max corner packet error 7.65754117e-9
  GPU audit, nonequilibrium seed1 8 steps:
    max population error 1.67235548e-7
    max leaf drift 2.23806128e-5; max leaf reference error 2.20813948e-5
    max corner packet error 1.09677929e-8
  At every step: coarse leaf count=step, fine leaf count=2*step, halo/covered
    count=0, explosion writes/ghost=step, coalescence writes/slot=step; PASS.
    Hop2 finite mask, all coalescence reads and all eight corner packets PASS.
  Normal entry: rest 1 step PASS. Eight-step equivalence evidence comes from
    the audit build of the same kernel, not an eight-step normal-entry run.
  Failure after explosion+two fine hops actually completed: 0 coarse steps
    published, download/step rejected, close passed. Separate targeted test;
    eight-step cases were not rerun to add this failure test.

Budgets and provenance
  Before each GPU run: physical GPU 0/1 idle (0%, 5MiB, no compute processes).
  Used only physical GPU0, UUID GPU-e8853ae7-a302-6a17-bcfa-aa767e9ed20c.
  Exact Python /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python; runtime asserts
  CelerisLab package and kernel root are from /home/frank14f/CelerisLab/src.
  PYTHONPATH explicit, no user site/bytecode, BLAS one thread, CUDA cache disabled.
  Production arrays 66,464 bytes, audit-only arrays 36,608 bytes: total 103,072
  (<128KiB). This excludes CUDA context/module overhead, not measured as arrays.
  GPU child watched at 50ms intervals, killed if sampled RSS exceeds 512MiB or
  120s. CUDA virtual address space was NOT restricted to 256MiB; driver mapping
  needs more. Largest sampled RSS 194,355,200 bytes (~185.35MiB); child getrusage
  184.902MiB. Full first run 3.77s; partial-failure check 2.29s. GPU logs total
  880 bytes (<2MiB); no data dumps, plots, dependency installs or system changes.
  CPU logs summarized from tool executions in cpu_validation.json. Exact GPU
  commands, environment, exit status, wall time and RSS are in gpu*.json; actual
  stdout/stderr in gpu*.txt. Compiler scratch cleaned on every build.

Audit and next boundary
  baseline.json contains the pre-edit tree and 311 preserved old-file hashes
  (including the prior evidence hash scope). incremental.patch contains only the
  THREE new code/test files; existing dirty changes are not folded into it.
  manifest.json records unchanged-baseline verification and artifact hashes.
  No commit/staging/push, DynamisLab or old file cleanup/modification occurred.

  This validates bounded implementation equivalence, NOT interface accuracy,
  stress transfer, long-time stability or 32-step production performance. The
  prior ~2.9% excess shear decay remains a research concern. Next joint decisions
  are whether/how to expose this narrow periodic backend through Simulation and
  when to implement an explicit two-level restart schema; neither is silently
  included here. No generic hierarchy or minimal flat-wall Jet work was started.

Authorization, verbatim as relayed by the coordinating thread
<transcript_evidence>
user（Sentinel_ed1ee5edd5e88191a1aaa4d710ce523f）: 推进吧，～/CelerisLab就是开发环境，可以改动，只要符合架构风格。遇到问题可以用undermind看文献，也可以让grok搜索互联网信息，还可以参考开源项目。
user（Sentinel_d0d3a42b2c088191aa8aebc105fb1b27）: 允许，你用GPU验证都行
</transcript_evidence>
