test: shear-wave modal-extinction handling; TG mock verify_source flow arg
- shear_wave.fit_rate: finite late R=0 returns rate_fit_valid=false with null fit quantities (no clipping, no invented rate); own screens and budgets treat it as a failure (CONTROL_SCREEN_FAIL / refined FAIL), other finite metrics retained, JSON-safe. - test_projected_pairs: dry-run/execution mocks expect the explicit 'taylor_green' flow argument now passed to verify_source. - run_case: SHEAR_WAVE_SHA256 repinned; extinction test added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f337652683
commit
de5b0cc080
5 files changed
+57
-14
No files matched your search
@@ -155,15 +155,21 @@ def fit_rate(rows, length, viscosity):
|
||||
"""
|
||||
late = [r for r in rows if r["tstar"] >= FIT_FROM_TSTAR - 1e-12]
|
||||
amp = np.array([math.hypot(r["a_hat"], r["b_hat"]) for r in late])
|
||||
if len(late) < 3 or not (np.isfinite(amp).all() and (amp > 0).all()):
|
||||
raise ValueError("need >= 3 late samples with finite positive R")
|
||||
if len(late) < 3 or not np.isfinite(amp).all():
|
||||
raise ValueError("need >= 3 late samples with finite R")
|
||||
exact_rate = decay_rate(length, viscosity)
|
||||
to_tstar = length / U # root steps per unit t*
|
||||
if not (amp > 0).all():
|
||||
# Finite modal extinction: a physical failure, not malformed data. No
|
||||
# clipping and no invented rate; fit quantities are unavailable.
|
||||
return dict(rate_fit_valid=False, rate=None, exact_rate=exact_rate,
|
||||
rate_tstar=None, exact_rate_tstar=exact_rate * to_tstar,
|
||||
rate_error=None, interval_rate_errors=None, log_fit_residual_max=None)
|
||||
t = np.array([r["step"] for r in late], dtype=float)
|
||||
(slope, intercept) = np.polyfit(t, np.log(amp), 1)
|
||||
residual = np.log(amp) - (slope * t + intercept)
|
||||
exact_rate = decay_rate(length, viscosity)
|
||||
to_tstar = length / U # root steps per unit t*
|
||||
return dict(
|
||||
rate=float(-slope), exact_rate=exact_rate,
|
||||
rate_fit_valid=True, rate=float(-slope), exact_rate=exact_rate,
|
||||
rate_tstar=float(-slope * to_tstar),
|
||||
exact_rate_tstar=exact_rate * to_tstar, # = 5 (2 pi)^2 / Re
|
||||
rate_error=abs(-slope / exact_rate - 1),
|
||||
@@ -228,10 +234,11 @@ def summarize(record):
|
||||
velocity_l2=max(r["velocity_l2"] for r in rows),
|
||||
mass_relative=max(r["mass_relative"] for r in rows),
|
||||
)
|
||||
if not all(_number(v) for v in (out["rate"], out["rate_error"], *out["interval_rate_errors"],
|
||||
out["log_fit_residual_max"])):
|
||||
if out["rate_fit_valid"] and not all(
|
||||
_number(v) for v in (out["rate"], out["rate_error"], *out["interval_rate_errors"],
|
||||
out["log_fit_residual_max"])):
|
||||
raise ValueError("nonfinite rate fit")
|
||||
out["own_screens_pass"] = out["complete"] and all(
|
||||
out["own_screens_pass"] = out["complete"] and out["rate_fit_valid"] and all(
|
||||
out[key] <= out["eps"] for key in ("rate_error", "phase_drift_abs", "residual_l2")
|
||||
) and all(out[key] <= limit for key, limit in LIMITS.items())
|
||||
return out
|
||||
@@ -280,12 +287,16 @@ def assess(base_control, fine_control, refined):
|
||||
statuses.append("INVALID_RUN")
|
||||
continue
|
||||
s["valid"] = True
|
||||
# rate_error is None when a modal fit is unavailable; never a pass.
|
||||
s["budget"] = {
|
||||
key: max(BASELINE_FACTOR * base[key], floor) for key, floor in FLOORS.items()
|
||||
key: (None if base[key] is None else max(BASELINE_FACTOR * base[key], floor))
|
||||
for key, floor in FLOORS.items()
|
||||
}
|
||||
s["budget_pass"] = all(s[key] <= s["budget"][key] for key in FLOORS)
|
||||
s["budget_pass"] = all(
|
||||
s[key] is not None and s["budget"][key] is not None and s[key] <= s["budget"][key]
|
||||
for key in FLOORS)
|
||||
s["control_ratios"] = {
|
||||
name: {key: (s[key] / c[key] if c[key] > 0 else None)
|
||||
name: {key: (s[key] / c[key] if s[key] is not None and c[key] else None)
|
||||
for key in (*FLOORS, "spurious_pressure_rms")}
|
||||
for name, c in (("root", base), ("finest", fine))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user