From 307468b6714122836c86801c5f651f56b46409d4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 30 Oct 2026 16:10:32 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20moving=20circles=20=E2=80=94=20current?= =?UTF-8?q?=20status=20and=20user=20guide,=20BC=20capability,=20stage-1=20?= =?UTF-8?q?evidence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/moving_bodies.md gains a current status/user-guide section; the staged contract below it is kept unchanged as the design record. configs/CONFIG.md states the single dense outer-boundary package. docs/validation/moving_bodies_stage1.md summarizes the Dütsch and VIV evidence with SHAs and binding limitations. One stale source comment fixed (comment only). Co-Authored-By: Claude Opus 5.5 --- docs/moving_bodies.md | 68 ++++++++++++++++++++----- docs/validation/moving_bodies_stage1.md | 46 +++++++++++++++++ src/CelerisLab/configs/CONFIG.md | 14 +++++ src/CelerisLab/simulation.py | 2 +- 4 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 docs/validation/moving_bodies_stage1.md diff --git a/docs/moving_bodies.md b/docs/moving_bodies.md index 8930a53..8175803 100644 --- a/docs/moving_bodies.md +++ b/docs/moving_bodies.md @@ -1,17 +1,61 @@ -# Moving circles on the uniform dense grid — S0 DRAFT contract +# Moving circles on the uniform dense grid -Status: **DRAFT, not frozen** for the force RHS, kernels and physical -acceptance. Host-only S1 (state, validation, guards; no kernels) is on branch -`claude/moving-bodies-s1`; positive-step runs with a moving body are rejected -until S2. When S2 lifts that guard, `run(n > 1)` with a pending target must -raise `ValueError` before mutation (4a), and `run(0)` must not upload a motion -record or consume the pending target. Base: main -`b2034f87e03656c5f67ab88562a70d6c338b9918`. Scope approved by Frank (via TRON, -thread C0C78UFKGRM/1793335557.460509): uniform-grid prescribed translation and -single-cylinder free transverse VIV. Out of scope: refinement/blocked path, -pinball assembly, EsoPull, shifted storage, D3Q19, DynamisLab, manuscript. +## Status and user guide (current) -Items marked **OPEN** are undecided; items marked **CANDIDATE** are proposals. +Development-stage feature, integrated from the reviewed slices S1–S3a +(production code identical to `653fd997`). Physical evidence and its limits: +`docs/validation/moving_bodies_stage1.md`. The force used as a structural RHS +is a declared stage choice, not an established result. + +*What it does.* Translating circles (with optional spin) on the dense +double-buffer D2Q9 path: per-step cut links from an FP64 geometry record +(M2 `MovingCircleLinks`), reclassification and refill of covered/uncovered +cells (M1 `MovingCircleCells`), moving-wall Bouzidi with wall velocity +`u + omega x r`, and separate per-body diagnostics. + +*API.* +- `Simulation.add_body("circle", centre, radius, + translation=Translation(offset_box, max_speed))` before `initialize()`; + `offset_box = (x_min, x_max, y_min, y_max)` in lattice cells around the + base centre (must contain 0), `0 < max_speed ≤ .5`. +- `set_body(id, offset=(dx, dy), vx=..., vy=..., omega=...)` sets a pending + target (validated against the applied offset: box, Euclidean step ≤ .5 + cell, speed, no sliding hold); `vx`/`vy` are the interval wall velocity. +- `run(1)` advances a pending target and commits it only after the step + synchronizes with `no_donor == 0`; `run(n > 1)` with a pending target + raises; without a target `run(n)` holds the geometry (spin allowed). + Direct `LBMStepper.step` refuses while a target is pending. +- `moving_diagnostics()` returns per body the columns of + `MovingTables.DIAG` (CME, Wen term, link mass, cover/uncover momentum and + mass, eq_only, no_donor, crossings) accumulated since obs were zeroed; + `obs`/`read_force` keep their contract (CME on the body). +- `get_flags()` reads device flags back when moving circles exist. + +*Supported:* dense double buffer, D2Q9, FP32 unshifted, SRT/MRT, circles, +spin. *Rejected before mutation:* EsoPull, ddf shifting, D3Q19, refinement / +blocked steppers, Jets or surface actuation on a moving circle, +`sync_bodies` and checkpoints while a moving circle exists, swept bands that +touch the domain edge, other bodies, sensors or force regions. + +*Failure lifecycle.* Device-side failures (upload, step, sync, no_donor) +mark the Simulation failed; later run/step/sync/checkpoint calls and direct +stepper calls refuse until `close()`. + +*Known limitations.* No mass correction at curved walls (static or moving); +cover/uncover and Wen terms are diagnostics, not a selected force law; the +host loop costs a fixed per-step synchronization (≈ 1 ms/step measured on a +7.2 M-cell grid, run(1) class); outer boundaries are the single dense +channel package (see `configs/CONFIG.md`). + +## Design record (staged contract, kept as written) + +The sections below are the contract the slices were reviewed against +(S0 → S3a). They are kept unchanged for provenance; where they say "draft", +"proposed" or "until S2/S3", the status above supersedes them. + +Original scope (Frank via TRON, thread C0C78UFKGRM/1793335557.460509): +uniform-grid prescribed translation and single-cylinder free transverse VIV; +base main `b2034f87e03656c5f67ab88562a70d6c338b9918`. ## 1. Working standards diff --git a/docs/validation/moving_bodies_stage1.md b/docs/validation/moving_bodies_stage1.md new file mode 100644 index 0000000..999ab76 --- /dev/null +++ b/docs/validation/moving_bodies_stage1.md @@ -0,0 +1,46 @@ +# Moving circles — stage-1 evidence (development level) + +Owner criterion (Yanqi via TRON): prescribed motion and one free VIV case both +"reasonably close" to a predeclared reference = development-stage success. +This is practical closeness, not a formal validation claim. Every number +below is from Astra's receipts as posted in Slack C0C78UFKGRM thread +1793335557.460509; raw outputs stay on Horsea under `/tmp/celeris-results-*` +and the Mac evidence directory (not in git). + +## Code + +- Production: `src/` identical to `653fd997` (slices S1 `983020b6`, + S2a `b920a303`, S3a `653fd997`). CPU suites and GPU hold/crossing gates + passed on those slices (G0a/G0b population-bitwise; X1 crossing ledger). +- Research drivers: `research/duetsch_re100_kc5/` (`dd37883d`, capture + `a0aea3b9`) and `research/viv_re150/` (`fb507aa1`), run as committed. + +## Prescribed in-line oscillation (Dütsch et al. 1998, Re 100, KC 5) + +- Protocol: `docs/validation/duetsch_re100_kc5_protocol.md`. +- Frozen settling gate (.002 F_ref waveform): **FAILED** and kept on record: + D40 domain stage (20/40/60 D, 11.25 T) and the 60 D duration diagnostic + (31.25 T, 0/28 pairs; last waveform drift .00613 F_ref). +- Unscored late-cycle CME fits c_d ≈ 2.02–2.05, c_i ≈ 1.46–1.48 vs the + paper's computed (2.09, 1.45); fields clean and symmetric (owner view). + The owner accepts ~0.61 % cycle drift at D40 for this stage; the gate is + not re-scored. +- Fig. 8 LDA profiles: qualitative only (no digitized ordinates). + +## Free transverse VIV (Kolahdouz §4.1.1 setup, Qin §4.5 target) + +- Predeclaration: `docs/validation/leontini_viv_predeclare.md` (agreed at + `1abfe954`); run at `fb507aa1`, single case, D = 40, 75 D × 60 D. +- Result: status `scored`, 336,384 steps (t U/D = 336.4); A_max = .5464 D vs + .520 D (+5.1 %, inside the declared ±10 % band); mean half peak-to-peak + .5448 D; f/f_n = .955; block drifts .78/.29/.18 %, last-five spreads + .15/.11/.10 %; finite, no_donor = 0, no seed; 337.7 s, ~1.0 ms/step. + +## Limitations (binding) + +- One resolution (D40) per case; no grid or time convergence. +- Structural RHS = CME + Wen is a theory-motivated stage choice; CME-only + and node-impulse variants were not run as RHS; no force law is validated. +- Boundary mismatches: NEQ outlet with backflow clamp vs traction outlet; + finite box; the strict Dütsch settling failure is unexplained. +- No mass correction at curved walls; ~1 ms/step host-coupled overhead. diff --git a/src/CelerisLab/configs/CONFIG.md b/src/CelerisLab/configs/CONFIG.md index 57d38d6..5a63d47 100644 --- a/src/CelerisLab/configs/CONFIG.md +++ b/src/CelerisLab/configs/CONFIG.md @@ -86,6 +86,20 @@ step/one_step_*.cu → kernel 编排 - 转速 `omega` 属于运行时状态,可在步进期间更新;该更新不改变 `N_OBJS` 或 `OBS_*` 内存布局,因此**不需要**因 `omega` 变化触发重新编译。 - 力矩观测从 `obs` 的 torque segment 读取;force / torque / sensor 段统一由 `config_obs.h` 宏描述。 +### 外边界能力(Outer boundaries, dense `Simulation`) + +The dense path supports one channel package, not four independently +selectable sides: +- left x = 0: velocity inlet (`method.inlet.scheme`, `profile`, `physics.velocity`); +- right x = nx−1: outlet (`method.outlet.mode`; `neq_extrap` holds rho = 1 with + a `max(u, 0)` backflow clamp when `backflow_clamp` is set); +- bottom and top: one shared `y_wall_bc` (`bounce_back` halfway or + `free_slip`); corners are walls. +`y_wall_bc = "on_site_velocity"` switches to x-periodic with on-site y planes +and requires an object-free domain. There is no x/y-periodic or symmetry +option for domains with bodies; adding outer BC types is a separate design +question, not covered by these keys. + ### 稳定性默认窗口(Stability defaults) - 默认 `method.omega_guard = {min: 0.01, max: 1.99}`,用于约束碰撞频率与 LES 有效粘度路径。 diff --git a/src/CelerisLab/simulation.py b/src/CelerisLab/simulation.py index c6dd90d..464de2f 100644 --- a/src/CelerisLab/simulation.py +++ b/src/CelerisLab/simulation.py @@ -28,7 +28,7 @@ from .cuda.context import CudaContext, context_bound from .cuda import compiler from .lbm.descriptors import FLUID -# Translating circles step only through their moving tables (fixed centre in S2a). +# Translating circles step only through their moving tables (attached at initialize). PENDING_BLOCKED = "a pending translation target is advanced only by Simulation.run(1)" MOVING_BLOCKED = ("translating circles need the moving kernels and their tables (attached " "at initialize); "