Add bounded coupled damping and prediction-based attempt selection
This commit is contained in:
@@ -47,6 +47,21 @@ namespace stellar_numerical_strategy_test {
|
||||
static_assert(!MakesTrialNumerics<nonlinear::PolynomialEnthalpy, nonlinear::EliminatedGravity,
|
||||
nonlinear::CoupledCurvatureCorrection>);
|
||||
static_assert(!MakesTrialNumerics<nonlinear::SampledEnthalpy, nonlinear::MonolithicGravity, UnregisteredTrial>);
|
||||
static_assert(nonlinear::CoupledTrialNumerics<nonlinear::CoupledCurvatureCorrection>);
|
||||
static_assert(nonlinear::CoupledTrialNumerics<nonlinear::BacktrackedCoupledCurvatureCorrection>);
|
||||
static_assert(!nonlinear::CoupledTrialNumerics<nonlinear::UncorrectedTrial>);
|
||||
static_assert(!nonlinear::TrialPathNumerics<solver::BacktrackedCoupledStep>);
|
||||
static_assert(MakesTrialNumerics<nonlinear::SampledEnthalpy, nonlinear::MonolithicGravity,
|
||||
nonlinear::BacktrackedCoupledCurvatureCorrection>);
|
||||
static_assert(MakesTrialNumerics<nonlinear::PolynomialEnthalpy, nonlinear::GravityCurvatureCorrection,
|
||||
nonlinear::BacktrackedCoupledCurvatureCorrection>);
|
||||
static_assert(!MakesTrialNumerics<nonlinear::SampledEnthalpy, nonlinear::EliminatedGravity,
|
||||
nonlinear::BacktrackedCoupledCurvatureCorrection>);
|
||||
static_assert(!MakesTrialNumerics<nonlinear::PolynomialEnthalpy, nonlinear::EliminatedGravity,
|
||||
nonlinear::BacktrackedCoupledCurvatureCorrection>);
|
||||
static_assert(std::same_as<typename decltype(nonlinear::NewtonNumerics{nonlinear::SampledEnthalpy{},
|
||||
nonlinear::MonolithicGravity{}, nonlinear::BacktrackedCoupledCurvatureCorrection{}})::TrialType,
|
||||
nonlinear::BacktrackedCoupledCurvatureCorrection>);
|
||||
|
||||
|
||||
[[nodiscard]] double matchingCentralDensity() {
|
||||
@@ -186,6 +201,11 @@ TEST_CASE("Typed numerical policies preserve the existing Newton configuration",
|
||||
const auto selected = nonlinear::Newton(nonlinear::NewtonOptions{}, nonlinear::NormalizedResidualMetric{},
|
||||
nonlinear::NewtonNumerics{nonlinear::SampledEnthalpy{}, nonlinear::GravityCurvatureCorrection{}});
|
||||
CHECK(selected.numerics().gravity.gravity.control.relativeTolerance == 1.e-10);
|
||||
const nonlinear::BacktrackedCoupledCurvatureCorrection damped;
|
||||
CHECK(damped.search.maximumSteps == 4);
|
||||
CHECK(damped.search.reduction == .5);
|
||||
CHECK(damped.attempt.maximumExcessRatio == 1.0);
|
||||
CHECK(damped.maximumAttemptsPerIteration == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Production gravity strategies retain optional model borders and restore rejected trials",
|
||||
@@ -300,25 +320,28 @@ TEST_CASE("Polynomial admissibility is invoked by each production gravity strate
|
||||
check(nonlinear::EliminatedGravity{permissiveGravity()});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
{
|
||||
const auto checkTrial = [&](auto correction) {
|
||||
const auto report = evaluate(context, nonlinear::NewtonNumerics{polynomial,
|
||||
nonlinear::MonolithicGravity{}, nonlinear::CoupledCurvatureCorrection{}});
|
||||
nonlinear::MonolithicGravity{}, correction});
|
||||
CHECK_FALSE(report.converged());
|
||||
CHECK(report.diagnostics().numericalStrategies.polynomialChecks > 0);
|
||||
CHECK(report.diagnostics().acceptedNonlinearIterations == 0);
|
||||
CHECK(report.lastAcceptedCheckpointView().valid());
|
||||
}
|
||||
};
|
||||
checkTrial(nonlinear::CoupledCurvatureCorrection{});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
checkTrial(nonlinear::BacktrackedCoupledCurvatureCorrection{});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
}
|
||||
|
||||
TEST_CASE("Coupled trial selection keeps the outer linear report and rejected stellar checkpoint",
|
||||
"[solver][numerical_strategies][coupled_trial_correction][rollback]") {
|
||||
"[solver][numerical_strategies][coupled_trial_correction][backtracked][rollback]") {
|
||||
using namespace stellar_numerical_strategy_test;
|
||||
auto context = makeContext<false>();
|
||||
const auto original = snapshot(context);
|
||||
const auto check = [&](auto gravity) {
|
||||
const nonlinear::CoupledCurvatureCorrection correction{};
|
||||
const auto check = [&](auto gravity, auto correction) {
|
||||
const auto report = evaluate(context, nonlinear::NewtonNumerics{
|
||||
nonlinear::SampledEnthalpy{}, gravity, correction});
|
||||
CHECK_FALSE(report.converged());
|
||||
@@ -329,18 +352,36 @@ TEST_CASE("Coupled trial selection keeps the outer linear report and rejected st
|
||||
CHECK(outer.control.absoluteTolerance == 1.e100);
|
||||
CHECK(report.diagnostics().numericalStrategies.lastLinearReportSpace == nonlinear::LinearReportSpace::full_system);
|
||||
const auto &auxiliary = report.diagnostics().numericalStrategies.coupledTrial;
|
||||
REQUIRE(auxiliary.currentSolve.has_value());
|
||||
CHECK(auxiliary.attempts == 1);
|
||||
CHECK(auxiliary.kept == 0);
|
||||
CHECK(auxiliary.fallbacks == 1);
|
||||
CHECK(auxiliary.currentSolve->linearSolve.control.relativeTolerance == correction.correction.control.relativeTolerance);
|
||||
CHECK(auxiliary.currentSolve->linearSolve.control.absoluteTolerance == correction.correction.control.absoluteTolerance);
|
||||
if constexpr (std::same_as<decltype(correction), nonlinear::CoupledCurvatureCorrection>) {
|
||||
REQUIRE(auxiliary.currentSolve.has_value());
|
||||
CHECK(auxiliary.attempts == 1);
|
||||
CHECK(auxiliary.fallbacks == 1);
|
||||
CHECK(auxiliary.currentSolve->linearSolve.control.relativeTolerance == correction.correction.control.relativeTolerance);
|
||||
CHECK(auxiliary.currentSolve->linearSolve.control.absoluteTolerance == correction.correction.control.absoluteTolerance);
|
||||
} else {
|
||||
// The captured zero outer correction predicts no decrease. The
|
||||
// optional selector must leave the auxiliary budget untouched.
|
||||
CHECK(auxiliary.status == solver::CoupledTrialAttemptStatus::prediction_deferred);
|
||||
CHECK(auxiliary.deferredAttempts == 1);
|
||||
CHECK(auxiliary.attempts == 0);
|
||||
CHECK_FALSE(auxiliary.currentSolve.has_value());
|
||||
CHECK(auxiliary.candidateCount == 0);
|
||||
CHECK(auxiliary.candidates.empty());
|
||||
CHECK(std::isnan(auxiliary.selectedBeta));
|
||||
}
|
||||
CHECK(report.lastAcceptedCheckpointView().valid());
|
||||
};
|
||||
check(nonlinear::MonolithicGravity{});
|
||||
check(nonlinear::MonolithicGravity{}, nonlinear::CoupledCurvatureCorrection{});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
check(nonlinear::GravityCurvatureCorrection{permissiveGravity()});
|
||||
check(nonlinear::GravityCurvatureCorrection{permissiveGravity()}, nonlinear::CoupledCurvatureCorrection{});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
check(nonlinear::MonolithicGravity{}, nonlinear::BacktrackedCoupledCurvatureCorrection{});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
check(nonlinear::GravityCurvatureCorrection{permissiveGravity()}, nonlinear::BacktrackedCoupledCurvatureCorrection{});
|
||||
REQUIRE(context.isReady());
|
||||
checkPreserved(original, snapshot(context));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user