11 Commits
Author SHA1 Message Date
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 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 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
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
ClaudeandClaude Opus 5.5 b1cd555b0f Jet review fixes: frozen Jet, validated amplitude replacement, test selector
Jet is a frozen dataclass; with_amplitude returns a validated copy, so
region/field/profile cannot drift from the cached per-link shapes and
amplitude cannot bypass validation. CurvedLinkSoA.set_jet_amplitude and
Simulation.set_jet_amplitude replace the Jet (Simulation also updates the
registered list so later geometry syncs keep the amplitude). Reject
non-finite hits; document edge rule (|s|<1 exclusive, radial/along
bounds inclusive). Fix the clipped-q test selector to receiver (9,5)
dir 8, as in test_surface_actuation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:18:29 +00:00
ClaudeandClaude Opus 5.5 932702f779 Wire Jets through ObjectManager and Simulation
ObjectManager.jets holds scene-level Jets. build_compact_lists_for
collects true FP64 hits (SimObject.get_curved_list hits_out) row-aligned
with the cut-link columns; BodySyncPlan carries them as curved_hits, and
sync_to_gpu / apply_sync_plan / the pre-sync check pass jets+hits to
assign_surface. Jets require D2Q9/FP32/unshifted/double_buffer and may
only drive links of stationary bodies. Simulation.add_jet (before
initialize) and set_jet_amplitude (velocity column re-upload only);
save_checkpoint refuses scenes with jets. Fine-path wiring not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:15:22 +00:00
ClaudeandClaude Opus 5.5 611a64c54a Add body-independent Jet: true-hit spatial selection, fields, profiles
Jet(region, field, profile, amplitude) with Sector/Tube regions,
Radial/Parallel fields and uniform/parabolic/quartic profiles. Selection
uses true FP64 hit points over all scene cut links, no body association.
Overlap between jets or with a SurfaceActuation aperture is rejected.
CurvedLinkSoA caches unit-amplitude shapes; set_jet_amplitude rewrites
and re-uploads only the surface-velocity column. SurfaceActuation.as_jet
is the legacy adapter (equivalence measured in tests). Kernel and SoA
geometry columns unchanged. Manager/Simulation/fine-path wiring pending.

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