Retain unbordered residual and central-border diagnostics in summaries

This commit is contained in:
2026-09-19 11:15:28 -04:00
parent d34ae09fc4
commit 54102b4f3c

View File

@@ -128,6 +128,11 @@ def build_rows(audits):
"observer_seconds": case["observer_timings"]["observer_total"], "observer_seconds": case["observer_timings"]["observer_total"],
"elapsed_seconds_including_observers": case["run"]["seconds"], "elapsed_seconds_including_observers": case["run"]["seconds"],
"utc_minus_monotonic_seconds": case["run"]["utc_minus_monotonic_seconds"]} "utc_minus_monotonic_seconds": case["run"]["utc_minus_monotonic_seconds"]}
physical18 = case["physical"]["18"]["metrics"]
# A bordered solve can meet its reported tolerance while the
# 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")
for q in (14, 18): for q in (14, 18):
physical = case["physical"][str(q)]["metrics"] physical = case["physical"][str(q)]["metrics"]
for source, label in (("enthalpy_virial_error", "h_energy_virial"), for source, label in (("enthalpy_virial_error", "h_energy_virial"),
@@ -305,6 +310,7 @@ class Tests(unittest.TestCase):
measure = {"summary": {"30": fine}, "surface": {}, "negative_mass_q30_minus_q22": 0., "negative_volume_q30_minus_q22": 0.} measure = {"summary": {"30": fine}, "surface": {}, "negative_mass_q30_minus_q22": 0., "negative_volume_q30_minus_q22": 0.}
q = {"eos_squared_integral": 4e-8, "eos_defined_everywhere_sampled": True, "volume": 1., "negative_enthalpy_samples": 0} q = {"eos_squared_integral": 4e-8, "eos_defined_everywhere_sampled": True, "volume": 1., "negative_enthalpy_samples": 0}
metrics = {"enthalpy_virial_error": 2e-6, "enthalpy_force_virial_error": 3e-5, metrics = {"enthalpy_virial_error": 2e-6, "enthalpy_force_virial_error": 3e-5,
"normalized_unbordered_residual": .04, "central_border": -.125, "normalized_border_action": .03,
"virial_error": None, "force_virial_error": None} "virial_error": None, "force_virial_error": None}
case = {"artifact_passed": True, "kind": "coupled", "n": 1.5, "J": 0., "K": 1., "density_degree": 2, case = {"artifact_passed": True, "kind": "coupled", "n": 1.5, "J": 0., "K": 1., "density_degree": 2,
"state_size": 50, "block_sizes": {"value/density": 27}, "state_size": 50, "block_sizes": {"value/density": 27},
@@ -327,6 +333,9 @@ class Tests(unittest.TestCase):
self.assertTrue(row["h_energy_virial_q18_within_1e5"]) self.assertTrue(row["h_energy_virial_q18_within_1e5"])
self.assertFalse(row["h_force_virial_q18_within_1e5"]) self.assertFalse(row["h_force_virial_q18_within_1e5"])
self.assertIsNone(row["density_energy_virial_q18_within_1e5"]) self.assertIsNone(row["density_energy_virial_q18_within_1e5"])
self.assertEqual(row["final_normalized_unbordered_residual"], .04)
self.assertEqual(row["final_central_border"], -.125)
self.assertEqual(row["final_normalized_border_action"], .03)
def main(): def main():
@@ -356,6 +365,7 @@ def main():
write_csv(args.output / "coupled_outcomes.csv", coupled, ["case", "n", "J", "density_degree", "source_state_dofs", "density_dofs", 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", "converged", "failure", "accepted_steps", "krylov_iterations", "newton_iteration_seconds", "linear_solve_seconds",
"initial_residual", "final_residual", "final_over_initial_residual", "h_energy_virial_q18", "h_force_virial_q18", "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", "h_energy_virial_q14", "h_force_virial_q14", "negative_mass_over_abs_mass", "negative_volume_fraction",
"negative_classification", "eos_l2_q30", "eos_rms_q30"]) "negative_classification", "eos_l2_q30", "eos_rms_q30"])
write_csv(args.output / "relative_to_Q2.csv", relative) write_csv(args.output / "relative_to_Q2.csv", relative)
@@ -369,6 +379,7 @@ def main():
"Negative-mass denominator is the absolute measured density mass, not a substituted exact target mass.", "Negative-mass denominator is the absolute measured density mass, not a substituted exact target mass.",
"Uncertainty scales are reconstruction indicators, not rigorous bounds; zero observed negativity is not a global positivity certificate.", "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.", "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.",
"Ratios to Q2 compare recorded endpoints and do not imply equal convergence or error tolerances were attained.", "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.", "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."], "P(h) virial milestones do not establish pointwise density validity; density-based virials are retained separately."],