diff --git a/experiments/DAMPED_COUPLED_TRIAL_2026-09-18.md b/experiments/DAMPED_COUPLED_TRIAL_2026-09-18.md index e66d84f..b6cfe1f 100644 --- a/experiments/DAMPED_COUPLED_TRIAL_2026-09-18.md +++ b/experiments/DAMPED_COUPLED_TRIAL_2026-09-18.md @@ -59,7 +59,9 @@ every candidate evaluation, fresh selected-state replay and unchanged accepted buffers/normalization. Only the accepted trial is replayed for quadrature-14 and quadrature-18 physical observations, outside the timed selection phase. -Operation timings exclude artifact output and physical replay; search wall time +Operation timings include raw preparation, gravity correction and the coupled transaction. +They exclude setup, ordinary initial/final metric calls, final restoration, accepted +commit refresh, artifact output and physical replay; search wall time also includes artifact output. Callback vector copies remain in the measured transaction. The no-correction control captures the same tangent for a comparable screen, so capture cost is reported separately and is not ordinary Newton work diff --git a/experiments/plateau_damped_coupled_diagnostics.hpp b/experiments/plateau_damped_coupled_diagnostics.hpp index 7126544..8ff80e9 100644 --- a/experiments/plateau_damped_coupled_diagnostics.hpp +++ b/experiments/plateau_damped_coupled_diagnostics.hpp @@ -133,7 +133,12 @@ void ProbeDampedCoupledPath(State &state, const mfem::Vector &base, const mfem:: const auto baseMetric = evaluate(baseF); mfem::Vector defect(action); defect += baseF; - const bool outerGate = d::Norm(defect) <= options.common.outerLinearTolerance * baseMetric.residualNorm; + const double defectNorm = d::Norm(defect); + const bool outerGate = d::Finite(baseF) && d::Finite(action) && d::Finite(defect) && + std::isfinite(baseMetric.residualNorm) && baseMetric.residualNorm > 0. && + std::isfinite(baseMetric.merit) && baseMetric.merit >= 0. && std::isfinite(d::Norm(direction)) && + std::isfinite(d::Norm(action)) && + std::isfinite(defectNorm) && defectNorm <= options.common.outerLinearTolerance * baseMetric.residualNorm; metric("base_norm", baseMetric.residualNorm); metric("base_merit", baseMetric.merit); metric("outer_relative_defect", d::Norm(defect) / baseMetric.residualNorm); @@ -196,11 +201,17 @@ void ProbeDampedCoupledPath(State &state, const mfem::Vector &base, const mfem:: gravitySeconds = d::Seconds(started); if (gravityGate) d::Save(file("gravity_correction" + suffix), gravity->fullCorrection); } - const bool usable = preparation.has_value() && gravityGate; + // Production rejects an overflowing prepared residual before the + // correction transaction, whose precondition requires a valid metric. + const bool preparedFinite = preparation.has_value() && gravityGate && d::Finite(state.trialNormalizedResidual); + const auto preparedMetric = preparedFinite ? evaluate(state.trialNormalizedResidual) : + solver::nonlinear::MetricEvaluation{nan, nan}; + const bool usable = preparedFinite && std::isfinite(preparedMetric.residualNorm) && + preparedMetric.residualNorm >= 0. && std::isfinite(preparedMetric.merit) && preparedMetric.merit >= 0.; const mfem::Vector before(state.trialNormalizedState); auto beforeMetric = solver::nonlinear::MetricEvaluation{nan, nan}; if (usable) { - beforeMetric = evaluate(state.trialNormalizedResidual); + beforeMetric = preparedMetric; d::Save(file("before" + suffix), before); d::Save(file("before_residual" + suffix), state.trialNormalizedResidual); }