"""Host guards and source contract for MRT reuse in refined/blocked stepping (no CUDA).""" from pathlib import Path import re import unittest from CelerisLab.config import LBMConfig from CelerisLab.lbm.refinement import FixedPatch2D KERNELS = Path(__file__).resolve().parents[2] / "src/CelerisLab/lbm/kernels" BOUNDS = (8, 6, 16, 14) class RefinementMRTHost(unittest.TestCase): def test_patch_accepts_implemented_models(self): for collision in ("SRT", "MRT"): with self.subTest(collision=collision): FixedPatch2D.from_config(LBMConfig(nx=24, ny=20, viscosity=.1, collision=collision), BOUNDS) def test_patch_rejects_unimplemented(self): for options in (dict(collision="TRT"), dict(collision="MRT", les_enabled=True)): with self.subTest(options=options), self.assertRaises(ValueError): FixedPatch2D.from_config(LBMConfig(nx=24, ny=20, viscosity=.1, **options), BOUNDS) def test_srt_statements_and_guards_preserved(self): """MRT is an additive compile-time branch; SRT statements and other guards remain.""" blocks = (KERNELS / "blocked.cu").read_text() + (KERNELS / "step/block_step.cu").read_text() channel = (KERNELS / "step/block_channel.cu").read_text() block_collision = (KERNELS / "operators/block_collision.cuh").read_text() self.assertIn('#include "operators/block_collision.cuh"', blocks) self.assertEqual(blocks.count("block_collide(f);"), 1) for text in ("compute_feq_from_momentum(drho, jx, jy, ux, uy, feq);", "compute_feq(rho, ux, uy, feq);", "collide_srt_no_force(f, feq, d_params.omega);"): self.assertIn(text, block_collision) self.assertIn("collide_srt(f, feq, forcing, omega);", block_collision) self.assertIn("#if COLLISION_MODEL == 2 || BLOCK_ROOT_BC == 2", block_collision) self.assertEqual(channel.count("block_collide(f);"), 1) # Executable text only: the header comment explains the absent force read. code = re.sub(r"//[^\n]*", "", channel + "\n" + block_collision) self.assertIn("d_params.omega", code) for text in ("collide_mrt_unforced", "collide_dispatch(", "d_params.fx", "d_params.fy"): self.assertNotIn(text, code) for source in (blocks,): self.assertIn("(COLLISION_MODEL != 0 && COLLISION_MODEL != 2)", source) self.assertIn("USE_LES", source) self.assertIn("STORE_PRECISION != 0", source) self.assertIn('#if COLLISION_MODEL == 2\n#include "operators/collision_mrt.cuh"\n#endif', source) # One unforced MRT call, in block_collide only; the steps never collide directly. self.assertEqual(block_collision.count("collide_mrt_no_force(f, rho, ux, uy, omega);"), 1) self.assertEqual(block_collision.count("compute_rho_u(f, rho, ux, uy);"), 1) self.assertEqual(block_collision.count("fmaxf(OMEGA_COLLISION_MIN, d_params.omega)"), 1) for source in (blocks, channel): self.assertNotIn("collide_mrt", source) self.assertNotIn("collide_srt", source) if __name__ == "__main__": unittest.main()