Commit Graph
304 Commits
Author SHA1 Message Date
Codex b77f2238dd Use direct momentum in opt-in shifted blocked equilibrium 2026-10-17 00:18:00 -07:00
Codex c33caf636d Retain shifted density perturbation in opt-in blocked collision 2026-10-16 23:28:29 -07:00
Codex aaf35c6505 Add opt-in shifted raw remap GPU lifecycle gate 2026-10-16 23:28:09 -07:00
Codex b811b643e7 Support tagged shifted storage in blocked host transfers 2026-10-16 23:27:28 -07:00
Codex fbe73779c1 Build refinement transfers from union and pin physical body support 2026-10-16 20:51:29 -07:00
TRON 1e8e2c9a69 Clarify raw exchange metadata and streamline host tests 2026-10-16 18:58:30 -07:00
Codex c750493b07 Add opt-in row-owned raw boundary exchange for blocked refinement 2026-10-16 18:47:04 -07:00
ClaudeandClaude Opus 5.5 21bcb8a141 Keep the __main__ guard last in the multipatch unit test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:37:44 +00:00
ClaudeandClaude Opus 5.5 8fa9ac0253 Test the initialize entry adapter forms
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:37:34 +00:00
ClaudeandClaude Opus 5.5 c11b138a09 Accept legacy named arrays in FixedPatchStepper.initialize
initialize(coarse_g=..., fine_g=..., child_g=...) raised TypeError after the
switch to *level_g. A small entry adapter (_initial_levels) maps either the
positional per-level form or the original names to one per-level tuple and
rejects mixed or incomplete forms with TypeError before any state check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:37:24 +00:00
ClaudeandClaude Opus 5.5 7ecb179a41 Migrate stepper tests to the level-list representation
Schedule test drives _pairs[i].explode/coalesce and patches _advance(index,
buffer) for the stale L1->L2 feed mutant; remap rejection test patches
_boundary_hosts entries and hierarchy.pairs instead of the read-only views;
the GPU launch-failure test patches _pairs[0].explode. Assertions unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:36:41 +00:00
ClaudeandClaude Opus 5.5 edce582a2d Mark wall rows OUTER in a zero-refinement hierarchy
build_hierarchy(cfg, [], wall_aware=True) left both base wall rows ACTIVE;
the refined path already marked them OUTER. Add the regression test.
Found by native review of eeb90ac.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:31:42 +00:00
ClaudeandClaude Opus 5.5 baba5e02d9 Drive FixedPatchStepper by level lists and one recursive hop
The constructor builds lbm.hierarchy geometry, per-level layouts, kernel
configs, boundaries and leaf masks as lists, then one _build_level per level
and one _build_pair per adjacent pair. step() runs _hop(0): a child explodes
from its parent's hop source and advances twice, then the parent gathers
halos, stages receiver-local restriction, applies BFL and steps. Launch
sequence for existing two/three-level cases is unchanged; depth >= 4 works
for fully blocked hierarchies with bodies/Jets on the finest level.

