CelerisLab/tests/unit/test_equilibrium.py
Frank14f 987566c0e6 feat(body): runtime body add/remove, unified action/obs, FRC_REGION flag
- Add runtime body topology sync (add_body/remove_body + sync_bodies)
  with recompile, DDF patch (feq + BFS inward fill), and commit.
- Unify action/obs flow: set_body/set_force are now host-only;
  run() auto-uploads action and downloads obs via CUDA stream.
- Add read_body(id) -> BodyTelemetry and read_bodies() for DRL loops.
- Add FRC_REGION flag (0x0800) for force_region cells.
- Extract equilibrium helpers (lbm/equilibrium.py) and DDF patch module
  (body/ddf_patch.py).
- Merge recompile / _runtime_recompile into single _recompile().
- Add n_objects to checkpoint; validate on load.
- Add test suite: 40 unit + 19 integration tests (59 total).
- Add conftest.py and docs/tests_overview.md for test documentation.
- Update README.md and CONFIG.md for new API.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-20 18:17:07 +08:00

51 lines
1.9 KiB
Python

"""D2Q9 equilibrium helpers — compute_feq_d2q9 and compute_macro_from_ddf correctness.
No GPU required."""
import unittest
import numpy as np
from CelerisLab.lbm.equilibrium import compute_feq_d2q9, compute_macro_from_ddf
class TestEquilibrium(unittest.TestCase):
"""Verify D2Q9 equilibrium and macroscopic helpers."""
def test_feq_at_rest(self):
"""Equilibrium at rho=1.0, u=0 should give w_i (weights)."""
feq = compute_feq_d2q9(1.0, 0.0, 0.0)
w = np.array([4/9, 1/9, 1/9, 1/9, 1/9,
1/36, 1/36, 1/36, 1/36], dtype=np.float32)
np.testing.assert_allclose(feq, w, rtol=1e-6)
def test_feq_sums_to_rho(self):
"""Sum of feq should equal rho."""
rho, ux, uy = 1.2, 0.05, -0.02
feq = compute_feq_d2q9(rho, ux, uy)
self.assertAlmostEqual(float(np.sum(feq)), rho, places=6)
def test_macro_preserves_ux_uy(self):
"""compute_macro_from_ddf(feq) should recover rho, ux, uy."""
rho, ux, uy = 1.0, 0.1, 0.0
feq = compute_feq_d2q9(rho, ux, uy)
rho_out, ux_out, uy_out = compute_macro_from_ddf(feq)
self.assertAlmostEqual(rho_out, rho, places=6)
self.assertAlmostEqual(ux_out, ux, places=6)
self.assertAlmostEqual(uy_out, uy, places=6)
def test_feq_nonzero_vel(self):
"""Equilibrium at non-zero velocity should be asymmetric."""
feq_x = compute_feq_d2q9(1.0, 0.1, 0.0)
feq_y = compute_feq_d2q9(1.0, 0.0, 0.1)
# x-directed flow should have f1 > f2 (right > left)
self.assertGreater(feq_x[1], feq_x[2],
"Right-moving f1 should exceed left-moving f2")
# y-directed flow should have f3 > f4 (up > down)
self.assertGreater(feq_y[3], feq_y[4],
"Up-moving f3 should exceed down-moving f4")
if __name__ == "__main__":
unittest.main()