Test-only opt-in. New shear_nested.py: fixed parent-frame rectangles (L0->L1 (16,16,60,112),(68,24,112,120); L1->L2 (44,44,108,212), (148,60,212,228)), exact leaves/hops/work/nu/tau, depth-3 + 4N-finest generalization of the shear assessment (same summaries/screens/budgets), bounded final macro snapshot writer/reader (packed ACTIVE leaves + rho/u, metadata, sha256, 8 MiB cap; no populations/restart/time series). run_case: --diagnostic nested_shear_n128 (U128, U512, constant/projected R128 depth 3), --final-snapshot only for projected depth 3, shear_nested.py path+hash pin. assess_shear_wave: assess_nested contract and CLI. shear_wave.py and oracle.py byte-identical; old guards/defaults unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
312 lines
16 KiB
Python
312 lines
16 KiB
Python
"""Fixed four-case shear-wave contracts.
|
|
|
|
Default: N128 (U128, U256, constant R128, projected R128). Opt-in
|
|
--diagnostic scaled_shear_n256: N256 (U256, U512, constant R256, projected
|
|
R256), same physical rectangle, t* schedule, nu = U N / 100, eps(N), limits
|
|
and floors, plus a descriptive comparison with the hash-pinned N128 receipts.
|
|
|
|
Shared provenance, build, workload and sample-time checks are reused from
|
|
assess_projected_pairs (same cases, source pins and geometry); only the
|
|
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
|
|
import shear_wave as sw
|
|
import shear_nested as nested
|
|
from run_case import (NESTED_SHEAR, SCALED_DIAGNOSTIC, SCALED_SHEAR, SHEAR_NESTED_SHA256,
|
|
SHEAR_WAVE_SHA256, sample_steps)
|
|
|
|
# Audited de5b0cc N128 receipts (evidence commit cba6bca, shear-wave-de5b0cc zip).
|
|
REFERENCE_REVISION = "de5b0cc080794d0ce44d37f845aa8e8dbf8c2016"
|
|
REFERENCE_RECEIPTS = {
|
|
"uniform128": "d4a60fb806d04bfa8098a862cceba51e00b49979a6a250fef17a5fc8e3ea3255",
|
|
"uniform256": "e0b58e734724be5f82ee5d6df84395e3181b4e96e4246dd5a574ea23a8d12386",
|
|
"constant128": "c70d7cd14b1257a01cc49f8edfcc7685d430e5301e2f2d60ed426936f8b96c51",
|
|
"projected128": "980161458b9463af09a8e3178063fea0f4bbeb465329e1d3becdb0f224537b54",
|
|
}
|
|
ROLES = ("uniform_root", "uniform_fine", "constant", "projected_linear")
|
|
|
|
SHARED = ("complete_matrix", "no_extra_cases", "no_duplicate_cases", "finite_receipts",
|
|
"same_source_and_harness", "clean_a135252_numerical_source",
|
|
"same_recorded_runtime", "same_explicit_device", "same_early_sampling")
|
|
PER_CASE = ("complete_times", "scales", "actual_builds", "reference", "runtime_source",
|
|
"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 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
|
|
and record.get("early_pressure") == dict(enabled=False, rows=[],
|
|
sampled_max_pressure_l2=None)
|
|
and (record.get("source") or {}).get("shear_wave_sha256") == SHEAR_WAVE_SHA256)
|
|
|
|
|
|
def cases_for(scaled):
|
|
factor = 2 if scaled else 1
|
|
return tuple((re, n * factor, depth, scheme) for re, n, depth, scheme in tg.CASES)
|
|
|
|
|
|
def assess(records, expected_revision=None, *, scaled=False):
|
|
if not isinstance(records, list) or not all(isinstance(r, dict) for r in records):
|
|
raise ValueError("records must be a list of receipt objects")
|
|
# The scaled TG assessor supplies N256/512 cases, builds and workload; its
|
|
# TG-only diagnostic identity and early-sampling checks are not used here.
|
|
base_checks = tg.assess(records, expected_revision,
|
|
diagnostic=SCALED_DIAGNOSTIC if scaled else None)["checks"]
|
|
checks = {name: base_checks.get(name, False) for name in SHARED}
|
|
checks["shear_diagnostic_identity"] = all(
|
|
r.get("diagnostic") == (SCALED_SHEAR if scaled else None) for r in records)
|
|
cases = cases_for(scaled)
|
|
indexed = {}
|
|
for r in records:
|
|
indexed.setdefault(tuple(r.get(k) for k in ("re_L", "n", "depth", "explosion")), r)
|
|
for key in cases:
|
|
_, n, depth, scheme = key
|
|
label = f"{n}/{depth}/{scheme}"
|
|
for name in PER_CASE:
|
|
checks[f"{label} {name}"] = base_checks.get(f"{label} {name}", False)
|
|
checks[f"{label} shear_metadata"] = key in indexed and metadata_ok(indexed[key], n)
|
|
contract_valid = all(checks.values())
|
|
result = dict(checks=checks, contract_valid=contract_valid,
|
|
cases=[list(k) for k in cases], expected_revision=expected_revision,
|
|
diagnostic=SCALED_SHEAR if scaled else None,
|
|
scope="2D periodic Re100 oblique (2,1) shear wave; one phase and one "
|
|
"rectangle; no placement robustness or convergence order")
|
|
if not contract_valid:
|
|
result.update(status="INVALID_SET", passed=False)
|
|
return result
|
|
try:
|
|
physics = sw.assess(indexed[cases[0]], indexed[cases[1]],
|
|
[indexed[cases[2]], indexed[cases[3]]])
|
|
except (KeyError, ValueError) as error:
|
|
result.update(status="INVALID_SET", passed=False, reason=str(error))
|
|
return result
|
|
result.update(physics=physics, status=physics["status"],
|
|
passed=physics["status"] == "PASS")
|
|
try:
|
|
result["signed"] = signed_summary([indexed[k] for k in cases])
|
|
except (KeyError, TypeError, ValueError) as error:
|
|
result["signed_unavailable"] = str(error)
|
|
return result
|
|
|
|
|
|
CASE_AGNOSTIC = ("finite_receipts", "same_source_and_harness", "clean_a135252_numerical_source",
|
|
"same_recorded_runtime", "same_explicit_device", "same_early_sampling")
|
|
|
|
|
|
def _nested_case_ok(r, n, depth):
|
|
"""Per-case identity of the fixed nested preset (scales, builds, patch, work, pins)."""
|
|
runtime = r.get("runtime_source", {})
|
|
package = Path(runtime.get("checkout", "")) / "src/CelerisLab"
|
|
cells = [n * n] if depth == 1 else nested.LEAVES
|
|
hops = [16 * n * 2**level for level in range(depth)]
|
|
work = r.get("workload", {})
|
|
snapshot = r.get("final_snapshot")
|
|
expected_patch = [] if depth == 1 else nested.REFINEMENTS
|
|
return {
|
|
"complete_times": r.get("completed") is True and tg.at_steps(
|
|
r.get("rows", []), sample_steps(n)[0], n),
|
|
"scales": (r.get("U") == sw.U and tg.finite(r.get("viscosity"))
|
|
and abs(r["viscosity"] - sw.U * n / 100) < 1e-15
|
|
and r.get("tau_by_level") == [0.5 + 3 * sw.U * n / 100 * 2**l
|
|
for l in range(depth)]
|
|
and r.get("mach") == sw.U * math.sqrt(3)),
|
|
"actual_builds": tg.valid_builds(r, n, depth),
|
|
"reference": (r.get("numerical_revision") == tg.NUMERICAL_REVISION
|
|
and r.get("reference_harness") == tg.REFERENCE_HARNESS),
|
|
"runtime_source": bool(runtime.get("checkout")) and all(
|
|
runtime.get(k) == str(package / tail) for k, tail in
|
|
(("module", "__init__.py"), ("compiler", "cuda/compiler_v2.py"),
|
|
("kernel_root", "lbm/kernels"))),
|
|
"patch": json.dumps(r.get("refinements")) == json.dumps(expected_patch),
|
|
"workload": (work.get("active_cells_by_level") == cells and work.get("level_hops") == hops
|
|
and work.get("root_intervals") == 16 * n
|
|
and work.get("active_collision_updates_by_level") == [
|
|
c * h for c, h in zip(cells, hops)]
|
|
and work.get("active_collision_updates") == sum(
|
|
c * h for c, h in zip(cells, hops))),
|
|
"shear_metadata": metadata_ok(r, n),
|
|
"nested_module_pin": (r.get("source") or {}).get("shear_nested_sha256")
|
|
== SHEAR_NESTED_SHA256,
|
|
# Optional, projected depth-3 only; bounded and hashed when present.
|
|
"snapshot": snapshot is None or (
|
|
depth == nested.DEPTH and r.get("explosion") == "projected_linear"
|
|
and snapshot.get("kept") is True and isinstance(snapshot.get("sha256"), str)
|
|
and len(snapshot["sha256"]) == 64
|
|
and 0 < snapshot.get("bytes", 0) <= nested.SNAPSHOT_MAX_BYTES
|
|
and snapshot.get("leaf_counts") == nested.LEAVES
|
|
and snapshot.get("step") == sample_steps(n)[0][-1]),
|
|
}
|
|
|
|
|
|
def assess_nested(records, expected_revision=None):
|
|
"""Fixed nested_shear_n128 four-case contract (U128, U512, constant/projected R128 d3)."""
|
|
if not isinstance(records, list) or not all(isinstance(r, dict) for r in records):
|
|
raise ValueError("records must be a list of receipt objects")
|
|
base_checks = tg.assess(records, expected_revision)["checks"]
|
|
checks = {name: base_checks.get(name, False) for name in CASE_AGNOSTIC}
|
|
indexed, duplicates = {}, []
|
|
for r in records:
|
|
key = tuple(r.get(k) for k in ("re_L", "n", "depth", "explosion"))
|
|
(duplicates.append(key) if key in indexed else indexed.__setitem__(key, r))
|
|
checks.update(complete_matrix=all(k in indexed for k in nested.CASES),
|
|
no_extra_cases=set(indexed) <= set(nested.CASES),
|
|
no_duplicate_cases=not duplicates,
|
|
shear_diagnostic_identity=all(r.get("diagnostic") == NESTED_SHEAR
|
|
for r in records))
|
|
for key in nested.CASES:
|
|
_, n, depth, scheme = key
|
|
label = f"{n}/{depth}/{scheme}"
|
|
case = _nested_case_ok(indexed[key], n, depth) if key in indexed else {}
|
|
for name in ("complete_times", "scales", "actual_builds", "reference", "runtime_source",
|
|
"patch", "workload", "shear_metadata", "nested_module_pin", "snapshot"):
|
|
checks[f"{label} {name}"] = bool(case.get(name, False))
|
|
contract_valid = all(checks.values())
|
|
result = dict(checks=checks, contract_valid=contract_valid, diagnostic=NESTED_SHEAR,
|
|
cases=[list(k) for k in nested.CASES], expected_revision=expected_revision,
|
|
finest_control="uniform 4N (U512)",
|
|
scope="2D periodic Re100 oblique (2,1) shear wave; fixed three-level/two-region "
|
|
"placement; changes placement and refined volume as well as depth, so no "
|
|
"isolated-level cost or resolution trend")
|
|
if not contract_valid:
|
|
result.update(status="INVALID_SET", passed=False)
|
|
return result
|
|
try:
|
|
physics = nested.assess(indexed[nested.CASES[0]], indexed[nested.CASES[1]],
|
|
[indexed[nested.CASES[2]], indexed[nested.CASES[3]]])
|
|
except (KeyError, ValueError) as error:
|
|
result.update(status="INVALID_SET", passed=False, reason=str(error))
|
|
return result
|
|
result.update(physics=physics, status=physics["status"], passed=physics["status"] == "PASS")
|
|
try:
|
|
# Role "uniform_fine" here is the 4N finest control.
|
|
result["signed"] = signed_summary([indexed[k] for k in nested.CASES])
|
|
except (KeyError, TypeError, ValueError) as error:
|
|
result["signed_unavailable"] = str(error)
|
|
return result
|
|
|
|
|
|
def _signed(record):
|
|
"""Raw signed quantities of one valid record (None when the fit is unavailable)."""
|
|
s = sw.summarize(record)
|
|
bias = None if not s["rate_fit_valid"] else s["rate"] / s["exact_rate"] - 1
|
|
return dict(n=record["n"], depth=record["depth"], explosion=record["explosion"],
|
|
rate_fit_valid=s["rate_fit_valid"], signed_rate_bias=bias,
|
|
rate_tstar=s["rate_tstar"], exact_rate_tstar=s["exact_rate_tstar"],
|
|
interval_rate_errors=s["interval_rate_errors"],
|
|
residual_l2=s["residual_l2"], spurious_pressure_scaled=s["spurious_pressure_scaled"],
|
|
spurious_pressure_rms=s["spurious_pressure_rms"],
|
|
final_amplitude_error=record["rows"][-1]["amplitude_error"])
|
|
|
|
|
|
def signed_summary(records):
|
|
"""Signed bias per case and refined excess over each uniform control."""
|
|
rows = dict(zip(ROLES, (_signed(r) for r in records)))
|
|
|
|
def minus(a, b):
|
|
return None if a is None or b is None else a - b
|
|
|
|
for role in ("constant", "projected_linear"):
|
|
for control in ("uniform_root", "uniform_fine"):
|
|
rows[role][f"excess_over_{control}"] = {
|
|
key: minus(rows[role][key], rows[control][key])
|
|
for key in ("signed_rate_bias", "residual_l2", "spurious_pressure_rms")}
|
|
return rows
|
|
|
|
|
|
def load_reference(paths):
|
|
"""The four audited N128 receipts verbatim; never relabelled as fresh controls."""
|
|
blobs = [Path(path).read_bytes() for path in paths]
|
|
hashes = {hashlib.sha256(blob).hexdigest() for blob in blobs}
|
|
if len(blobs) != 4 or hashes != set(REFERENCE_RECEIPTS.values()):
|
|
raise ValueError("N128 receipt hashes differ from the audited de5b0cc evidence")
|
|
return [json.loads(blob) for blob in blobs]
|
|
|
|
|
|
def resolution_trend(new_result, reference, reference_revision=REFERENCE_REVISION):
|
|
"""Descriptive N128 -> N256 signed changes; never an acceptance gate or an order."""
|
|
old_result = assess(reference, reference_revision)
|
|
if "signed" not in old_result or "signed" not in new_result:
|
|
return dict(valid=False, reason="N128 reference or N256 set lacks a valid signed summary")
|
|
out = {}
|
|
for role in ROLES:
|
|
old, new = old_result["signed"][role], new_result["signed"][role]
|
|
out[role] = {}
|
|
for key in ("signed_rate_bias", "residual_l2", "spurious_pressure_rms",
|
|
*(f"excess_over_{c}" for c in ("uniform_root", "uniform_fine"))):
|
|
if key not in old:
|
|
continue
|
|
pairs = old[key].items() if isinstance(old[key], dict) else [(None, old[key])]
|
|
for sub, low in pairs:
|
|
high = new[key][sub] if sub else new[key]
|
|
ok = low is not None and high is not None
|
|
out[role][key if sub is None else f"{key}.{sub}"] = dict(
|
|
n128=low, n256=high, signed_change=high - low if ok else None,
|
|
n256_to_n128=high / low if ok and low else None)
|
|
return dict(valid=True, reference_revision=reference_revision,
|
|
reference_receipt_sha256=REFERENCE_RECEIPTS,
|
|
reference_status=old_result["status"], changes=out,
|
|
scope="same-placement two-resolution trend; not a convergence order, "
|
|
"placement robustness or redesign decision")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
p = argparse.ArgumentParser(description=__doc__)
|
|
p.add_argument("files", type=Path, nargs=4)
|
|
p.add_argument("--output", type=Path, required=True)
|
|
p.add_argument("--expected-revision", required=True)
|
|
p.add_argument("--diagnostic", choices=[SCALED_SHEAR, NESTED_SHEAR])
|
|
p.add_argument("--reference-files", type=Path, nargs=4)
|
|
args = p.parse_args()
|
|
if args.output.exists():
|
|
p.error("Output already exists; choose a new path to retain prior evidence")
|
|
if args.diagnostic == NESTED_SHEAR:
|
|
if args.reference_files:
|
|
p.error("nested_shear_n128 takes no reference files (no resolution trend)")
|
|
result = assess_nested([json.loads(path.read_text()) for path in args.files],
|
|
args.expected_revision)
|
|
text = json.dumps(result, indent=2, allow_nan=False) + "\n"
|
|
args.output.write_text(text)
|
|
print(text, end="")
|
|
raise SystemExit(0 if result["passed"] else 1)
|
|
if bool(args.diagnostic) != bool(args.reference_files):
|
|
p.error("--diagnostic scaled_shear_n256 requires --reference-files (N128 receipts)")
|
|
result = assess([json.loads(path.read_text()) for path in args.files], args.expected_revision,
|
|
scaled=bool(args.diagnostic))
|
|
if args.diagnostic:
|
|
try:
|
|
reference = load_reference(args.reference_files)
|
|
except ValueError as exc:
|
|
p.error(str(exc))
|
|
result["resolution_trend"] = resolution_trend(result, reference)
|
|
text = json.dumps(result, indent=2, allow_nan=False) + "\n"
|
|
args.output.write_text(text)
|
|
print(text, end="")
|
|
raise SystemExit(0 if result["passed"] else 1)
|