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>
This commit is contained in:
1 parent
d5b7e98750
commit
987566c0e6
28 files changed
+2112
-86
No files matched your search
@@ -0,0 +1,50 @@
|
||||
"""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()
|
||||
Reference in new issue
Block a user