Audit trial rejection stages and expose line-search obstruction counts

This commit is contained in:
2026-09-19 11:21:26 -04:00
parent 54102b4f3c
commit cd71f374f0
2 changed files with 114 additions and 0 deletions

View File

@@ -133,6 +133,12 @@ def build_rows(audits):
# unbordered equations still carry the auxiliary border action.
for key in ("normalized_unbordered_residual", "central_border", "normalized_border_action"):
row["final_" + key] = finite(physical18[key], "final " + key, nonnegative=key != "central_border")
line_search = case["line_search"]
for key in ("pressure_force_rejections", "residual_metric_rejections"):
row[key] = finite(line_search[key], key, True)
row["minimum_accepted_alpha"] = line_search["minimum_accepted_alpha"]
if row["minimum_accepted_alpha"] is not None:
require(0 < finite(row["minimum_accepted_alpha"], "minimum accepted alpha") <= 1, "Invalid accepted step")
for q in (14, 18):
physical = case["physical"][str(q)]["metrics"]
for source, label in (("enthalpy_virial_error", "h_energy_virial"),
@@ -320,6 +326,7 @@ class Tests(unittest.TestCase):
"final_residual": .01, "threshold": 1e-8, "accepted_steps": 1, "linear_iterations": 7,
"iteration_seconds": 10., "iterations": [{"linear_seconds": 6.}]},
"observer_timings": {"observer_total": 200.}, "run": {"seconds": 215., "utc_minus_monotonic_seconds": .01},
"line_search": {"pressure_force_rejections": 4, "residual_metric_rejections": 1, "minimum_accepted_alpha": 1/32},
"physical": {"14": {"metrics": metrics}, "18": {"metrics": metrics}}}
audit = {"artifact_passed": True, "campaigns": {"/recorded/campaign": {
"producer_commit": "test", "mesh_sha256": "test", "cases": {"sample": case}}}}
@@ -336,6 +343,9 @@ class Tests(unittest.TestCase):
self.assertEqual(row["final_normalized_unbordered_residual"], .04)
self.assertEqual(row["final_central_border"], -.125)
self.assertEqual(row["final_normalized_border_action"], .03)
self.assertEqual(row["pressure_force_rejections"], 4)
self.assertEqual(row["residual_metric_rejections"], 1)
self.assertEqual(row["minimum_accepted_alpha"], 1/32)
def main():
@@ -364,6 +374,7 @@ def main():
"surface_minimum_enthalpy", "surface_negative_enthalpy_samples"])
write_csv(args.output / "coupled_outcomes.csv", coupled, ["case", "n", "J", "density_degree", "source_state_dofs", "density_dofs",
"converged", "failure", "accepted_steps", "krylov_iterations", "newton_iteration_seconds", "linear_solve_seconds",
"pressure_force_rejections", "residual_metric_rejections", "minimum_accepted_alpha",
"initial_residual", "final_residual", "final_over_initial_residual", "h_energy_virial_q18", "h_force_virial_q18",
"final_normalized_unbordered_residual", "final_central_border", "final_normalized_border_action",
"h_energy_virial_q14", "h_force_virial_q14", "negative_mass_over_abs_mass", "negative_volume_fraction",
@@ -380,6 +391,7 @@ def main():
"Uncertainty scales are reconstruction indicators, not rigorous bounds; zero observed negativity is not a global positivity certificate.",
"Newton seconds sum reported nonlinear-iteration times, excluding observer and setup costs; total elapsed time is kept separately.",
"Final unbordered residual, signed central border and normalized border action come from q18 physical diagnostics; bordered convergence does not imply that these vanish.",
"Pressure-force and residual-metric rejection counts retain the recorded stage distinction; residual-metric counts include any nonfinite metric failures as well as insufficient decrease.",
"Ratios to Q2 compare recorded endpoints and do not imply equal convergence or error tolerances were attained.",
"Undefined values are null/blank; zero is kept exactly. No logarithmic plot floor is inserted.",
"P(h) virial milestones do not establish pointwise density validity; density-based virials are retained separately."],