lbm: fixed-centre moving-circle cut links (S2a)

MovingCircleLinks computes the cut links of each translating circle from an
FP64 {cx, cy, r} table over its swept band (same q/hit/clamp/fallback order
as build_cut_links, explicit _rn operations) and applies the unchanged
apply_bouzidi_link with spin wall velocity. obs keeps its contract; a
separate per-body diagnostics buffer records CME, the Wen term u_w*dm,
link_dm and the link count. Moving tables are built at initialize and
attached to the stepper, which then launches the kernel before the static
curved kernel; until then direct and run steps stay blocked. Displacement
is disabled: set_body offset/vx/vy on a translating circle raises before
mutation. Contract section 10a documents S2a and the S3 pending rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-10-30 07:35:02 +00:00
co-authored by Claude Opus 5.5
parent 983020b625
commit 0f8a428f07
8 changed files with 287 additions and 26 deletions
+25
View File
@@ -338,6 +338,31 @@ recorded as not runnable rather than replaced by another test.
run with a moving body raises before upload/launch; stationary unaffected). No kernels, no GPU runs, no
y-only VIV oscillator (S4), no force RHS.
## 10a. S2a — fixed-centre moving links (implemented on `claude/moving-bodies-s2a`)
- `MovingCircleLinks` (`kernels/step/moving_circle.cu`, dense double buffer)
runs before the static curved kernel when moving tables are attached: one
thread per (band cell, direction) slot, FP64 `{cx, cy, r}` at the applied
offset, q/hit/clamp/fallback in the order of `build_cut_links` with explicit
`_rn` operations (host/device bit parity is a test target, not a claim),
then the unchanged `apply_bouzidi_link` with spin wall velocity only.
- `obs` keeps its contract (CME and torque from `apply_bouzidi_link`). A
separate per-body diagnostics buffer receives `cme`, the Wen term
`u_w * dm`, `link_dm` and the link count from the same link outputs; it is
zeroed with obs and only exists when moving circles do. Optional
`slot_debug` (q, fallback, rx, ry per slot) is null in production.
- Displacement is disabled: `set_body(offset=..., vx=..., vy=...)` on a
translating circle raises before mutation, before and after initialize, so
no pending target can exist and `run`/`step`/direct `LBMStepper.step` all
hold at the applied geometry. `initialize()` never reads or consumes
`pending`. `stepper.blocked` is cleared only when the moving tables are
attached (initialize, stepper recreation).
- S3 rule (not implemented): once targets are re-enabled, any pending target
must raise in `run`/`step` and in `LBMStepper.step` alike before any launch,
swap or step-count change; zero-step calls never consume it.
- 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.
## 11. Remaining decisions
Structural RHS (section 6); motion-record layout; refill details; coupling