Files
CelerisLab/docs/development/src_coherence.md
T
ClaudeandClaude Opus 5.5 ae53fade13 Contract: name the in-EDGE half-cell projection; repair DFG runner current-checkout Jet path
- No NODE<->EDGE input conversion still leaves the root-edge -> fine-local
  half-cell projection (prepare_fine_boundary, fine_hits_to_edge_frame); say so.
- run_refined_dfg.py (jet_scenario != none, current checkout only): pass
  level=1 to FixedPatchStepper.set_jet_amplitude on reversal; use
  blocked_coarse_tables there. jet_scenario=none keeps the pinned source's
  blocked_base_tables; manifests and results unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 02:45:30 +00:00

5.2 KiB

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. This concerns input placement only: within the EDGE frame, refined levels still project root-edge coordinates to fine-local cell indices with the half-cell shift (prepare_fine_boundary: (v - o)/dx - .5; hits back via fine_hits_to_edge_frame origin + dx*(hit + .5)), using edge_frame/fine_origin below.
  • 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).