Files
CelerisLab/tests/unit/test_shear_refinement_example.py

85 lines
4.0 KiB
Python

"""CPU-only research-example contracts; no solver/GPU import required."""
import unittest
import numpy as np
from research.shear_refinement.boundary_shear_tagging import tag_cells, strain_rate
from research.shear_refinement.example import (CHILDREN, grow_rectangle, topology,
observe, initial_fields)
class ShearRefinementExample(unittest.TestCase):
def test_affine_shear_physical_spacing_and_rotation(self):
y, x = np.indices((12, 20), dtype=float)
x, y = 7.+.5*(x+.5), 3.+.5*(y+.5)
valid = np.ones(x.shape, bool)
np.testing.assert_allclose(strain_rate(.003*y, 0*x, valid, .5), .003, atol=1e-17)
np.testing.assert_allclose(strain_rate(-.003*y, .003*x, valid, .5), 0., atol=1e-17)
def test_holes_are_unknown_not_walls_or_zero(self):
valid = np.zeros((7, 7), bool); valid[3, 3] = True
u = np.full(valid.shape, np.nan); u[3, 3] = .1
result = tag_cells(u, u, np.zeros_like(valid), valid=valid, owned=valid,
dx_level=.5, origin=(7., 3.), U_ref=.05, L_ref=1.,
shear_on=.01, shear_off=0., band_on=0., band_off=0., n_buffer=0)
self.assertTrue(result.unevaluable[3, 3])
self.assertTrue(np.isnan(result.strain_star[3, 3]))
self.assertFalse(result.tagged.any())
self.assertTrue(np.isinf(result.wall_distance).all())
def test_masked_hole_never_supplies_a_gradient(self):
y, x = np.indices((9, 9), dtype=float)
valid = np.ones(x.shape, bool); valid[:, 4] = False
ux = .003*(5.+.5*y); uy = np.zeros_like(ux)
ux[~valid] = np.inf; uy[~valid] = np.nan
strain = strain_rate(ux, uy, valid, .5)
np.testing.assert_allclose(strain[valid], .003, atol=1e-17)
self.assertTrue(np.isnan(strain[~valid]).all())
def test_predictable_growth_and_input_unchanged(self):
mask = np.zeros((64, 96), bool); mask[22, 74] = True
before = mask.copy()
self.assertEqual(grow_rectangle(CHILDREN[1], mask), (56, 16, 76, 40))
np.testing.assert_array_equal(mask, before)
mask[:] = False
self.assertEqual(grow_rectangle(CHILDREN[1], mask), CHILDREN[1])
def test_budget_and_geometry_rejection(self):
mask = np.zeros((64, 96), bool); mask[22, 74] = True
with self.assertRaisesRegex(ValueError, 'area cap'):
grow_rectangle(CHILDREN[1], mask, area_cap=479)
with self.assertRaises(ValueError):
grow_rectangle((57, 16, 72, 40), mask)
mask = np.zeros((9, 9), bool); mask[8, 8] = True
with self.assertRaisesRegex(ValueError, 'frame'):
grow_rectangle((0, 0, 4, 4), mask)
with self.assertRaises(ValueError):
topology((CHILDREN[0], (56, 16, 88, 40)))
def test_uniform_velocity_observation_does_not_grow(self):
from CelerisLab.lbm.equilibrium import compute_feq_d2q9
mesh = topology()
g = np.broadcast_to(compute_feq_d2q9(1., .01, 0.)[:, None, None],
(9, *mesh.leaf_masks[1].shape)).copy()
g[:, ~mesh.leaf_masks[1]] = np.nan
rectangles, report = observe(g, mesh)
self.assertEqual(rectangles, CHILDREN)
self.assertEqual(report['requested'], 0)
def test_observation_growth_and_low_strain_no_change(self):
mesh = topology()
g = initial_fields(mesh)[1]
g[:, ~mesh.leaf_masks[1]] = np.nan
before = g.copy()
rectangles, report = observe(g, mesh)
self.assertEqual(rectangles, (CHILDREN[0], (56, 16, 76, 40)))
self.assertEqual(report['requested'], 64)
self.assertEqual(report['corridor_unknown'], 0)
self.assertEqual(report['corridor_unavailable'], 0)
self.assertGreater(report['out_of_scope'], 0)
np.testing.assert_array_equal(g, before)
rectangles, report = observe(g, mesh, shear_on=1.)
self.assertEqual(rectangles, CHILDREN)
self.assertEqual(report['requested'], 0)
if __name__ == '__main__': unittest.main()