diff --git a/tests/unit/test_jets_review.py b/tests/unit/test_jets_review.py index 7b5177f..13ca59b 100644 --- a/tests/unit/test_jets_review.py +++ b/tests/unit/test_jets_review.py @@ -1,9 +1,12 @@ -"""Grok review cases for claude/jet (test-only; from Grok's inline patch at Slack -ts 1792052057.423679). The rotated-tube and non-circle-wall cases were clipped -by the Slack reader and are not included yet.""" +"""Grok review cases for claude/jet (test-only). + +The oracle and wrap tests are Grok's inline patch (Slack ts 1792052057.423679). +The rotated-tube and square-wall cases follow Grok's stated checks; their text +was clipped in transit, so they are re-written here, not copied verbatim. +""" import math import numpy as np -from CelerisLab.body.jets import Sector +from CelerisLab.body.jets import Jet, Parallel, Radial, Sector, Tube, jet_link_shapes from .test_surface_actuation import circle @@ -38,3 +41,39 @@ def test_sector_axis_pi_wraps(): assert sel.tolist() == [True, True, False] sel, _ = Sector((0., 0.), -math.pi, .01, 2.).select(hits) assert sel.tolist() == [True, True, False] + + +def test_rotated_tube_30deg_selection_and_parallel_axis(): + a = math.radians(30) + u, n = np.array([math.cos(a), math.sin(a)]), np.array([-math.sin(a), math.cos(a)]) + hits = np.array([2*u, 2*u + .999*n, 2*u - .999*n, 2*u + 1.001*n, -.1*u, 4.1*u]) + jet = Jet(Tube((0., 0.), a, 4., 1.), Parallel(a)) + shape, jet_id = jet_link_shapes([jet], hits) + assert (jet_id == 0).tolist() == [True, True, True, False, False, False] + np.testing.assert_allclose(shape[:3], np.tile(u, (3, 1)), rtol=0, atol=1e-15) + np.testing.assert_array_equal(shape[3:], 0.) + + +def test_exact_edge_rule_axis_aligned(): + # Exactly representable samples: lateral |s| = 1 is excluded; Tube along + # 0 and length and Sector r_min/r_max are included. + tube = Tube((0., 0.), 0., 4., 1.) + sel, s = tube.select(np.array([[2., 1.], [2., -1.], [2., .5], [0., 0.], [4., 0.]])) + assert sel.tolist() == [False, False, True, True, True] + assert s.tolist() == [1., -1., .5, 0., 0.] + sel, _ = Sector((0., 0.), 0., .5, 2., 1.).select(np.array([[1., 0.], [2., 0.], [.5, 0.], [2.5, 0.]])) + assert sel.tolist() == [True, True, False, False] + + +def test_synthetic_square_wall_off_centre_radial(): + # Synthetic hit sampling on a flat face x=10 (no square geometry, cut links or + # kernel involved): selection is purely spatial and the field points away + # from (5, 0), not along the face normal (1, 0). + y = np.linspace(-2., 2., 9) + hits = np.stack((np.full_like(y, 10.), y), axis=1) + jet = Jet(Tube((10., -1.), math.pi/2, 2., .5), Radial((5., 0.), inward=False), amplitude=1e-3) + shape, jet_id = jet_link_shapes([jet], hits) + assert np.array_equal(jet_id == 0, np.abs(y) <= 1) + d = hits[jet_id == 0] - (5., 0.) + np.testing.assert_allclose(shape[jet_id == 0], d/np.hypot(*d.T)[:, None], rtol=0, atol=1e-15) + assert np.abs(shape[jet_id == 0, 1]).max() > .1 # not the wall normal