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>
This commit is contained in:
Claude
2026-10-27 15:12:20 +00:00
co-authored by Claude Opus 5.5
parent e18f7abe2b
commit 2b10b01c49
14 changed files with 84 additions and 777 deletions
@@ -53,24 +53,12 @@ def totals(arrays, maps):
def level_storage(level):
"""Raw device storage of one level as dense (9, ny, nx), dense or blocked."""
if level.layout is None:
raw = np.empty(level.shape, np.float32)
cuda.memcpy_dtoh(raw, level.current)
return raw
"""Raw device storage of one blocked level as dense (9, ny, nx)."""
blocked = np.empty(level.layout.blocked_shape, np.float32)
cuda.memcpy_dtoh(blocked, level.current)
return level.layout.to_dense(blocked)
def global_array(module, name, shape):
out = np.empty(shape, dtype=np.uint32)
ptr, size = module.get_global(name)
assert size == out.nbytes
cuda.memcpy_dtoh(out, ptr)
return out
class CoupledGPU(unittest.TestCase):
def test_actual_tg_rates_one_interval(self):
"""Algebraic rate/phase check, not a new physical Taylor--Green benchmark.
@@ -181,11 +169,8 @@ class CoupledGPU(unittest.TestCase):
self.assertFalse(context.is_closed)
print("partial failure: two fine hops completed, no coarse step published; cleanup PASS", flush=True)
def eight_steps(self, backend, spec, maps, audit):
"""Rest and seeded nonequilibrium, 8 steps against the scalar reference.
audit=True also checks the dense CELERIS_REFINEMENT_AUDIT ownership counters.
"""
def eight_steps(self, backend, spec, maps):
"""Rest and seeded nonequilibrium, 8 steps against the scalar reference."""
p = backend.patch
for case in ("rest", "nonequilibrium_seed1"):
with self.subTest(case=case):
@@ -196,11 +181,6 @@ class CoupledGPU(unittest.TestCase):
for a in (state.coarse_f, state.fine_f)))
initial = postcollision(state, spec, maps)
backend.initialize(*initial)
if audit: # dense audit build only
for level in backend._levels:
for name in ("collision_counts", "explosion_counts", "incoming_counts"):
ptr, size = level.module.get_global(name)
cuda.memset_d8(ptr, 0, size)
before = totals(backend.download(), maps)
max_error = max_drift = max_moment_error = max_corner = 0.0
for step in range(1, 9):
@@ -220,17 +200,7 @@ class CoupledGPU(unittest.TestCase):
self.assertLessEqual(drift, MOMENT_ATOL)
self.assertLessEqual(moment_error, MOMENT_ATOL)
max_drift, max_moment_error = max(max_drift, drift), max(max_moment_error, moment_error)
c, f = backend._levels
if audit:
np.testing.assert_array_equal(global_array(c.module, "collision_counts", (16, 16)),
step * maps.coarse_active)
np.testing.assert_array_equal(global_array(f.module, "collision_counts", (24, 24)),
2 * step * maps.fine_active)
np.testing.assert_array_equal(global_array(f.module, "explosion_counts", (24, 24)),
step * ~maps.fine_active)
owners = np.zeros((9, 16, 16), np.uint32)
owners.ravel()[p.coalesce_coarse] = step
np.testing.assert_array_equal(global_array(c.module, "incoming_counts", owners.shape), owners)
f = backend._levels[1]
raw = level_storage(f)
np.testing.assert_array_equal(np.isfinite(raw), diagnostic["hop2_valid"])
self.assertTrue(np.isfinite(raw.ravel()[p.coalesce_fine]).all())
@@ -245,7 +215,7 @@ class CoupledGPU(unittest.TestCase):
max_corner = max(max_corner, error)
print(f"{case}: steps=8 max_population={max_error:.9g} "
f"max_leaf_drift={max_drift:.9g} max_leaf_error={max_moment_error:.9g} "
f"max_corner_packet={max_corner:.9g}; ownership/counts PASS", flush=True)
f"max_corner_packet={max_corner:.9g}; PASS", flush=True)
def test_bounded_equivalence_blocked(self):
"""The same eight-step reference and launch-failure checks on whole-level tiles."""
@@ -255,7 +225,7 @@ class CoupledGPU(unittest.TestCase):
with CudaContext(0) as context:
with PeriodicPatchStepper(cfg, context=context, refinements=[(4, 4, 12, 12)],
level_blocks=[(16, 16), (24, 24)]) as backend:
self.eight_steps(backend, spec, maps, audit=False)
self.eight_steps(backend, spec, maps)
with patch.object(backend._pairs[0], "explode", side_effect=RuntimeError("injected launch failure")):
with self.assertRaisesRegex(RuntimeError, "injected"):
backend.step()
@@ -264,59 +234,5 @@ class CoupledGPU(unittest.TestCase):
operation()
self.assertFalse(context.is_closed)
def test_bounded_equivalence_and_ownership(self):
self.assertEqual(Path(CelerisLab.__file__).resolve(), ROOT / "src/CelerisLab/__init__.py")
self.assertEqual(Path(compiler._KERNEL_DIR).resolve(), ROOT / "src/CelerisLab/lbm/kernels")
spec = ref.make_spec(collision="srt")
maps = ref.build_maps(spec)
cfg = LBMConfig(nx=16, ny=16, viscosity=.1)
compile_original = compiler.compile_kernel
def audit_compile(*args, **kwargs):
# Only this private build's entry differs. Production source unchanged.
entry = Path(kwargs["build_dir"]) / "refinement_audit.cu"
entry.write_text('#define CELERIS_REFINEMENT_AUDIT\n#include "refinement.cu"\n')
kwargs["source"] = entry.name
return compile_original(*args, **kwargs)
with CudaContext(0) as context:
with patch.object(compiler, "compile_kernel", audit_compile):
backend = PeriodicPatchStepper(cfg, context=context, refinements=[(4, 4, 12, 12)])
with backend:
# Production allocations: four DDF arrays and four compact tables.
device_bytes = 2 * 9 * (16**2 + 24**2) * 4
p = backend.patch
device_bytes += sum(a.nbytes for a in (p.ghost_fine, p.ghost_coarse,
p.coalesce_coarse, p.coalesce_fine))
audit_bytes = sum((2 + 9) * np.prod(level.shape[1:]) * 4
for level in backend._levels)
self.assertLess(device_bytes + audit_bytes, 128 * 1024)
print(f"device_arrays={device_bytes} audit_arrays={audit_bytes} bytes", flush=True)
self.eight_steps(backend, spec, maps, audit=True)
# Fail before any additional time step; no stale synchronized export.
with patch.object(backend._pairs[0], "explode", side_effect=RuntimeError("injected launch failure")):
with self.assertRaisesRegex(RuntimeError, "injected"):
backend.step()
with self.assertRaisesRegex(RuntimeError, "failed"):
backend.download()
with self.assertRaisesRegex(RuntimeError, "failed"):
backend.step()
self.assertFalse(context.is_closed)
with self.assertRaisesRegex(RuntimeError, "closed"):
backend.download()
# Compile and execute the actual non-audited entry as well: one step.
with PeriodicPatchStepper(cfg, context=context, refinements=[(4, 4, 12, 12)]) as plain:
rest = postcollision(ref.make_state(spec), spec, maps)
plain.initialize(*rest)
plain.step()
for got, expected in zip(plain.download(), rest):
np.testing.assert_allclose(got, expected, rtol=0, atol=POP_ATOL, equal_nan=True)
print("normal-build rest: steps=1 PASS; source/kernel paths pinned", flush=True)
rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024
print(f"host_peak_rss={rss:.3f} MiB", flush=True)
if __name__ == "__main__":
unittest.main(verbosity=2)