- Coarse/fine name the two members of any pair (Hierarchy docstring); only the misleading blocked_base_tables -> blocked_coarse_tables. prepare_fine_boundary and blocked_fine_tables keep their pair-relative names. - Depth-1 static circles use the integer-NODE frame (unchanged behavior); the root EDGE frame applies to refined levels only. Contract text corrected. - _kernel_configs documents why it stays distinct from Hierarchy.configs. - Drop the stale re-export comment; two tests import table builders from refinement_tables. Mechanical caller renames for this delta only. No numerical code or config derivation changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
75 lines
4.9 KiB
Markdown
75 lines
4.9 KiB
Markdown
# src coherence stage (from main 914906e)
|
|
|
|
Owner direction 2026-10-28: unified style over historical compatibility, inside `src`.
|
|
No numerical change is intended; kernel text was moved verbatim (PTX/bit parity is
|
|
pending a GPU run).
|
|
|
|
## Conventions (defined once, in `lbm.hierarchy.Hierarchy`)
|
|
|
|
- Level `l = 0 .. depth-1` (0 = root). Pair `hierarchy.pairs[l-1]` builds level `l`.
|
|
- Array shapes are `(ny, nx)`; rectangles, origins and centers are `(x, y)`.
|
|
- Coarse/fine name the two members (parent/child) of ANY pair, not absolute L0/L1:
|
|
`fine_shape`, `fine_origin`, `prepare_fine_boundary`, `blocked_fine_tables`,
|
|
`blocked_coarse_tables`.
|
|
- Refined levels (l >= 1) of FixedPatchStepper place bodies/Jets in the root EDGE frame
|
|
(root cell `i` = `[i, i+1)`). Uniform `Simulation` objects AND the static circles of a
|
|
single-level (depth 1) FixedPatchStepper use the integer-NODE frame. Nothing converts
|
|
between them.
|
|
- `Hierarchy.edge_frame(l)` -> `((ox, oy), h)`: cell `(i, j)` of level `l`'s allocated
|
|
array (ghost band and holes included) covers `[o + h*i, o + h*(i+1))`. A scalar
|
|
FixedPatch2D window carries the half-coarse-cell ghost shift `bounds - HALO/2` in
|
|
`fine_origin`; a set's level-wide grid has origin 0. Level 1 boundaries are built from
|
|
the root config (the wall-aware fields live there); deeper ones from the parent frame.
|
|
- `FixedPatch2D.fine_level_offset` (was `fine_level_origin`) is an array INDEX offset
|
|
`(y, x)`, not an `(x, y)` origin.
|
|
|
|
## FixedPatchStepper migration map
|
|
|
|
| removed / changed | replacement |
|
|
|---|---|
|
|
| `patch`, `child_patch` | `hierarchy.pairs[0]`, `hierarchy.pairs[1]` |
|
|
| `base_layout`, `fine_layout`, `child_layout` (stepper properties) | `layouts[0]`, `layouts[1]`, `layouts[2]` (`FixedPatchSet2D.fine_layout(block)` is unchanged) |
|
|
| `fine_boundary`, `child_boundary` | `boundaries[1]`, `boundaries[2]` (host geometry; `None` = no bodies/Jets) |
|
|
| `_jets` | `jets[1]` |
|
|
| `_boundaries[l]` (dict from L1, level keys) | `_device_boundaries[l]` (list from L0, `None` at L0 unless single-level static circles) |
|
|
| `_level_boundaries` (private, b4eacf7) | `_device_boundaries` |
|
|
| `_fine_tables`, `_actuated`, `_jet_cache` | `_device_boundaries[1].tables` / `.actuated` / `.jet_cache` |
|
|
| `_remap_cfg` (private) | `_root_cfg` |
|
|
| `refinement_tables.blocked_base_tables` (also via `refinement_stepper`) | `refinement_tables.blocked_coarse_tables` (import from `refinement_tables`; the stepper no longer re-exports) |
|
|
| `_fine_leaf`, `_child_leaf` | `leaf[1]`, `leaf[2]` (copies) |
|
|
| `_middle_kind` | `hierarchy.kinds[1]` |
|
|
| `_boundary_hosts` (private) | `_boundaries` (private list behind `boundaries`) |
|
|
| `remap_child(rects, child_objects=...)` | `remap_finest(rects, objects=...)` |
|
|
| `set_jet_amplitude(i, a)` (implicit level 1) | `set_jet_amplitude(i, a, level=l)` (required) |
|
|
| `read_raw_exchange(b)` / `read_exchange_window(b)` (implicit level 1) | `read_raw_exchange(b, level=l)` / `read_exchange_window(b, level=l)` (required) |
|
|
| `_level_name(l)` "base/fine/child" messages | `"level l"` |
|
|
| `refinement.MIN_PATCH_GAP` | deleted (no gap policy exists) |
|
|
| `params.cuh HaloPlan`, `collide_trt_no_force` | deleted (zero references) |
|
|
|
|
Kept: `step_count`, constructor keywords (`refinements`, `level_blocks`, `level_objects`,
|
|
`level_jets`, `coarse_boundary`, `explosion`), `Simulation.set_jet_amplitude(i, a)` (one level),
|
|
`RemapTopology.from_config(..., child_objects=, child_jets=)` (internal remap helper; "child" =
|
|
the replaced level relative to its parent).
|
|
|
|
## Responsibilities
|
|
|
|
- Construction: `_check_levels` (inputs), `_kernel_configs` (per-level kernel configs),
|
|
`Hierarchy.edge_frame` (geometry frames), `_build_level` / `_build_pair` / `_upload_boundary`
|
|
(device). Observation reads share `_observed_boundary` + `_summarize`.
|
|
- Blocked kernels: `operators/block_collision.cuh block_collide` is the one collision extension
|
|
point of `BlockStep` and `BlockChannelStep`. MRT shares one path; SRT keeps its two explicit
|
|
arithmetic variants (level: unclamped, no-force, shifted direct-momentum feq; channel: uniform
|
|
OneStep arithmetic with omega clamp), selected by `BLOCK_ROOT_BC`.
|
|
- `explosion="projected_linear"` stays an optional capability; `"constant"` stays default.
|
|
|
|
## Not done / open
|
|
|
|
- Two per-level config derivations stay distinct on purpose: `Hierarchy.configs`
|
|
(`_middle_config`, wall fields reset on every refined level, geometry validation) vs.
|
|
`FixedPatchStepper._kernel_configs` (reset only on level 1 of a slot_reservoir root;
|
|
generates each level's config.h). Folding them needs a config.h/PTX diff gate.
|
|
- No single-`Simulation` facade over FixedPatchStepper: the two own different state models
|
|
(uniform node frame, body sync, forcing, checkpoint vs. immutable blocked hierarchy, edge
|
|
frame, remap-as-new-instance). A facade would only forward calls; no concrete need found.
|
|
- Tests, examples and validation callers are migrated separately (pinned runners stay frozen).
|