Add jet, surface and fixed-patch tests and runnable examples

This commit is contained in:
Frank14f
2026-10-15 10:13:49 +08:00
parent ed1a6ee54e
commit cdbb9c42f6
48 changed files with 9267 additions and 210 deletions
@@ -0,0 +1,97 @@
"""GPU ownership, isolated builds and immutable allocation contracts."""
from pathlib import Path
import numpy as np
import pycuda.driver as cuda
import pytest
import CelerisLab
from CelerisLab.cuda import compiler_v2
from ._cases import make_sim
def test_source_provenance():
root = Path(__file__).resolve().parents[2] / "src/CelerisLab"
assert Path(CelerisLab.__file__).resolve().parent == root
assert Path(compiler_v2.kernel_path("kernel_v2.cu")).resolve() == root / "lbm/kernels/kernel_v2.cu"
def test_two_contexts_interleaved_and_non_lifo_close():
before = cuda.Context.get_current()
first = make_sim(nx=32, ny=16)
second = make_sim(nx=48, ny=24, streaming="esopull", shifted=True)
try:
assert first._build_dir != second._build_dir
assert cuda.Context.get_current() == before
first.initialize()
second.initialize()
for _ in range(3):
first.run(1)
second.run(1)
assert first.get_macroscopic()["rho"].shape == (16, 32)
assert second.get_macroscopic()["rho"].shape == (24, 48)
first.close()
second.run(1)
assert np.isfinite(second.get_macroscopic()["rho"]).all()
assert cuda.Context.get_current() == before
finally:
second.close()
first.close()
def test_structural_change_rejected_before_running():
with make_sim(nx=32, ny=16) as sim:
sim.initialize()
before = sim.get_ddf().copy()
sim.lbm_cfg.nx = 64
with pytest.raises(ValueError, match="allocation|structural"):
sim.run(1)
with pytest.raises(ValueError, match="allocation|structural"):
sim._recompile()
sim.lbm_cfg.nx = 32
np.testing.assert_array_equal(sim.get_ddf(), before)
assert sim.stepper.step_count == 0
sim.run(1)
def test_viscosity_recompile_updates_device_omega():
import struct
with make_sim(nx=32, ny=16) as sim:
sim.lbm_cfg.viscosity = 0.08
sim.recompile()
assert sim.stepper.step_count == 0
sim.initialize()
with sim.ctx.activate():
ptr, _ = sim._module.get_global("d_params")
buf = np.empty(20, dtype=np.uint8)
cuda.memcpy_dtoh(buf, ptr)
omega = struct.unpack("=ffffI", buf.tobytes())[0]
assert omega == pytest.approx(sim.lbm_cfg.omega, rel=1e-7)
sim.run(1)
@pytest.mark.parametrize("streaming",["double_buffer","esopull"])
@pytest.mark.parametrize("prior_steps",[3,4])
def test_reinitialize_matches_fresh_state_and_observation_window(streaming,prior_steps):
with make_sim(nx=32,ny=16,streaming=streaming,shifted=True) as fresh, \
make_sim(nx=32,ny=16,streaming=streaming,shifted=True) as reused:
for sim in (fresh,reused):
sim.add_body("sensor",center=(16,8),radius=2)
sim.initialize()
reused.run(prior_steps)
assert reused.stepper.step_count==prior_steps
assert reused.bodies._obs_accum_steps==prior_steps
reused.initialize()
assert reused.stepper.step_count==0
assert reused.bodies._obs_accum_steps==0
np.testing.assert_array_equal(reused.bodies.obs_pinned,0)
with reused.ctx.activate():
obs=np.empty(reused.bodies.obs_total_floats,np.float32)
cuda.memcpy_dtoh(obs,reused.bodies.obs_gpu)
np.testing.assert_array_equal(obs,0)
np.testing.assert_array_equal(reused.get_ddf(),fresh.get_ddf())
for key,value in fresh.get_macroscopic().items():
np.testing.assert_array_equal(reused.get_macroscopic()[key],value)
# Equal next step proves restored parity, not only equal initialization bytes.
fresh.run(1);reused.run(1)
np.testing.assert_array_equal(reused.get_ddf(),fresh.get_ddf())