Tests load research drivers via importlib under unique module names instead of a bare 'import run' (shared-process collision between the Dütsch and VIV drivers). lifecycle.md qualifies immutable geometry and the host-only get_flags for translating circles; supported_settings.md points to the dense-only moving-circle feature; leontini_viv_predeclare.md is renamed viv_re150_predeclare.md (Re 150 Kolahdouz/Qin case) with references updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97 lines
8.5 KiB
Markdown
97 lines
8.5 KiB
Markdown
# Supported settings: 2D Jet + fixed multilevel refinement (candidate 888c8038)
|
|
|
|
Every entry names the guard that enforces it (file and function or kernel guard,
|
|
at source revision 888c80381c006e976be2af8a452288729fc17c1b) and, where one
|
|
exists, an existing test that exercises it. A setting not listed here is not
|
|
claimed. Observations at the end are tied to the exact case in which they were
|
|
measured; they are not general bounds.
|
|
|
|
## Lattice, storage, collision
|
|
|
|
| Setting | Supported | Guard |
|
|
|---|---|---|
|
|
| Dimension / lattice | 2D D2Q9 only (3D refinement is future work) | `lbm/refinement.py` `FixedPatch2D.from_config`; `#error` guards in `lbm/kernels/blocked.cu` |
|
|
| Precision / streaming | FP32 storage, double buffer | same guards |
|
|
| Collision on refinement levels | SRT or MRT; TRT and LES rejected | `lbm/refinement.py` `FixedPatch2D.from_config` (re-checked for fine boundaries in `prepare_fine_boundary`) |
|
|
| Shifted (ddf_shifting) storage | supported (every level is blocked); one representation on all levels | `lbm/refinement_stepper.py` `FixedPatchStepper._check_storage` |
|
|
| Fine relaxation | 1/tau_fine must lie inside the configured omega guards | `lbm/refinement.py` `FixedPatch2D.from_config` |
|
|
| Single blocked level `FixedPatchStepper(refinements=[], level_blocks=[(by, bx)], level_objects=[circles])` (replaces `PeriodicBlockStepper`, removed in 8e1feff) | doubly periodic, SRT only, no LES/Jets/projection/exchange observation, stationary passive circles; `download()` returns a 1-tuple | `lbm/refinement_stepper.py` `_check_levels`, `FixedPatchStepper.__init__`; `lbm/blocks.py` `static_circle_tables` |
|
|
| Refinement storage | blocked on every level: `level_blocks` is required, one tile `(by, bx)` per level dividing that level; a whole-level tile (`(ny, nx)` at the root, the fine window shape for one rectangle) always divides. Dense and mixed dense/blocked storage were removed (parity of D/D, D/B and B/B recorded at 1573942 and 2469af7) | `lbm/refinement_stepper.py` `_check_levels`, `FixedPatchStepper.__init__` |
|
|
|
|
Tests: `tests/unit/test_refinement_mrt.py`, `tests/validation/multigrid/test_refinement_mrt_gpu.py`,
|
|
`tests/unit/test_shifted_storage.py`, `tests/unit/test_shifted_block_operators.py`.
|
|
|
|
## Refinement hierarchy (`FixedPatchStepper(cfg, *, context, refinements, ...)`)
|
|
|
|
| Setting | Supported | Guard |
|
|
|---|---|---|
|
|
| Depth | at least one refinement level; one entry per level in `level_blocks`/`level_objects`/`level_jets` | `lbm/refinement_stepper.py` `_check_levels` |
|
|
| Single L1 rectangle | two-coarse-cell margin to the domain edge | `lbm/refinement.py` `FixedPatch2D.from_config` |
|
|
| Several L1 rectangles (union) | require `level_blocks[0]` and `level_blocks[1]`; transfers must close (dependency checks, no fixed gap rule) | `lbm/refinement_stepper.py` `_check_levels`; `lbm/refinement.py` `_check_parent_pull_closure` |
|
|
| Nested levels | depth >= 3 must be all blocked; a blocked level requires blocked levels below; a scalar child needs a scalar parent | `lbm/refinement_stepper.py` `_check_levels`; `lbm/hierarchy.py` `build_hierarchy` |
|
|
| Nested transfer support | child only over inherited ACTIVE cells, donors/receivers uncovered ACTIVE, no child over the parent restriction footprint | `lbm/refinement.py` `_nested_kind` |
|
|
| Tile shape | positive `(by, bx)`; the level allocation must be divisible by the tile (no partial tiles yet) | `lbm/refinement_stepper.py` `_check_levels`, `lbm/refinement.py` `FixedPatchSet2D.fine_layout` (shape); `lbm/blocks.py` `BlockLayout2D.build` (divisibility) |
|
|
| Coarse boundary | `periodic`, `slot_reservoir` or `channel` | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__` |
|
|
| `slot_reservoir` | on-site velocity bottom slot, reservoir top, velocity 0, 2 <= slot width < nx, patch rows 4..ny-4 | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__`; `lbm/refinement.py` `prepare_fine_boundary` |
|
|
| `channel` | all levels blocked; Zou-He inlet, pressure-NEQ outlet, stationary bounce-back walls; transfers away from the closure | `lbm/channel.py` `validate_channel_config`, `validate_channel_transfers` |
|
|
| Explosion | `constant` (default); `projected_linear` only periodic, all-blocked SRT, no bodies/Jets, no LES (experimental) | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__` |
|
|
| L2 runtime remap (`remap_finest`) | periodic three-level L2 sets only, no L0/L1 bodies, identical pinned boundary | `lbm/refinement_stepper.py` `FixedPatchStepper.remap_finest` |
|
|
|
|
Tests: `tests/unit/test_refinement_three_level_multipatch.py`, `tests/validation/multigrid/test_refinement_multipatch.py`,
|
|
`test_refinement_three_level.py`, `test_refinement_three_level_multipatch_gpu.py`, `test_refinement_blocked_base.py`,
|
|
`test_refinement_blocked_fine.py`, `test_channel_root_gpu.py`, `tests/unit/test_channel_root.py`,
|
|
`tests/unit/test_projected_pair_stepper.py`, `test_runtime_child_remap_gpu.py`, `test_pinned_body_remap_gpu.py`.
|
|
|
|
## Bodies and Jets on refined levels
|
|
|
|
| Setting | Supported | Guard |
|
|
|---|---|---|
|
|
| Bodies | stationary circles without sensor/force-region roles, entirely inside the patch union, fully resolved, disjoint, stencil away from the two-hop transfer footprint | `lbm/refinement.py` `prepare_fine_boundary` |
|
|
| Level | not on L0; only on the finest level of a nested hierarchy | `lbm/refinement_stepper.py` `_check_levels` |
|
|
| Jet condition | velocity only; `pressure` is reserved and raises NotImplementedError | `body/jets.py` `Jet.__post_init__` |
|
|
| Jet geometry | each Jet selects resolved links of exactly one stationary body; no Jet/Jet or Jet/SurfaceActuation overlap; abs(amplitude) < 1 lattice | `body/jets.py` `Jet.__post_init__`, `jet_link_shapes`, `_surface_links` |
|
|
| Jets with shifted storage | only in the all-blocked stepper with SRT and no LES | `body/jets.py` `_surface_links` |
|
|
| SurfaceActuation | unshifted storage only | `body/objects.py` `SimObject.validate_surface_actuation` |
|
|
| Raw boundary exchange (force) | blocked body levels only; the window ledger requires `observe_raw_exchange` | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__` |
|
|
| Checkpoint with Jets | refused | `simulation.py` `Simulation.save_checkpoint` |
|
|
|
|
Raw exchange is the cut-link momentum reaction (wall + aperture), not a validated
|
|
nozzle thrust or stress load. Jet amplitude is a lattice velocity, not a flow rate.
|
|
|
|
Tests: `tests/unit/test_jets.py`, `test_jets_review.py`, `test_shifted_jets.py`, `test_raw_exchange.py`,
|
|
`tests/validation/multigrid/test_refinement_jets.py`, `test_shifted_jets_gpu.py`, `test_raw_exchange_gpu.py`,
|
|
`test_exchange_window.py`, `test_fine_surface_gpu.py`.
|
|
|
|
## Observations from specific tested cases (not general bounds)
|
|
|
|
- SRT channel root vs uniform OneStep, strict-parity test
|
|
`tests/validation/multigrid/test_channel_root_gpu.py::ChannelRootGPU::test_uniform_matched_root`:
|
|
in one of its 18 sub-cases (2 storage modes x 3 profile/clamp/damp settings x 3 blocks; which
|
|
one is not recorded), 1 of the 4320 compared values differs, max abs 2.33e-10, max rel 1.77e-7
|
|
(about 2 ULP). The test remains failed; its cause and any general bound are unresolved.
|
|
- MRT root parity test
|
|
`tests/validation/multigrid/test_refinement_mrt_gpu.py::RefinementMRTGPU::test_uniform_matched_mrt_root`
|
|
(12 sub-cases: 2 storage modes x 2 profiles x 3 blocks, default outlet settings) passed bitwise
|
|
in the Horsea focused GPU run at K1 7813334 (2026-10-21).
|
|
- Periodic Taylor-Green Re 100, measured at 36ffc8b1 (V3 matched pair, N128 depth 2):
|
|
every per-sample screen passed; the constant explosion's aggregate worst velocity L2,
|
|
0.004418, exceeds its preregistered 0.002 budget, while projected_linear passed that budget.
|
|
- Curved-wall pressure (pilot harness, exact-q analytic annulus, tau 0.8): the coarse swirl r1
|
|
case exceeded its terminal density-gain cap (1.105e-4 vs 1e-4), so the frozen 9-case matrix
|
|
is NOT_ESTABLISHED. No validated fix exists. This is a pilot harness, not production code.
|
|
- DFG 2D-1 Re 20 (V4, SRT, t* 60, pressure-NEQ outlet and local Zou-He inlet): refined and uniform
|
|
runs were NOT_STEADY under the frozen steady rule, so no interval verdict was given.
|
|
|
|
## Moving circles (dense `Simulation`, uniform grid only)
|
|
|
|
Translating circles with optional spin are supported on the dense double
|
|
buffer D2Q9 FP32 path only (not on `FixedPatchStepper` or refined levels).
|
|
API, supported/rejected modes and limits: `docs/moving_bodies.md`; stage-1
|
|
evidence: `docs/validation/moving_bodies_stage1.md`.
|
|
|
|
## Not supported in this release
|
|
|
|
3D, dynamic/automatic AMR (tagging, time-varying hierarchies beyond `remap_finest`),
|
|
moving bodies on refined levels, pressure Jets, Jet checkpoints, LES or TRT on refined
|
|
levels, partial (non-dividing) tiles.
|