- 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>
5.2 KiB
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). Pairhierarchy.pairs[l-1]builds levell. - 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)). UniformSimulationobjects 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 viafine_hits_to_edge_frameorigin + dx*(hit + .5)), usingedge_frame/fine_originbelow. Hierarchy.edge_frame(l)->((ox, oy), h): cell(i, j)of levell'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 shiftbounds - HALO/2infine_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(wasfine_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_collideis the one collision extension point ofBlockStepandBlockChannelStep. 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 byBLOCK_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-
Simulationfacade 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).