Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2469af70d0 |
@@ -23,13 +23,16 @@ Route capabilities (rejections checked before CUDA by test_route_capability_matr
|
||||
channel root rejected rejected yes
|
||||
several L1 rectangles rejected rejected yes
|
||||
depth >= 3 with a dense level rejected rejected yes
|
||||
MRT, periodic root, circle/actuation/Jet yes yes yes (parity gate)
|
||||
two fine bodies (Jet + passive, two actuated) yes yes yes (parity gate)
|
||||
MRT with slot/reservoir root rejected on every route (on_site_velocity is SRT-only)
|
||||
Slot/reservoir walls are compile-time WALL_* macros on a dense root and the
|
||||
d_block_wall constant on a blocked root: BC-encoding parity, bit-identical by
|
||||
this gate. Dense fine bodies use CurvedLinkSoA + CurvedBoundaryKernel
|
||||
(n_objects > 0), blocked ones BlockCurvedBoundary; same links and physics,
|
||||
compared through the population rows. Parked here: MRT (covered by
|
||||
test_refinement_mrt_gpu::test_dense_versus_blocked_mrt_two_level), shifted and
|
||||
depth >= 3 (no dense route to compare), several bodies (later slice).
|
||||
compared through the population rows. MRT body-free is also covered by
|
||||
test_refinement_mrt_gpu::test_dense_versus_blocked_mrt_two_level. Parked:
|
||||
shifted and depth >= 3 (no dense route to compare).
|
||||
"""
|
||||
from contextlib import ExitStack, contextmanager, nullcontext
|
||||
from dataclasses import replace
|
||||
@@ -354,6 +357,25 @@ class BlockedBaseGPU(unittest.TestCase):
|
||||
|
||||
|
||||
ROUTES = (("D/D", [None, None]), ("D/B", [None, FINE_BLOCK]), ("B/B", [(12, 8), FINE_BLOCK]))
|
||||
# Two-body rows: patch (4, 4, 28, 20) gives a 40 x 56 fine window, tiled (8, 8).
|
||||
WIDE_BOUNDS = (4, 4, 28, 20)
|
||||
WIDE_ROUTES = (("D/D", [None, None]), ("D/B", [None, (8, 8)]), ("B/B", [(12, 8), (8, 8)]))
|
||||
LEFT, RIGHT, RADIUS = (12.0, 12.0), (20.0, 12.0), 2.15
|
||||
|
||||
|
||||
def body(ident, center, spec=None):
|
||||
from CelerisLab.body.geometry.circle import CircleGeometry
|
||||
from CelerisLab.body.objects import SimObject
|
||||
return SimObject(ident, geometry=CircleGeometry(*center, RADIUS), center=center, radius=RADIUS,
|
||||
surface_actuation=spec)
|
||||
|
||||
|
||||
TWO_BODY_CASES = (
|
||||
("jet + passive", lambda: [body(0, LEFT), body(1, RIGHT)],
|
||||
lambda: [actuation(SPEED).as_jet(LEFT, RADIUS)], -SPEED),
|
||||
("actuated +/-", lambda: [body(0, LEFT, actuation(SPEED)), body(1, RIGHT, actuation(-SPEED))],
|
||||
lambda: [], None),
|
||||
)
|
||||
|
||||
|
||||
def same_summary(a, b):
|
||||
@@ -414,17 +436,18 @@ def replace_value(tree, path, value=None):
|
||||
class DenseBlockedRouteParity(unittest.TestCase):
|
||||
"""D/D vs D/B vs B/B, unshifted SRT, one circle or one velocity Jet; see module docstring."""
|
||||
|
||||
def run_routes(self, mode, objects=(), jets=(), switch=None):
|
||||
def run_routes(self, mode, objects=(), jets=(), switch=None, cfg=None, bounds=BOUNDS, routes=ROUTES):
|
||||
from CelerisLab.cuda.context import CudaContext
|
||||
cfg = config(mode)
|
||||
p = FixedPatch2D.from_config(cfg, BOUNDS)
|
||||
cfg = cfg or config(mode)
|
||||
p = FixedPatch2D.from_config(cfg, bounds)
|
||||
arrays = state(NY, NX, 1), state(*p.fine_shape, 2)
|
||||
bodies = sorted({obj.obj_id for obj in objects})
|
||||
results = {}
|
||||
with CudaContext(0) as context:
|
||||
for name, blocks in ROUTES:
|
||||
for name, blocks in routes:
|
||||
observe = bool(objects) and blocks[1] is not None
|
||||
snapshots, ledgers = [], []
|
||||
with FixedPatchStepper(cfg, context=context, coarse_boundary=mode, refinements=[BOUNDS],
|
||||
with FixedPatchStepper(cfg, context=context, coarse_boundary=mode, refinements=[bounds],
|
||||
level_blocks=blocks, level_objects=[(), tuple(objects)],
|
||||
level_jets=[(), tuple(jets)],
|
||||
observe_raw_exchange=observe) as backend:
|
||||
@@ -435,7 +458,8 @@ class DenseBlockedRouteParity(unittest.TestCase):
|
||||
backend.step(step - backend.step_count)
|
||||
snapshots.append(backend.download() + raw(backend))
|
||||
if observe and step:
|
||||
ledgers.append(tuple(backend.read_raw_exchange(0, window=window)
|
||||
ledgers.append(tuple(backend.read_raw_exchange(body, window=window)
|
||||
for body in bodies
|
||||
for window in ("last_base_step", "last_substep")))
|
||||
backend.initialize(*arrays)
|
||||
snapshots.append(backend.download() + raw(backend))
|
||||
@@ -475,6 +499,24 @@ class DenseBlockedRouteParity(unittest.TestCase):
|
||||
self.check(f"{mode} jet switch",
|
||||
self.run_routes(mode, objects=[circle()], jets=[jet()], switch=-SPEED))
|
||||
|
||||
def test_mrt_bodies(self):
|
||||
"""MRT, periodic root (on_site_velocity slot/reservoir is SRT-only on every route)."""
|
||||
cfg = replace(config("periodic"), collision="MRT")
|
||||
for label, objects, jets, switch in (("circle", [circle()], (), None),
|
||||
("actuated +", [circle(actuation(SPEED))], (), None),
|
||||
("actuated -", [circle(actuation(-SPEED))], (), None),
|
||||
("jet switch", [circle()], [jet()], -SPEED)):
|
||||
self.check(f"MRT periodic {label}",
|
||||
self.run_routes("periodic", objects, jets, switch, cfg=cfg))
|
||||
|
||||
def test_two_bodies(self):
|
||||
"""Two circles on a wider patch (same tiles on every route): Jet + passive, two actuated."""
|
||||
for mode in ("periodic", "slot_reservoir"):
|
||||
for label, objects, jets, switch in TWO_BODY_CASES:
|
||||
self.check(f"{mode} two bodies {label}",
|
||||
self.run_routes(mode, objects(), jets(), switch, bounds=WIDE_BOUNDS,
|
||||
routes=WIDE_ROUTES))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user