New keywords refinements/level_blocks/level_objects/level_jets (L0 included);
legacy keywords are normalised by _legacy_levels and are mutually exclusive
with them. The dense two-level path stays as an isolated branch in _hop
(fused PatchCoarseStep root, dense fine BFL). Removed _child, _middle_kind
storage, _explode/_coalesce/_ghosts/_donors/_targets/_children,
_advance_child, _blocked_fine_boundary and _remap_blocks; existing public
attributes and the private names tests still read are thin read-only views.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:30:58 +00:00
ClaudeandClaude Opus 5.5 eeb90ace9a Add host-only arbitrary-depth refinement hierarchy builder
lbm/hierarchy.py loops the existing pair logic (FixedPatch2D/FixedPatchSet2D
for L0->L1, nest_patch/nest_patch_set for deeper pairs, _middle_config for
the per-level config chain) and returns validated per-level configs, pair
tables and composed kinds for any depth. Legacy scalar window forms are
accepted so existing public shapes are unchanged. Validates each config copy
because LBMConfig.omega is only computed by validate(). Not yet used by the
stepper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:19:29 +00:00
ClaudeandClaude Opus 5.5 77c034a29a Move host-only blocked table helpers into refinement_tables
Pure move of blocked_fine_tables, blocked_kind, blocked_base_tables,
_BlockedBoundary and _prepare_blocked_boundary out of the pycuda-importing
refinement_stepper into a numpy-only module, so CPU tests can import them
directly. refinement_stepper re-exports the public names; no behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:19:19 +00:00
TRON 60ad6b8b0d Generalize synchronized remap to multiple pinned body rectangles 2026-10-16 11:32:42 -07:00
TRON 864a220dbe Add research measured-strain fluid refinement example 2026-10-16 11:09:49 -07:00
TRON 6a7e9226db Add bounded pinned-circle manual L2 remapping 2026-10-16 10:41:56 -07:00
TRON 766658185f Add explicit synchronized L2 runtime continuation 2026-10-16 10:12:40 -07:00
TRON 999d3a0e94 Add synchronized CPU leaf population remap 2026-10-16 10:07:34 -07:00
TRON a24e6d2742 Support bounded three-level separated patch unions 2026-10-16 09:18:07 -07:00
TRON 20fb16ded5 Support stationary bodies and geometry Jets on nested L2 2026-10-16 08:49:08 -07:00
ClaudeandClaude Opus 5.5 64665319a4 Multipatch: fine_objects and jets on several patches (level-wide projection)
prepare_fine_boundary accepts a FixedPatchSet2D: objects are projected once
onto the level-wide fine grid (FixedPatchSet2D.fine_origin = (0, 0), same
coarse cell-edge -> fine cell transform), each circle must lie inside one
patch, coarse transfer cells are checked against the covered union, and body
ids stay object positions, so the existing jet one-body-per-jet, overlap and
(receiver, dir) writer checks run once over the whole level (caller obj_id
cannot bypass them). The stepper no longer rejects fine_objects/jets with
several patches; blocked link tables, BFL and the jet amplitude cache are
reused unchanged. No kernel change. README/docstring scope updated.

Tests: CPU translation/ids/rejections (outside one patch, one jet over two
bodies at zero amplitude); GPU one body via the new path == single-patch path
(both modes), two bodies (+jets, amplitude switch) == tiled single (bitwise).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:59:48 +00:00
ClaudeandClaude Opus 5.5 f1dcf329ff README: minimal three-level (nested child) usage and limits
Doc-only: child coordinates in L1 window cells, three arrays in/out, 1:2:4,
single body-free chain; example reuses the accepted 16/24/24 fixture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:54:05 +00:00
ClaudeandClaude Opus 5.5 dd9a4dc4b8 Three levels: step unpacks only the first two levels; README multipatch nits
step() did 'c, f = self._levels', which raises for three levels before any
launch (root review). The child level is driven from the fine hops. Other
_levels uses are per-level loops or explicit indices. README multipatch
example now defines rest locally and states coarse/fine NaN separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:39:29 +00:00
ClaudeandClaude Opus 5.5 76555de4b8 Three levels: nested body-free child patch on a single chain
FixedPatchStepper(..., child=(x0,y0,x1,y1), child_block=(by,bx)) adds an L2
patch in L1 window cells (requires fine_block/base_block, one L1 patch, no
bodies/jets). nest_patch() builds the L1->L2 FixedPatch2D (2*nu on L1) and
the composed L1 kind (inherited INNER/OUTER kept, child-covered ACTIVE made
OUTER), rejecting from the actual tables: coverage outside ACTIVE, donors or
receivers not uncovered ACTIVE, surviving ACTIVE pulls of covered/OUTER cells
without a child-supplied arrival, and overlap with L1's restriction footprint.

