# CelerisLab/tests/unit/test_body_flags.py """Body type flag masks — OBSTACLE, SENSOR_FLAG, FRC_REGION bits for circle / sensor / force_region. No GPU required.""" import unittest import numpy as np from CelerisLab.body.manager import ObjectManager from CelerisLab.body.objects import SimObject from CelerisLab.body.geometry.circle import CircleGeometry from CelerisLab.lbm.descriptors import ( FLUID, SOLID, OBSTACLE, BC_CURVED, SENSOR_FLAG, FRC_REGION, ) def _make_obj(cx: float, cy: float, radius: float, is_sensor: bool = False, is_force_region: bool = False) -> SimObject: geom = CircleGeometry(cx, cy, radius) return SimObject(obj_id=-1, geometry=geom, center=(cx, cy), radius=radius, is_sensor=is_sensor, is_force_region=is_force_region) NX, NY = 64, 32 class TestBodyFlags(unittest.TestCase): """Verify flag mask bits for each body type.""" def _obj_flag_mask(self, obj: SimObject) -> np.ndarray: return obj.get_flag_mask(NX, NY) def test_circle_has_obstacle_solid_curved(self): mask = self._obj_flag_mask(_make_obj(32, 16, 5)) center = 32 + 16 * NX self.assertTrue(mask[center] & OBSTACLE, "Circle should have OBSTACLE bit") self.assertTrue(mask[center] & SOLID, "Circle should have SOLID bit") self.assertTrue(mask[center] & BC_CURVED, "Circle should have BC_CURVED bit") self.assertFalse(mask[center] & FLUID, "Circle interior should NOT be FLUID") def test_sensor_has_sensor_flag(self): mask = self._obj_flag_mask(_make_obj(32, 16, 5, is_sensor=True)) center = 32 + 16 * NX self.assertTrue(mask[center] & SENSOR_FLAG, "Sensor should have SENSOR_FLAG bit") self.assertTrue(mask[center] & FLUID, "Sensor should be FLUID") def test_force_region_has_frc_region_flag(self): mask = self._obj_flag_mask( _make_obj(32, 16, 5, is_force_region=True)) center = 32 + 16 * NX self.assertTrue(mask[center] & FRC_REGION, "Force region should have FRC_REGION bit") self.assertTrue(mask[center] & FLUID, "Force region should be FLUID") def test_circle_has_no_sensor_or_frc_flag(self): mask = self._obj_flag_mask(_make_obj(32, 16, 5)) center = 32 + 16 * NX self.assertFalse(mask[center] & SENSOR_FLAG, "Circle should NOT have SENSOR_FLAG") self.assertFalse(mask[center] & FRC_REGION, "Circle should NOT have FRC_REGION") def test_force_region_has_no_obstacle(self): mask = self._obj_flag_mask( _make_obj(32, 16, 5, is_force_region=True)) center = 32 + 16 * NX self.assertFalse(mask[center] & OBSTACLE, "Force region should NOT have OBSTACLE bit") def test_all_body_types_nonzero_masks(self): for obj in [ _make_obj(32, 16, 5), _make_obj(32, 16, 5, is_sensor=True), _make_obj(32, 16, 5, is_force_region=True), ]: mask = self._obj_flag_mask(obj) self.assertGreater(np.count_nonzero(mask), 0, f"{obj.is_sensor=},{obj.is_force_region=}: " "mask should have non-zero entries") if __name__ == "__main__": unittest.main()