lbm: translating circles move with refill (S3a)

MovingCircleCells reclassifies swept-band cells from immutable old/new FP64
predicates: covered cells add their raw momentum and mass to diagnostics and
become solid; uncovered cells are refilled in all nine slots from donors
fluid in both geometries (mean density, NEQ from the best-aligned donor,
wall velocity at the cell), counting eq_only and no_donor. MovingCircleLinks
adds the translation velocity to the wall velocity. Simulation.run(1)
uploads the motion record, runs M1 then M2, synchronizes, rejects a nonzero
no_donor count and only then commits the target and uploads the hold
record; any failure marks the Simulation failed. Targets block direct
stepper calls and multi-step runs. get_flags reads device flags back when
translating circles exist. Contract section 10b.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-30 08:51:20 +00:00
1 parent b920a303a4
commit d50b8ba1be
6 files changed
+313 -43

No files matched your search

+28
View File
@@ -363,6 +363,34 @@ recorded as not runnable rather than replaced by another test.
- Not validation: a pass of the zero-motion gates says nothing about moving
geometry. GPU parity (G0a/G0b) is unverified until run on a free device.
## 10b. S3a — translation with refill (implemented on `claude/moving-bodies-s3a`)
- Targets are enabled again (4a). `set_body(offset, vx, vy)` validates against
`applied`; a pending target blocks direct `LBMStepper.step(n > 0)` before any
launch; `run(n > 1)` with a target raises before mutation; `run(0)` never
consumes it; `run(1)` advances it.
- Per advancing step, on one stream: upload the immutable FP64 records
`{c_old, c_new, r, u}` (only when changed) → M1 `MovingCircleCells` → M2
`MovingCircleLinks` (`u_w = u + omega x r` at the hit point) → static curved →
`OneStep` → swap → force region → sensors → synchronize → read `no_donor` →
commit (`applied := pending.offset`) → upload the hold record
(`c_old = c_new = applied`, `u = 0`). Hold steps launch no M1 and are the
S2a path. Any failure from the upload on marks the circles and the
Simulation failed; nothing is committed.
- M1 classifies with the old/new predicates only (no flag reads). Covered
cells add raw `sum c G` / `sum G` of `G^{n-1}` to `cover_*` and become
`SOLID|OBSTACLE|BC_CURVED`. Uncovered cells: donors are fluid in both
geometries; `rho_bar` over all of them; NEQ from the donor with the largest
unnormalized `c·n > 0` (first direction wins ties, `n` from `c_new`);
`u_w` (translation + spin) at the cell position; all nine slots written;
raw `sum c G`, `sum G` of the refill go to `uncover_*`; no donor →
`f_eq(RHO, u_w)` plus `no_donor` (hard failure before commit); no NEQ donor
→ `eq_only`.
- `get_flags()` reads the device flags back (synchronized) when moving tables
exist; otherwise it returns the host array as before.
- Not selected: the structural force. CME+node vs CME+Wen stay OPEN until X1
and G4 have run.
## 11. Remaining decisions
Structural RHS (section 6); motion-record layout; refill details; coupling