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

This commit is contained in:
Frank14f committed 2026-10-15 10:13:49 +08:00
1 parent ed1a6ee54e
commit cdbb9c42f6
48 files changed
+9267 -210

No files matched your search

@@ -20,7 +20,6 @@ from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Sequence, Tuple
import numpy as np
import pycuda.driver as cuda
_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
_DEFAULT_LBM = os.path.join(_REPO, "src", "CelerisLab", "configs", "config_lbm.json")
@@ -272,76 +271,71 @@ def _run_one(
)
body = _body_doc(domain.center, alpha=spec.alpha)
tmpd = tempfile.mkdtemp(prefix="celeris_kan99b_mrt_")
lbm_tmp = os.path.join(tmpd, "config_lbm.json")
body_tmp = os.path.join(tmpd, "config_body.json")
_write_json(lbm_tmp, cfg)
_write_json(body_tmp, body)
from CelerisLab import Simulation
from CelerisLab import Simulation # noqa: WPS433
with tempfile.TemporaryDirectory(prefix="celeris_kan99b_mrt_") as tmpd:
lbm_tmp = os.path.join(tmpd, "config_lbm.json")
body_tmp = os.path.join(tmpd, "config_body.json")
_write_json(lbm_tmp, cfg)
_write_json(body_tmp, body)
with Simulation(lbm_config_path=lbm_tmp, body_config_path=body_tmp) as sim, sim.ctx.activate():
if sim.bodies.count < 1:
raise RuntimeError("Expected one cylinder in body config.")
sim.bodies.get(0).state.omega = np.float32(_omega_body(spec.alpha))
sim.initialize()
sim = Simulation(lbm_config_path=lbm_tmp, body_config_path=body_tmp)
if sim.bodies.count < 1:
sim.close()
raise RuntimeError("Expected one cylinder in body config.")
sim.bodies.get(0).state.omega = np.float32(_omega_body(spec.alpha))
sim.initialize()
stream = sim.stream
rec = max(1, int(record_every))
total = int(spec.burn) + int(spec.steps)
if total < 1:
raise ValueError("burn + steps must be >= 1")
stream = cuda.Stream()
rec = max(1, int(record_every))
total = int(spec.burn) + int(spec.steps)
if total < 1:
sim.close()
raise ValueError("burn + steps must be >= 1")
step_hist: List[int] = []
fx_hist: List[float] = []
fy_hist: List[float] = []
field_snapshots: List[str] = []
run_id = _run_id(spec)
snap_dir = os.path.join(out_dir, "fields", run_id)
if field_every > 0:
os.makedirs(snap_dir, exist_ok=True)
step_hist: List[int] = []
fx_hist: List[float] = []
fy_hist: List[float] = []
field_snapshots: List[str] = []
run_id = _run_id(spec)
snap_dir = os.path.join(out_dir, "fields", run_id)
if field_every > 0:
os.makedirs(snap_dir, exist_ok=True)
for step in range(1, total + 1):
sim.bodies.zero_force_segment_async(stream)
sim.stepper.step(
1,
action_gpu=sim.bodies.action_gpu,
obs_gpu=sim.bodies.obs_gpu,
stream=stream,
)
if step % rec == 0 or step == total:
stream.synchronize()
sim.bodies.download_obs_full_async(stream)
stream.synchronize()
force = sim.bodies.read_force(0, normalize=False)
fx = float(force[0])
fy = float(force[1])
if not np.isfinite(fx) or not np.isfinite(fy):
raise RuntimeError(f"NaN/Inf force at step {step}")
step_hist.append(step)
fx_hist.append(fx)
fy_hist.append(fy)
if field_every > 0 and (step % int(field_every) == 0 or step == total):
stream.synchronize()
macro = sim.get_macroscopic()
snap_path = os.path.join(snap_dir, f"macro_step{step:08d}.npz")
np.savez_compressed(
snap_path,
rho=np.asarray(macro["rho"], dtype=np.float32),
ux=np.asarray(macro["ux"], dtype=np.float32),
uy=np.asarray(macro["uy"], dtype=np.float32),
)
field_snapshots.append(snap_path)
for step in range(1, total + 1):
sim.bodies.zero_force_segment_async(stream)
sim.stepper.step(
1,
action_gpu=sim.bodies.action_gpu,
obs_gpu=sim.bodies.obs_gpu,
stream=stream,
)
if step % rec == 0 or step == total:
stream.synchronize()
sim.bodies.download_obs_full_async(stream)
stream.synchronize()
force = sim.bodies.read_force(0, normalize=False)
fx = float(force[0])
fy = float(force[1])
if not np.isfinite(fx) or not np.isfinite(fy):
sim.close()
raise RuntimeError(f"NaN/Inf force at step {step}")
step_hist.append(step)
fx_hist.append(fx)
fy_hist.append(fy)
if field_every > 0 and (step % int(field_every) == 0 or step == total):
stream.synchronize()
macro = sim.get_macroscopic()
snap_path = os.path.join(snap_dir, f"macro_step{step:08d}.npz")
np.savez_compressed(
snap_path,
rho=np.asarray(macro["rho"], dtype=np.float32),
ux=np.asarray(macro["ux"], dtype=np.float32),
uy=np.asarray(macro["uy"], dtype=np.float32),
)
field_snapshots.append(snap_path)
stream.synchronize()
macro_last = sim.get_macroscopic()
ux_last = np.asarray(macro_last["ux"], dtype=np.float64).reshape(domain.ny, domain.nx)
uy_last = np.asarray(macro_last["uy"], dtype=np.float64).reshape(domain.ny, domain.nx)
rho_last = np.asarray(macro_last["rho"], dtype=np.float64).reshape(domain.ny, domain.nx)
sim.close()
macro_last = sim.get_macroscopic()
ux_last = np.asarray(macro_last["ux"], dtype=np.float64).reshape(domain.ny, domain.nx)
uy_last = np.asarray(macro_last["uy"], dtype=np.float64).reshape(domain.ny, domain.nx)
rho_last = np.asarray(macro_last["rho"], dtype=np.float64).reshape(domain.ny, domain.nx)
step_arr = np.asarray(step_hist, dtype=np.int64)
fx_arr = np.asarray(fx_hist, dtype=np.float64)
@@ -686,7 +680,10 @@ def main() -> int:
print(f"Wrote: {summary_csv}", flush=True)
print(f"Wrote: {json_out}", flush=True)
return 0
failed = any("error" in row for row in rows)
if not args.smoke:
failed |= any(not gate["pass_all"] for gate in k2_gate)
return int(failed)
if __name__ == "__main__":