Distinguish strategy failures and expose the actual trial tangent

This commit is contained in:
2026-09-17 10:09:22 -04:00
parent 5f3eb0b18c
commit 2e31917269
6 changed files with 152 additions and 13 deletions

View File

@@ -118,6 +118,8 @@ namespace mean_field::solver::detail {
report.gravitySolves = subsystem.GetSolveCount();
report.gravityIterations = subsystem.GetIterationCount();
report.gravityFailures = subsystem.GetFailureCount();
report.gravityPreparedFailures = preparedFailures;
report.lastLinearReportSpace = lastLinearReportSpace;
report.gravitySolveSeconds = subsystem.GetSolveSeconds();
if (const auto &last = subsystem.GetLastSolveReport(); last.has_value()) {
report.lastGravityTrueResidual = last->trueResidualNorm;
@@ -174,6 +176,7 @@ namespace mean_field::solver::detail {
std::isfinite(targetDefect) && targetDefect <= tolerance;
lastPreparedDefect = targetDefect;
}
if (!preparation || !trialSolveSucceeded) { ++preparedFailures; }
return preparation;
}
@@ -186,6 +189,8 @@ namespace mean_field::solver::detail {
double lastCorrectionNorm{0.0};
double lastPreparedDefect{0.0};
double liftedRelativeDefect{0.0};
std::uint64_t preparedFailures{0};
nonlinear::LinearReportSpace lastLinearReportSpace{nonlinear::LinearReportSpace::full_system};
};
template <typename State>
@@ -259,13 +264,18 @@ namespace mean_field::solver::detail {
LinearSolveReport Solve(State &state, const LinearSolveControl &control) {
this->subsystem.Refresh();
try {
this->lastLinearReportSpace = nonlinear::LinearReportSpace::gravity_subsystem;
auto inner = m_operator.TryCondenseRightHandSide(state.linearRightHandSide, m_rhs);
if (!inner.Converged()) { return inner; }
this->subsystem.GetPartition().GatherRetainedValues(state.normalizedCorrection, m_correction);
this->lastLinearReportSpace = nonlinear::LinearReportSpace::reduced_system;
auto report = m_backend.Solve(m_rhs, m_correction, control);
if (!report.Converged()) { return report; }
inner = m_operator.TryLiftCorrection(m_correction, state.linearRightHandSide, state.normalizedCorrection);
if (!inner.Converged()) { return inner; }
if (!inner.Converged()) {
this->lastLinearReportSpace = nonlinear::LinearReportSpace::gravity_subsystem;
return inner;
}
state.normalizedOperator->Mult(state.normalizedCorrection, this->fullAction);
this->fullAction -= state.linearRightHandSide;
const auto communicator = this->subsystem.GetCommunicator();
@@ -283,6 +293,7 @@ namespace mean_field::solver::detail {
}
return report;
} catch (const GravityReductionFailure &failure) {
this->lastLinearReportSpace = nonlinear::LinearReportSpace::gravity_subsystem;
return failure.GetReport();
}
}
@@ -368,9 +379,14 @@ namespace mean_field::solver::detail {
return report;
}
bool CaptureDirection(State &state, nonlinear::NumericalStrategyDiagnostics &diagnostics) {
m_directionSolveFailed = false;
if (!m_enthalpy.Repair(state, diagnostics)) { return false; }
if constexpr (!std::same_as<Gravity, nonlinear::EliminatedGravity> || altersDirection) {
if (!m_gravity.CaptureDirection(state)) { m_gravity.CopyDiagnostics(diagnostics); return false; }
if (!m_gravity.CaptureDirection(state)) {
m_directionSolveFailed = true;
m_gravity.CopyDiagnostics(diagnostics);
return false;
}
}
if constexpr (altersDirection && std::same_as<Gravity, nonlinear::EliminatedGravity>) {
mfem::Vector action(state.Problem().EquationSize());
@@ -389,7 +405,9 @@ namespace mean_field::solver::detail {
return preparation;
}
bool TrialSolveSucceeded() const noexcept { return m_gravity.TrialSolveSucceeded(); }
bool DirectionSolveFailed() const noexcept { return m_directionSolveFailed; }
private:
bool m_directionSolveFailed{false};
PreparedEnthalpyStrategy<State, Enthalpy> m_enthalpy;
PreparedGravityStrategy<State, Gravity> m_gravity;
};