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>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-15 08:58:17 +00:00
1 parent 063508d1a3
commit 19bd3088ef
3 files changed
+33 -3

No files matched your search

+17
View File
@@ -253,6 +253,23 @@ def test_set_body_rejects_motion_of_jet_driven_body(device):
bodies.set_body_state(0, omega=0.)
def test_action_upload_rejects_motion_of_jet_driven_body(device):
# Direct edits of the public action array are checked at the upload gate.
jet = Jet(Sector(CENTER, 0., .6, 3.), Radial(CENTER, inward=False), "quartic", 2e-3)
field, bodies = jet_case(device, [jet])
stream = SimpleNamespace(synchronize=lambda: None)
slot = 3*field.cfg.dim
for index in (0, 1, slot - 1): # vx, vy, omega
bodies.action[:] = 0
bodies.action[index] = .01
writes = device.writes
with pytest.raises(ValueError, match="stationary"):
bodies._upload_action_async(stream)
assert device.writes == writes # nothing reached the device
bodies.action[:] = 0
bodies._upload_action_async(stream) # zero motion stays accepted
def test_fine_boundary_keeps_edge_frame_hits_and_checks_jets():
from CelerisLab.body.objects import SimObject
from CelerisLab.body.geometry.circle import CircleGeometry