test: add POST-G shear initialization counterfactual
This commit is contained in:
1 parent
be8e6d691d
commit
70c83b7233
4 files changed
+225
-16
No files matched your search
@@ -1062,7 +1062,7 @@ class ProbeTraceTests(unittest.TestCase):
|
||||
with self.assertRaises(SystemExit):
|
||||
run_case.main()
|
||||
|
||||
def run_mocked(self, n, depth, diagnostic, scheme, masks):
|
||||
def run_mocked(self, n, depth, diagnostic, scheme, masks, initializer=sw.initial):
|
||||
from types import SimpleNamespace
|
||||
from contextlib import nullcontext
|
||||
arrays = self.exact_arrays(masks, n, 0.0)
|
||||
@@ -1081,7 +1081,9 @@ class ProbeTraceTests(unittest.TestCase):
|
||||
pass
|
||||
|
||||
def initialize(self, *given):
|
||||
pass
|
||||
assert len(given) == depth
|
||||
for level, (values, mask) in enumerate(zip(given, masks)):
|
||||
np.testing.assert_array_equal(values, initializer(mask.shape, level, n, U * n / sw.RE))
|
||||
|
||||
def step(self, count):
|
||||
self.step_count += count
|
||||
@@ -1289,3 +1291,126 @@ class WideXDiagnosticTests(unittest.TestCase):
|
||||
refinements=self.wide.REFINEMENTS)
|
||||
self.assertEqual(helper.mod.assess_nested(records, "r")["status"], "INVALID_SET")
|
||||
self.assertNotIn(run_case.WIDE_X_SHEAR, helper.mod.PRESETS)
|
||||
|
||||
|
||||
class PostGDiagnosticTests(unittest.TestCase):
|
||||
"""Three initialization-only cases, excluded from historical qualification."""
|
||||
|
||||
def setUp(self):
|
||||
import shear_postg
|
||||
self.postg = shear_postg
|
||||
|
||||
def test_moments_phase_and_physical_scaling(self):
|
||||
from CelerisLab.lbm.population_storage import _encode_physical, _decode_stored
|
||||
velocities = np.array([CX, CY], dtype=float).T
|
||||
for level in range(3):
|
||||
shape, nu = (31, 47), .0384
|
||||
h, tau = 2.0**-level, .5 + 3 * nu * 2**level
|
||||
eq = sw.initial(shape, level, 128, nu)
|
||||
g = self.postg.initial(shape, level, 128, nu)
|
||||
x, y = centers(shape, level)
|
||||
k = sw.wavevector(128)
|
||||
strain = (.5 * U * np.cos(k[0] * x + k[1] * y + sw.PHI)[None, None]
|
||||
* (np.outer(sw.E, h * k) + np.outer(h * k, sw.E))[:, :, None, None])
|
||||
tensor = np.einsum("qi,qj->qij", velocities, velocities) - np.eye(2)[None] / 3
|
||||
a = 3 * oracle.W[:, None, None] * np.einsum("qij,ijyx->qyx", tensor, strain)
|
||||
np.testing.assert_allclose(g, eq - (tau - 1) * a, rtol=0, atol=6e-17)
|
||||
for weights in (np.ones(9), CX, CY):
|
||||
np.testing.assert_allclose(np.einsum("q,qyx->yx", weights, g - eq),
|
||||
0, rtol=0, atol=2e-16)
|
||||
stress = np.einsum("qi,qj,qyx->ijyx", velocities, velocities, g - eq)
|
||||
np.testing.assert_allclose(stress, (1 - tau) * 2 / 3 * strain, rtol=0, atol=6e-17)
|
||||
pre = eq - tau * a
|
||||
rho = pre.sum(axis=0)
|
||||
pre_eq = sw.equilibrium(rho, np.einsum("q,qyx->yx", CX, pre) / rho,
|
||||
np.einsum("q,qyx->yx", CY, pre) / rho)
|
||||
np.testing.assert_allclose((1 - 1 / tau) * pre + pre_eq / tau, g, rtol=0, atol=4e-16)
|
||||
self.assertAlmostEqual((tau - .5) * h, .1152, places=16)
|
||||
self.assertGreater(1 - tau, 0)
|
||||
encoded = _decode_stored(_encode_physical(g, True), True)
|
||||
self.assertGreater(encoded.min(), 0)
|
||||
for weights in (np.ones(9), CX, CY):
|
||||
np.testing.assert_allclose(np.einsum("q,qyx->yx", weights, encoded - eq),
|
||||
0, rtol=0, atol=3e-9)
|
||||
# The U512 control is the same physical spacing/tau/phase as nested L2.
|
||||
np.testing.assert_array_equal(self.postg.initial((512, 512), 0, 512, .1536),
|
||||
self.postg.initial((512, 512), 2, 128, .0384))
|
||||
|
||||
def test_actual_initializers_and_three_complete_schedules(self):
|
||||
helper = ProbeTraceTests()
|
||||
helper.setUp()
|
||||
work = 0
|
||||
for _, n, depth, scheme in self.postg.CASES:
|
||||
masks = helper.nested.leaf_masks() if depth == 3 else [np.ones((n, n), bool)]
|
||||
rec, counts, files = helper.run_mocked(n, depth, run_case.POSTG_SHEAR, scheme, masks,
|
||||
initializer=self.postg.initial)
|
||||
self.assertEqual(rec["initialization"], self.postg.INITIALIZATION)
|
||||
self.assertEqual(rec["initialization_id"], "postg_first_gradient_v1")
|
||||
self.assertFalse(rec["qualification_eligible"])
|
||||
self.assertTrue(rec["completed"])
|
||||
self.assertEqual(rec["limits"], sw.LIMITS)
|
||||
self.assertEqual([r["step"] for r in rec["rows"]], run_case.sample_steps(n)[0])
|
||||
self.assertEqual(rec["probe_trace"]["steps"], list(helper.probes.STEPS))
|
||||
self.assertEqual(rec["probe_trace"]["probes"], helper.probes.select(masks, n))
|
||||
self.assertEqual(counts[-1], 16 * n)
|
||||
self.assertIn(1920 * (n // 128), counts)
|
||||
self.assertEqual(files, ["probe.json"])
|
||||
self.assertNotIn("final_snapshot", rec)
|
||||
work += rec["workload"]["active_collision_updates"]
|
||||
self.assertEqual(work, 2952265728)
|
||||
|
||||
def test_fixed_admission_and_source_pin(self):
|
||||
from tests.validation.multigrid import check_projected_pairs as gate
|
||||
repo = HERE.parents[2]
|
||||
self.assertEqual(run_case.SHEAR_POSTG_SHA256,
|
||||
hashlib.sha256((HERE / "shear_postg.py").read_bytes()).hexdigest())
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
base = ["run_case.py", "--repo", str(repo), "--expected-revision", "f" * 40,
|
||||
"--output", str(Path(tmp) / "case.json"), "--dry-run", "--re", "100",
|
||||
"--flow", "shear_wave", "--diagnostic", run_case.POSTG_SHEAR, "--probe-trace"]
|
||||
for n, depth, scheme, valid in ((128, 1, "constant", True), (512, 1, "constant", True),
|
||||
(128, 3, "projected_linear", True),
|
||||
(128, 3, "constant", False), (256, 1, "constant", False),
|
||||
(128, 2, "projected_linear", False)):
|
||||
argv = base + ["--n", str(n), "--depth", str(depth), "--explosion", scheme]
|
||||
extras = ([], ["--final-snapshot"], ["--early-pressure"], ["--re", "1000"],
|
||||
["--flow", "taylor_green"]) if valid else ([],)
|
||||
for extra in extras:
|
||||
with self.subTest(argv=argv + extra), patch.object(sys, "argv", argv + extra), \
|
||||
patch.object(run_case, "verify_source", return_value={}) as verify, \
|
||||
patch.object(run_case, "runtime_source", return_value={}), \
|
||||
redirect_stdout(io.StringIO()), patch("sys.stderr", io.StringIO()):
|
||||
if valid and not extra:
|
||||
self.assertEqual(run_case.main(), 0)
|
||||
verify.assert_called_once_with(repo, "f" * 40, "shear_postg", probes=True)
|
||||
else:
|
||||
with self.assertRaises(SystemExit):
|
||||
run_case.main()
|
||||
verify.assert_not_called()
|
||||
with patch.object(sys, "argv", base[:-1] + ["--n", "128", "--depth", "1"]), \
|
||||
patch("sys.stderr", io.StringIO()):
|
||||
with self.assertRaises(SystemExit):
|
||||
run_case.main()
|
||||
with patch.object(gate, "preflight", return_value=run_case.NUMERICAL_REVISION), \
|
||||
patch.object(run_case, "provenance", return_value=dict(source_tree_sha256=run_case.SOURCE_SHA256)):
|
||||
self.assertEqual(run_case.verify_source(repo, "r", "shear_postg")["shear_postg_sha256"],
|
||||
run_case.SHEAR_POSTG_SHA256)
|
||||
for module, attr, value in ((self.postg, "__file__", "/wrong/shear_postg.py"),
|
||||
(run_case, "SHEAR_POSTG_SHA256", "wrong")):
|
||||
with patch.object(module, attr, value), self.assertRaisesRegex(RuntimeError, "shear_postg"):
|
||||
run_case.verify_source(repo, "r", "shear_postg")
|
||||
|
||||
def test_old_assessors_reject_identity_or_initializer(self):
|
||||
from copy import deepcopy
|
||||
helper = NestedPresetTests()
|
||||
helper.setUp()
|
||||
for base, assessor in ((helper.nested_set(), helper.mod.assess_nested),
|
||||
([receipt(128, 1), receipt(256, 1), receipt(128, 2),
|
||||
receipt(128, 2, "projected_linear")], helper.mod.assess)):
|
||||
self.assertTrue(assessor(base, "r")["passed"])
|
||||
for change in (dict(diagnostic=run_case.POSTG_SHEAR),
|
||||
dict(initialization=self.postg.INITIALIZATION)):
|
||||
records = deepcopy(base)
|
||||
records[-1].update(change)
|
||||
self.assertEqual(assessor(records, "r")["status"], "INVALID_SET")
|
||||
self.assertNotIn(run_case.POSTG_SHEAR, helper.mod.PRESETS)
|
||||
Reference in new issue
Block a user