diff --git a/docs/validation/taylor_green.md b/docs/validation/taylor_green.md index 8847a90..cb2281e 100644 --- a/docs/validation/taylor_green.md +++ b/docs/validation/taylor_green.md @@ -337,3 +337,8 @@ Assessment: - These are descriptive. Passing or failing another floor-controlled screen is not the conclusion, and a two-resolution ratio is not a convergence order. +- Portability: the receipt's recomputed `eps = |k|^2` is compared within + 4 ULPs (`close_ulps`), not by exact equality. A cross-runtime replay + differed by one ULP: 0.012047856934923534 on Horsea vs + 0.012047856934923532 elsewhere. Source and file hashes, case identity, + the other metadata and every scientific threshold stay exact. diff --git a/tests/validation/taylor_green/assess_shear_wave.py b/tests/validation/taylor_green/assess_shear_wave.py index da010fd..0793a9b 100644 --- a/tests/validation/taylor_green/assess_shear_wave.py +++ b/tests/validation/taylor_green/assess_shear_wave.py @@ -13,6 +13,7 @@ Taylor-Green-specific checks are replaced by shear-wave metadata and physics. import argparse import hashlib import json +import math from pathlib import Path import assess_projected_pairs as tg @@ -36,11 +37,26 @@ PER_CASE = ("complete_times", "scales", "actual_builds", "reference", "runtime_s "patch", "workload") +METADATA_ULPS = 4 + + +def close_ulps(recorded, expected, ulps=METADATA_ULPS): + """Portable check for recomputed float metadata only (e.g. eps = |k|^2). + + The recorded value comes from another runtime/libm, so exact equality can + fail by one ULP (observed: 0.012047856934923534 Horsea vs ...532 here). + A few ULPs is far below any meaningful change; hashes, case identity and + scientific thresholds stay exact. + """ + return (isinstance(recorded, float) and math.isfinite(recorded) + and abs(recorded - expected) <= ulps * math.ulp(max(abs(recorded), abs(expected)))) + + def metadata_ok(record, n): return (record.get("flow") == "shear_wave" and record.get("mode") == list(sw.MODE) and record.get("polarization") == sw.E.tolist() and record.get("angle_deg") == sw.ANGLE_DEG and record.get("phase") == sw.PHI - and record.get("eps") == sw.eps(n) + and close_ulps(record.get("eps"), sw.eps(n)) and record.get("numerics") == tg.NUMERICS and record.get("initialization") == sw.INITIALIZATION and record.get("limits") == sw.LIMITS diff --git a/tests/validation/taylor_green/test_shear_wave.py b/tests/validation/taylor_green/test_shear_wave.py index 773633a..fe593ed 100644 --- a/tests/validation/taylor_green/test_shear_wave.py +++ b/tests/validation/taylor_green/test_shear_wave.py @@ -427,6 +427,19 @@ class ContractTests(unittest.TestCase): self.assertTrue(result["contract_valid"], [k for k, v in result["checks"].items() if not v]) self.assertEqual(result["status"], "PASS") + def test_eps_metadata_is_portable_but_bounded(self): + import assess_shear_wave + self.assertTrue(assess_shear_wave.close_ulps(0.012047856934923534, 0.012047856934923532)) + exact = sw.eps(128) + for value, ok in ((math.nextafter(exact, 1.0), True), + (math.nextafter(math.nextafter(exact, 0.0), 0.0), True), + (exact * (1 + 1e-12), False), (exact * 2, False), + (str(exact), False), (float("nan"), False), (None, False)): + records = [dict(r) for r in self.records] + records[2]["eps"] = value + status = self.assess(records, "r")["status"] + self.assertEqual(status == "PASS", ok, (value, status)) + def test_reproduced_false_passes_are_rejected(self): a = self.assess self.assertEqual(a(self.records[:2], "r")["status"], "INVALID_SET") # empty refined