Snapshot optimized solver and audit diagnostics before numerical experiments

This commit is contained in:
2026-09-16 14:34:06 -04:00
parent 75cc638739
commit 80cc3d83d7
64 changed files with 11969 additions and 267 deletions

View File

@@ -143,11 +143,12 @@ namespace mean_field::solver::detail {
};
std::array<double, 9> minimumRealValues{};
std::array<double, 9> maximumRealValues{};
const std::array<int, 3> localIntegerValues{
options.maximumIterations, options.linearSolve.maximumIterations, options.backtracking.maximumTrials
const std::array<int, 4> localIntegerValues{
options.maximumIterations, options.linearSolve.maximumIterations, options.backtracking.maximumTrials,
static_cast<int>(options.backtracking.geometryPreflight)
};
std::array<int, 3> minimumIntegerValues{};
std::array<int, 3> maximumIntegerValues{};
std::array<int, 4> minimumIntegerValues{};
std::array<int, 4> maximumIntegerValues{};
if (MPI_Allreduce(
localRealValues.data(), minimumRealValues.data(), static_cast<int>(localRealValues.size()), MPI_DOUBLE,
@@ -341,7 +342,6 @@ export namespace mean_field::solver {
ValidateInitialState();
InitializeWorkspaces();
PrepareInitialOperator();
InitializeGeometryPreflightRules();
physicalInverse = std::unique_ptr<PhysicalInverseType>{new PhysicalInverseType(
PreparePhysicalInverse(std::move(preconditionerPrescription), RequireProblem(storage))
@@ -485,6 +485,10 @@ export namespace mean_field::solver {
const double maximumStepSize,
const double fractionToBoundarySafety
) {
if (!geometryPreflightRulesInitialized) {
InitializeGeometryPreflightRules();
geometryPreflightRulesInitialized = true;
}
normalizedOperator->DenormalizeState(normalizedCorrection, physicalCorrection);
const auto &physicalOperator = Problem().GetPhysicalOperator();
Problem().BuildVolumeDisplacementDirection(physicalCorrection, volumeDisplacementDirection);
@@ -513,6 +517,7 @@ export namespace mean_field::solver {
mfem::Vector volumeDisplacementDirection;
mfem::Vector candidatePhysicalState;
std::vector<deformation::NewtonStepGeometryRule> geometryPreflightRules;
bool geometryPreflightRulesInitialized{false};
double acceptedMinimumJacobianDeterminant{std::numeric_limits<double>::quiet_NaN()};
std::unique_ptr<NormalizedOperatorType> normalizedOperator;
std::unique_ptr<PhysicalInverseType> physicalInverse;
@@ -1271,31 +1276,33 @@ export namespace mean_field::solver {
}
const nonlinear::MetricEvaluation previousMetric = acceptedMetric;
const Clock::time_point geometryPreflightStart = Clock::now();
timings.geometryPreflight = state.EstimateLargestSafeStepSize(
nextLineSearchStepLength, options.backtracking.fractionToBoundarySafety
);
timings.geometryPreflightSeconds =
std::chrono::duration<double>(Clock::now() - geometryPreflightStart).count();
diagnostics.totalGeometryPreflightSeconds += timings.geometryPreflightSeconds;
diagnostics.lastGeometryPreflight = timings.geometryPreflight;
if (timings.geometryPreflight->limitedByGeometry) {
++diagnostics.geometryLimitedIterations;
}
if (timings.geometryPreflight->stepSize < options.backtracking.minimumStepLength) {
diagnostics.finalResidualNorm = acceptedMetric.residualNorm;
NotifyAfter(
iteration, nonlinear::IterationDisposition::globalization_failure, false, 0.0, 0,
diagnostics.initialResidualNorm, previousMetric, acceptedMetric, linearReport, timings, state
if (options.backtracking.geometryPreflight) {
const Clock::time_point geometryPreflightStart = Clock::now();
timings.geometryPreflight = state.EstimateLargestSafeStepSize(
nextLineSearchStepLength, options.backtracking.fractionToBoundarySafety
);
return Failure(
state, std::move(diagnostics), StellarEquilibriumFailureReason::globalization_failure,
"The geometry preflight found no orientation-preserving Newton step at or above the "
"configured minimum step length."
);
}
timings.geometryPreflightSeconds =
std::chrono::duration<double>(Clock::now() - geometryPreflightStart).count();
diagnostics.totalGeometryPreflightSeconds += timings.geometryPreflightSeconds;
diagnostics.lastGeometryPreflight = timings.geometryPreflight;
if (timings.geometryPreflight->limitedByGeometry) {
++diagnostics.geometryLimitedIterations;
}
if (timings.geometryPreflight->stepSize < options.backtracking.minimumStepLength) {
diagnostics.finalResidualNorm = acceptedMetric.residualNorm;
NotifyAfter(
iteration, nonlinear::IterationDisposition::globalization_failure, false, 0.0, 0,
diagnostics.initialResidualNorm, previousMetric, acceptedMetric, linearReport, timings, state
);
return Failure(
state, std::move(diagnostics), StellarEquilibriumFailureReason::globalization_failure,
"The geometry preflight found no orientation-preserving Newton step at or above the "
"configured minimum step length."
);
}
}
bool accepted = false;
double acceptedStepLength = 0.0;
int lineSearchTrials = 0;
@@ -1303,7 +1310,8 @@ export namespace mean_field::solver {
StellarEquilibriumFailureReason rejectionReason =
StellarEquilibriumFailureReason::globalization_failure;
std::string rejectionMessage = "The backtracking line search found no acceptable Newton step.";
double stepLength = timings.geometryPreflight->stepSize;
double stepLength = timings.geometryPreflight ?
timings.geometryPreflight->stepSize : nextLineSearchStepLength;
const Clock::time_point lineSearchStart = Clock::now();
try {