Record gravity relift work before descent rejection

This commit is contained in:
2026-09-17 12:17:10 -04:00
parent b9e6794999
commit c82e68dd7e
3 changed files with 31 additions and 1 deletions

View File

@@ -0,0 +1,26 @@
# Gravity work accounting on direction rejection
The combined polynomial-enthalpy and reduced-gravity strategy checks descent
twice: once when selecting the enthalpy repair, and again after lifting the
repaired retained direction into gravity coordinates. A successful gravity
relift performs real auxiliary work even when the second check rejects the
direction before line search.
Previously, the successful-relift diagnostics were copied only after the second
check. Its early rejection could therefore leave solve counts, iteration counts,
timings, and the last inner residual at their earlier linear-solve snapshot.
The snapshot now occurs immediately after successful direction capture and
before the final descent check. Linear-report coordinates retain their existing
meaning; this changes no tolerance, direction, state, or acceptance decision.
The immutable `b21fa40` rotating `positivity-reduced` artifact records 20 gravity
solves and a positive final merit slope. Those counters can omit a successful
last relift: they do not distinguish rejection during enthalpy repair from
rejection after relifting. Its `direction_repairs` count also includes a chosen
positive repair fraction whose candidate subsequently fails descent. Historical
artifacts must retain these qualifications rather than being retroactively
interpreted as complete work counters.
The regression is a repeat of that bounded combined rotating case, checking
unchanged accepted states and residual history while accounting for all
successful relift work. No extra numerical fixture or solver change is needed.

View File

@@ -72,6 +72,8 @@ export namespace mean_field::solver::nonlinear {
struct NumericalStrategyDiagnostics final {
int polynomialChecks{0};
// Nonzero repair proposals include directions later rejected by a
// descent check; this measures repair activity, not accepted steps.
int directionRepairs{0};
double lastRepairFraction{0.0};
double lastMeritDirectionalDerivative{0.0};

View File

@@ -440,6 +440,9 @@ namespace mean_field::solver::detail {
return false;
}
}
// A successful gravity relift still belongs in the work report if
// the following full-merit check rejects the repaired direction.
m_gravity.CopyDiagnostics(diagnostics);
if constexpr (altersDirection && std::same_as<Gravity, nonlinear::EliminatedGravity>) {
mfem::Vector action(state.Problem().EquationSize());
state.normalizedOperator->Mult(state.normalizedCorrection, action);
@@ -448,7 +451,6 @@ namespace mean_field::solver::detail {
if (!std::isfinite(diagnostics.lastMeritDirectionalDerivative) ||
diagnostics.lastMeritDirectionalDerivative >= 0.0) { return false; }
}
m_gravity.CopyDiagnostics(diagnostics);
return true;
}
auto PrepareTrial(State &state, const double alpha, nonlinear::NumericalStrategyDiagnostics &diagnostics) {