Files
CelerisLab/tests/unit/test_example_tiles.py
T
ClaudeandClaude Opus 5.5 2b10b01c49 test: retire dense-route tests, require tiles everywhere (D2)
Retired with the dense refinement route (results recorded at 1573942 and
2469af7 or named as accepted losses):
- test_refinement_blocked_base: BlockedBaseGPU exact parity (3 tests),
  DenseBlockedRouteParity (6 tests incl. MRT and two bodies),
  DenseBlockedRouteCPU (capability matrix, ledger comparator);
- test_refinement_blocked_fine: BlockedFineGPU dense-vs-blocked (3 tests);
- test_refinement_mrt_gpu: test_dense_versus_blocked_mrt_two_level;
- test_raw_exchange_gpu: test_dense_fine_storage_reference (private
  link_exchange cut-link oracle, accepted loss);
- test_refinement_gpu: test_bounded_equivalence_and_ownership (dense
  CELERIS_REFINEMENT_AUDIT ownership counters, accepted loss); its physics
  stays in test_bounded_equivalence_blocked; eight_steps loses the audit
  branch and the misleading 'ownership/counts PASS' label;
- test_fine_surface_gpu: test_fine_surface_four_hops (dense per-hop flux
  ledger, CurvedLinkSoA reflection oracle, audit counts: accepted losses;
  raw exchange covers the boundary part only, not full flux closure) and the
  dense SoA fault tests (missing surface buffer, close frees SoA); blocked
  equivalents remain in test_refinement_blocked_fine/_base;
- test_raw_exchange.test_dense_observation_rejected_before_device_access.
New TileContractCPU: level_blocks omitted/None/wrong length/None entry/
wrong arity/non-integer/bool/non-positive/non-tuple/not dividing all raise
before CUDA; whole-level tiles reach CUDA. Rejection tests and fixtures pass
tiles; launch-order and kernel-text tests follow the blocked root;
examples/fixed_periodic_patch uses whole-level tiles (+ host tile test).

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

71 lines
3.5 KiB
Python

"""The public examples run all-blocked: their level tiles must reach the device unchanged.
Host only: a context whose activation raises proves construction (layouts, tables,
boundary checks) succeeded up to the first CUDA call.
"""
import ast
from dataclasses import replace
from pathlib import Path
import unittest
from unittest.mock import Mock
from CelerisLab.body.geometry.circle import CircleGeometry
from CelerisLab.body.objects import SimObject
from CelerisLab.config import LBMConfig
from CelerisLab.lbm.refinement_stepper import FixedPatchStepper
EXAMPLES = Path(__file__).resolve().parents[2] / "examples"
def literal(name, constant):
"""Module-level literal from an example, read without importing it (no pycuda)."""
tree = ast.parse((EXAMPLES / name).read_text())
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
names = target.elts if isinstance(target, ast.Tuple) else [target]
for i, t in enumerate(names):
if isinstance(t, ast.Name) and t.id == constant:
value = node.value.elts[i] if isinstance(target, ast.Tuple) else node.value
return ast.literal_eval(value)
raise KeyError(constant)
def forbidden():
return Mock(activate=Mock(side_effect=AssertionError("CUDA reached")), sm_arch="sm_70")
class ExampleTiles(unittest.TestCase):
def test_fixed_patch_jet_tiles(self):
bounds, blocks = literal("fixed_patch_jet.py", "BOUNDS"), literal("fixed_patch_jet.py", "LEVEL_BLOCKS")
width, amplitude = literal("fixed_patch_jet.py", "WIDTH"), literal("fixed_patch_jet.py", "AMPLITUDE")
cfg = LBMConfig(nx=48, ny=48, viscosity=.1, velocity=0., wall_slot_width=width,
wall_normal_velocity=amplitude, y_wall_bc="on_site_velocity",
top_wall_bc="reservoir")
with self.assertRaisesRegex(AssertionError, "CUDA reached"):
FixedPatchStepper(cfg, context=forbidden(), coarse_boundary="slot_reservoir",
refinements=[bounds], level_blocks=[tuple(b) for b in blocks])
def test_fixed_periodic_patch_tiles(self):
with self.assertRaisesRegex(AssertionError, "CUDA reached"):
FixedPatchStepper(LBMConfig(nx=16, ny=16, viscosity=.1, velocity=1e-3), context=forbidden(),
refinements=[(4, 4, 12, 12)], level_blocks=[(16, 16), (24, 24)])
def test_fixed_patch_circle_default_tiles(self):
bounds = literal("fixed_patch_circle.py", "BOUNDS")
nx, ny = literal("fixed_patch_circle.py", "NX"), literal("fixed_patch_circle.py", "NY")
center, radius = literal("fixed_patch_circle.py", "CENTER"), literal("fixed_patch_circle.py", "RADIUS")
body = SimObject(0, geometry=CircleGeometry(*center, radius), center=center, radius=radius)
periodic = LBMConfig(nx=nx, ny=ny, viscosity=.1)
slot = replace(periodic, velocity=0, wall_normal_velocity=.001, wall_slot_width=8,
y_wall_bc="on_site_velocity", top_wall_bc="reservoir")
for mode, cfg in (("periodic", periodic), ("slot_reservoir", slot)):
with self.subTest(mode=mode), self.assertRaisesRegex(AssertionError, "CUDA reached"):
FixedPatchStepper(cfg, context=forbidden(), coarse_boundary=mode,
refinements=[bounds], level_blocks=[(12, 8), (16, 20)],
level_objects=[(), (body,)])
if __name__ == "__main__":
unittest.main()