Support stationary bodies and geometry Jets on nested L2

This commit is contained in:
TRON committed 2026-10-16 08:49:08 -07:00
1 parent 64665319a4
commit 20fb16ded5
5 files changed
+400 -67

No files matched your search

+69
View File
@@ -310,5 +310,74 @@ class NestPatchTests(unittest.TestCase):
refinement.nest_patch(self.cfg, self.l1, bounds)
class ChildBoundaryTests(unittest.TestCase):
@staticmethod
def body(center=(8., 8.), radius=.8, obj_id=99, spec=None):
from CelerisLab.body.geometry.circle import CircleGeometry
from CelerisLab.body.objects import SimObject
return SimObject(obj_id, geometry=CircleGeometry(*center, radius), center=center,
radius=radius, surface_actuation=spec)
def prepare(self, objects, jets=(), large=False):
from dataclasses import replace
cfg = LBMConfig(nx=32 if large else 16, ny=32 if large else 16, viscosity=.1)
parent = FixedPatch2D.from_config(cfg, (4, 4, 28, 28) if large else (4, 4, 12, 12))
child, _ = refinement.nest_patch(cfg, parent, (8, 8, 40, 40) if large else (8, 8, 16, 16))
middle = replace(cfg, nx=parent.fine_shape[1], ny=parent.fine_shape[0], viscosity=.2)
return child, refinement.prepare_fine_boundary(middle, child, objects, jets=jets,
parent_origin=parent.fine_origin, parent_spacing=.5)
def test_root_frame_matches_independent_parent_frame_projection(self):
from CelerisLab.body.jets import Jet, Parallel, Tube, jet_link_shapes
jet = Jet(Tube((6.5, 8.), 0., 3., .3), Parallel(0.), amplitude=.002)
original = self.body()
child, b = self.prepare([original], [jet])
middle = LBMConfig(nx=24, ny=24, viscosity=.2)
transformed = self.body((12., 12.), 1.6)
local_jet = Jet(Tube((9., 12.), 0., 6., .6), Parallel(0.), amplitude=.002)
other = refinement.prepare_fine_boundary(middle, child, [transformed], jets=[local_jet])
for a, c in zip(b.curved_host, other.curved_host):
np.testing.assert_array_equal(a, c)
np.testing.assert_array_equal(b.flags, other.flags)
np.testing.assert_allclose(b.curved_hits, 2 + .5 * other.curved_hits, atol=0, rtol=0)
for a, c in zip(jet_link_shapes([jet], b.curved_hits),
jet_link_shapes([local_jet], other.curved_hits)):
np.testing.assert_allclose(a, c, atol=1e-14, rtol=0)
self.assertEqual(len(b.curved_host[0]), 60)
self.assertAlmostEqual(child.tau_fine, .5 + 12 * .1)
self.assertEqual(original.geometry.center, (8., 8.))
self.assertEqual(original.obj_id, 99)
def test_invalid_body_and_jet_contracts(self):
from CelerisLab.body.jets import Jet, Parallel, Tube
from CelerisLab.body.objects import SurfaceActuation
jet = Jet(Tube((6.5, 8.), 0., 3., .3), Parallel(0.), amplitude=.002)
for body in (self.body((6., 8.)), self.body((6.9, 8.)), self.body(radius=2.1)):
with self.assertRaises(ValueError):
self.prepare([body])
moving = self.body()
moving.state.vx = .01
with self.assertRaisesRegex(ValueError, "stationary"):
self.prepare([moving])
with self.assertRaises(ValueError):
self.prepare([self.body()], [jet, jet])
empty = Jet(Tube((0., 0.), 0., 1., .1), Parallel(0.), amplitude=0.)
with self.assertRaises(ValueError):
self.prepare([self.body()], [empty])
spec = SurfaceActuation(.7, .85, .002)
with self.assertRaisesRegex(ValueError, "SurfaceActuation"):
self.prepare([self.body(spec=spec)], [spec.as_jet((8., 8.), .8)])
def test_one_jet_two_real_bodies_same_caller_id_rejected(self):
from CelerisLab.body.jets import Jet, Parallel, Tube
bodies = [self.body((12., 14.), 1., 7), self.body((17., 14.), 1., 7)]
_, boundary = self.prepare(bodies, large=True) # establish legal geometry first
self.assertEqual(np.unique(boundary.curved_host[3]).tolist(), [0, 1])
for amplitude in (0., .002):
jet = Jet(Tube((10., 14.), 0., 9., .4), Parallel(0.), amplitude=amplitude)
with self.assertRaisesRegex(ValueError, "one jet may drive only one body"):
self.prepare(bodies, [jet], large=True)
if __name__ == "__main__":
unittest.main(verbosity=2)