Step order per L1 hop: explode L1(src)->L2, two L2 hops (halo, step), L1 halo,
receiver-local L2->L1 staging into src, L1 step. The second hop thus feeds L2
from the new L1 G; L2 is never refilled from L0; L0 stays once per step (1:2:4).
Existing kernels only; a small _Pair holds the child transfer bindings (explode
from the child module, parent window stride). Two-level API unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:35:57 +00:00
ClaudeandClaude Opus 5.5 6301887093 Multipatch: validate fine block before modulo, raw-core GPU checks, README usage
FixedPatchSet2D.fine_layout rejects non-positive, float, bool or wrong-length
block sizes with ValueError before any modulo (was ZeroDivisionError/TypeError).
The face gap-4 GPU test now checks raw owner cores directly by kind/covered
for every patch (ACTIVE finite, OUTER/holes/covered NaN; INNER not asserted),
not only the masked download and reversed-order parity. README documents the
body-free multipatch call, scope and level-wide fine shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:22:00 +00:00
ClaudeandClaude Opus 5.5 0397b6ebb7 Multipatch: CPU guards and frozen GPU gates through the new interface
One rectangle via the multipatch path is bit-identical to the old
single-patch blocked path (both modes, raw masks); S1 two-patch 16x32 equals
the 16x16 one-patch run tiled (bitwise), in both rectangle orders; face
gap-4 pair is order-invariant with exact covered/hole masks. Mass printed
as a diagnostic only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:01:41 +00:00
ClaudeandClaude Opus 5.5 4c8240ea13 Multipatch: FixedPatchSet2D host metadata and opt-in FixedPatchStepper path
Several separated (>= 4 coarse cells) body-free 2:1 patches share one
level-wide fine grid stored by a sparse BlockLayout2D over the patch
supports. FixedPatchSet2D re-addresses each FixedPatch2D's tables to level
coordinates (same rows/child order, canonical patch order). The stepper
accepts a sequence of rectangles as bounds (requires fine_block and
base_block; rejects fine_objects/jets), reusing the existing blocked step
sequence and kernels. Helpers use a covered mask instead of one rectangle
and skip unstored fine holes. No kernel changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:00:50 +00:00
ClaudeandClaude Opus 5.5 93d1cddd27 BlockLayout2D.build: check capacity before generating regular origins
c397e08 moved the 64-bit capacity check after np.arange(nby*nbx), so an
over-limit regular layout allocated before rejecting. Check arithmetic
block count (regular) or validated selected count (sparse) first; mock
regression asserts no np.arange before the ValueError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:27:13 +00:00
ClaudeandClaude Opus 5.5 68ecaf9e81 BlockLayout2D.to_dense: restore hole-only NaN fill guard
cc64abc dropped the guard, so full layouts with integer arrays raised on
an empty NaN assignment (regression caught by test_to_dense_dtype_contract).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:20:56 +00:00
ClaudeandClaude Opus 5.5 cc64abcafe BlockLayout2D.to_dense: require floats when the layout has holes
Holes are filled with NaN, which bool/str silently mangled and integers
rejected with a conversion error. Sparse layouts now raise a clear
ValueError for non-floating arrays; full layouts keep any dtype.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:16:52 +00:00
ClaudeandClaude Opus 5.5 aecee19c19 BlockLayout2D: copy caller-supplied origins
An int64 C-contiguous origins array was kept by reference (and frozen in
the caller's hands), so mutating it later changed layout.origins and
block_cell without changing owner/halos. Copy before marking read-only;
regression checks origins, owner and block_cell invariance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:15:37 +00:00
ClaudeandClaude Opus 5.5 fa7fd9097a Test: map the q<.5 variant of a sparse cut link separately
The fixture listed (fluid_idx=13, dir=3) twice with different q, so the
existing repeated-link rejection fired before the sparse checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:14:55 +00:00
ClaudeandClaude Opus 5.5 c397e08565 BlockLayout2D: explicit selected block origins with hole owners
build(..., origins=None|[(y0, x0), ...]) stores only grid-aligned selected
blocks (unique, strictly row-major, no silent reordering). Cells of absent
blocks own layout.hole (= nblocks*L, one past the last block cell) so an
unguarded index fails rather than wrapping like -1; layout.owned is the
dense mask. Halo pairs never read holes, to_blocked ignores hole values,
to_dense returns NaN there, map_cut_links rejects receivers, solid
neighbors or q<.5 donors in absent blocks, blocked_link_tables stores
owned flags only. origins=None or every origin reproduces the regular
layout exactly. Storage only: no CUDA or stepper changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:09:15 +00:00
ClaudeandClaude Opus 5.5 99ddb5fc27 Test: fine jet ownership uses remapped physical owners
Caller obj_id 99 spanning 2x2 fine blocks: driven rows carry the single
remapped owner 0 across several block ids, accepted; source id unchanged.
Caller ids (99, 7) under one tube are rejected at amplitude 0 and .002
on the 32x24 fixture; source ids unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:42:04 +00:00
ClaudeandClaude Opus 5.5 bf0adda45f Test: jet ownership is set membership, not row adjacency
Synthetic rows: one jet over non-contiguous rows of one body is accepted;
the same rows with a second body id are rejected (Grok case 2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:41:15 +00:00
ClaudeandClaude Opus 5.5 64d54ab23e Jets: one jet may drive links of only one body
surface_link_velocity (the shared host check used by CurvedLinkSoA,
ObjectManager sync, prepare_fine_boundary and FixedPatchStepper) now
rejects a jet whose selected cut links carry more than one body id, at
any amplitude, before uploads. Identity is the scene-wide body id of the
physical cut-link list, so one body spanning storage blocks stays valid.
No body selector; empty-selection semantics unchanged.

Tests: two bodies under one jet rejected (amplitude 2e-3 and 0) on the
Simulation/manager path and on the fine path; separate jets on separate
bodies accepted on both; one fine body crossing 2x2 block seams accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:39:58 +00:00
ClaudeandClaude Opus 5.5 f1e03423f3 Action upload: keep 2D slot fallback for ObjectManager(cfg=None)
19bd308 computed slot = 3*self.cfg.dim unconditionally, so a default
manager without cfg raised even when empty. Use the existing fallback
(cfg.dim if cfg else 2). Regression for empty and one-body managers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:03:11 +00:00
ClaudeandClaude Opus 5.5 e67799812e Jet review tests: rotated tube, exact edge rule, synthetic flat wall
Test-only. Rotated 30-degree tube: lateral .999 in, 1.001 out, along -0.1
and 4.1 out, Parallel(30 deg) gives the axis unit vector. Separate
axis-aligned exact-edge check: |s| = 1 excluded, Tube along 0/length and
Sector r_min/r_max included. Synthetic hit sampling on a flat face x=10
(no non-circle geometry or kernel coverage): spatial selection |y| <= 1
and off-centre radial vectors from (5, 0) rather than the face normal.
Re-written from Grok's stated cases; the original text was clipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:02:05 +00:00
ClaudeandClaude Opus 5.5 19bd3088ef Gate action upload on Jet stationarity; document setter device-error handling
ObjectManager._upload_action_async is the single entry for every action
path (setters, direct edits of the public action array, run()). It now
also rejects nonzero vx/vy/omega slots of Jet-driven bodies via
validate_jet_motion, before any device copy. Regression: each motion
slot edited directly is rejected with no device write; zero motion
uploads. Simulation.set_jet_amplitude documents that a device error
requires close/recreate, as for other CUDA exceptions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:58:17 +00:00
ClaudeandClaude Opus 5.5 063508d1a3 Jet amplitude setter: failed state on device errors, commit after upload
FixedPatchStepper.set_jet_amplitude validates index/amplitude and builds
the new rows before touching the device; invalid input leaves the
instance usable. A copy/sync error marks it failed (as initialize/step/
download do) and re-raises; host state (_jets, blocked velocity table)
commits only after a successful upload. CurvedLinkSoA.set_jet_amplitude
likewise uploads a new array first and commits jets/surface_velocity
afterwards. Focused mocked-driver tests for dense and blocked copy
failure, invalid input and IndexError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:49:35 +00:00
ClaudeandClaude Opus 5.5 508d412e43 Add Grok's Jet review tests (5-link sector oracle, axis wrap)
Taken from Grok's inline patch (Slack ts 1792052057.423679); the selector
fix in that patch was already applied in b1cd555. The rotated-tube and
non-circle-wall cases were clipped in transit and are not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:42:51 +00:00
ClaudeandClaude Opus 5.5 aebef52345 Wire Jets into FixedPatchStepper fine level (dense and blocked)
FixedPatchStepper(..., jets=()) passes jets (coarse cell-edge frame, as
fine_objects) to prepare_fine_boundary, which runs the shared assignment
checks before CUDA. Dense fine path: assign_surface with jets and the
boundary's true hits. Blocked path: surface_link_velocity with jets/hits;
unit-amplitude shapes cached. set_jet_amplitude (new/ready only) validates
first, then rewrites the dense SoA column or the blocked jet rows and
re-uploads only the velocity buffer after a stream sync. Scheduling,
kernels and launch ABI unchanged.

tests/validation/multigrid/test_refinement_jets.py: mocked-driver CPU
checks and frozen GPU gates G1-G3 (layout identity, jet vs legacy <=1e-6,
amplitude switch).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:42:51 +00:00
ClaudeandClaude Opus 5.5 f26410f94a Merge base-blocked FixedPatchStepper 906e0d9 into claude/jet
Exact codex/refinement-blocked-base-20261015 head, cleared by Astra/root.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:41:38 +00:00
ClaudeandClaude Opus 5.5 038a759ff1 Jets: one shared assignment check for dense and fine levels
Move surface_link_velocity (pure host code) from lbm/curved_links.py to
body/jets.py, re-exported by curved_links, so refinement.py can reuse it
without importing PyCUDA. prepare_fine_boundary now runs the same
assignment validation as the steppers when jets are given, rejecting
jet-vs-SurfaceActuation overlap (root's C(12.25,12.25) R2.15 case) as
well as empty/overlapping jets. Test the overlap and a disjoint pair.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:35:12 +00:00
ClaudeandClaude Opus 5.5 f7753be0e4 Jets: enforce stationary rule at ObjectManager.set_body_state too
Move the Jet motion check into ObjectManager.validate_jet_motion (uses the
synced field's cut-link jet_id) and call it from both Simulation.set_body
and the direct ObjectManager.set_body_state entry, before any state or
action change. Test both entries, vx too, and that action is untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:32:29 +00:00
ClaudeandClaude Opus 5.5 62c525e735 Jets: freeze origins, guard set_body, fine-boundary hit helper
Sector/Tube/Radial store origin as a validated float 2-tuple, so caller
lists/arrays cannot change a registered definition. Simulation.set_body
rejects nonzero motion for bodies with Jet-driven links once initialized
(before initialize the sync-time stationary check applies).
prepare_fine_boundary accepts jets in the same coarse cell-edge frame as
fine objects, records read-only FP64 edge-frame hits (FineBoundary2D
.curved_hits, default None) and rejects empty or overlapping selections
before CUDA. FixedPatchStepper wiring is not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:27:35 +00:00
Frank14f 906e0d9a0e Support blocked parent storage in fixed patch stepping 2026-10-15 16:25:26 +08:00
ClaudeandClaude Opus 5.5 da8bfb0d4a Jets: explicit cell-edge/node frame conversion, same-physical-hit test
Replace fine_hits_to_physical with fine_hits_to_edge_frame (patch
cell-edge frame, coarse centers at I+1/2, as FixedPatchStepper uses) and
edge_to_node_frame (Simulation integer-node frame, shift -1/2). Test one
physical circle through both frames: fine hits converted to node frame
lie on the Simulation circle and one node-frame Jet selects the same arc
on coarse and fine links; relabelling without conversion is detected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:23:28 +00:00