98 lines
4.9 KiB
Python
98 lines
4.9 KiB
Python
"""CPU geometry tests for lbm.hierarchy (no CUDA). Geometry construction only, not LBM numerics."""
|
|
import unittest
|
|
|
|
import numpy as np
|
|
from CelerisLab.config import LBMConfig
|
|
from CelerisLab.lbm import refinement as r
|
|
from CelerisLab.lbm.hierarchy import build_hierarchy, leaf_partition
|
|
|
|
CFG = LBMConfig(nx=48, ny=48, viscosity=.02)
|
|
L1 = [(6, 6, 26, 26), (32, 30, 42, 42)] # L0 cells; L1 ACTIVE x/y 12..52 and x 64..84, y 60..84
|
|
L2 = [(20, 20, 44, 44), (72, 68, 76, 76)] # L1 cells; L2 ACTIVE 40..88 and x 144..152, y 136..152
|
|
L3 = [(56, 56, 72, 72)] # L2 cells
|
|
FOUR = [L1, L2, L3]
|
|
SMALL = LBMConfig(nx=16, ny=16, viscosity=.1)
|
|
|
|
|
|
class FourLevels(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.h = build_hierarchy(CFG, FOUR)
|
|
|
|
def test_config_chain(self):
|
|
self.assertEqual(self.h.depth, 4)
|
|
for level, c in enumerate(self.h.configs):
|
|
self.assertEqual((c.ny, c.nx), (48 << level, 48 << level))
|
|
self.assertAlmostEqual(c.viscosity, .02 * 2 ** level, places=12)
|
|
self.assertEqual(self.h.kinds[level].shape, (c.ny, c.nx))
|
|
for level, p in enumerate(self.h.pairs):
|
|
self.assertAlmostEqual(p.tau_coarse, 1 / self.h.configs[level].omega, places=12)
|
|
self.assertAlmostEqual(p.tau_fine, 1 / self.h.configs[level + 1].omega, places=12)
|
|
|
|
def test_partition_and_composition(self):
|
|
h = self.h
|
|
np.testing.assert_array_equal(leaf_partition(h), np.ones((48, 48)))
|
|
for level in (1, 2):
|
|
covered, raw = h.pairs[level].covered, h.pairs[level - 1].fine_kind
|
|
self.assertTrue((h.kinds[level][covered] == r.OUTER_GHOST).all())
|
|
np.testing.assert_array_equal(h.kinds[level][~covered], raw[~covered])
|
|
np.testing.assert_array_equal(h.kinds[3], h.pairs[2].fine_kind)
|
|
|
|
def test_depth_is_list_length(self):
|
|
for depth in range(1, 5):
|
|
h = build_hierarchy(CFG, FOUR[:depth - 1])
|
|
self.assertEqual(h.depth, depth)
|
|
np.testing.assert_array_equal(leaf_partition(h), np.ones((48, 48)))
|
|
for level in range(depth - 1):
|
|
np.testing.assert_array_equal(h.kinds[level], self.h.kinds[level])
|
|
|
|
def test_illegal_coverage_reports_first_guard(self):
|
|
cases = [([L1, [(10, 20, 30, 44)]], "inherited ACTIVE"),
|
|
([L1, L2[:1] + [(54, 54, 58, 58)]], "inherited ACTIVE"),
|
|
([L1, L2, [(40, 40, 60, 60)]], "donors/receivers"),
|
|
([L1, L2, [(41, 41, 60, 60)]], "donors/receivers")]
|
|
for levels, reason in cases:
|
|
with self.subTest(levels=levels), self.assertRaisesRegex(ValueError, reason):
|
|
build_hierarchy(CFG, levels)
|
|
build_hierarchy(CFG, [L1, L2, [(56, 56, 64, 64), (66, 56, 72, 64)]]) # gap 2 closes
|
|
build_hierarchy(CFG, [L1, L2, [(42, 42, 60, 60)]]) # minimal legal margin
|
|
|
|
|
|
class LegacyForms(unittest.TestCase):
|
|
def test_scalar_parent_and_child_match_existing_calls(self):
|
|
local = r.FixedPatch2D.from_config(SMALL, (4, 4, 12, 12))
|
|
child, kind = r.nest_patch(SMALL, local, (8, 8, 16, 16))
|
|
h = build_hierarchy(SMALL, [(4, 4, 12, 12), (8, 8, 16, 16)])
|
|
np.testing.assert_array_equal(h.kinds[0], np.where(local.covered, r.OUTER_GHOST, r.ACTIVE))
|
|
np.testing.assert_array_equal(h.kinds[1], kind)
|
|
np.testing.assert_array_equal(h.kinds[2], child.fine_kind)
|
|
for name in ("ghost_fine", "ghost_coarse", "coalesce_coarse", "coalesce_fine"):
|
|
np.testing.assert_array_equal(getattr(h.pairs[1], name), getattr(child, name))
|
|
np.testing.assert_array_equal(leaf_partition(h), np.ones((16, 16)))
|
|
|
|
def test_set_child_under_scalar_parent(self):
|
|
local = r.FixedPatch2D.from_config(SMALL, (4, 4, 12, 12))
|
|
child, kind = r.nest_patch_set(SMALL, local, [(8, 8, 16, 16)])
|
|
h = build_hierarchy(SMALL, [(4, 4, 12, 12), [(8, 8, 16, 16)]])
|
|
np.testing.assert_array_equal(h.kinds[1], kind)
|
|
np.testing.assert_array_equal(h.pairs[1].coalesce_fine, child.coalesce_fine)
|
|
np.testing.assert_array_equal(leaf_partition(h), np.ones((16, 16)))
|
|
|
|
def test_scalar_child_under_set_parent_is_rejected(self):
|
|
with self.assertRaisesRegex(ValueError, "scalar parent"):
|
|
build_hierarchy(SMALL, [[(4, 4, 12, 12)], (12, 12, 20, 20)])
|
|
|
|
def test_wall_rows_and_single_level(self):
|
|
h = build_hierarchy(SMALL, [(4, 4, 12, 12)], wall_aware=True)
|
|
self.assertTrue((h.kinds[0][[0, -1]] == r.OUTER_GHOST).all())
|
|
one = build_hierarchy(SMALL, [])
|
|
self.assertEqual(one.depth, 1)
|
|
self.assertTrue((one.kinds[0] == r.ACTIVE).all())
|
|
walled = build_hierarchy(SMALL, [], wall_aware=True) # regression: no refinement
|
|
self.assertTrue((walled.kinds[0][[0, -1]] == r.OUTER_GHOST).all())
|
|
self.assertTrue((walled.kinds[0][1:-1] == r.ACTIVE).all())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|