perf(allocations): reduced overall allocations by 95%, increaseed jacobian applicatin by 2x
This commit uses global pre allocated work space to dramatically reduce memory usage and allocation time
This commit is contained in:
@@ -76,17 +76,20 @@ namespace stellar_solver_architecture_test {
|
||||
std::shared_ptr<LifetimeProbe> probe;
|
||||
double correctionValue{0.0};
|
||||
bool resizeCorrection{false};
|
||||
bool surfaceCorrectionOnly{false};
|
||||
|
||||
ScriptedBackend() = default;
|
||||
|
||||
explicit ScriptedBackend(
|
||||
std::shared_ptr<LifetimeProbe> lifetimeProbe,
|
||||
const double scriptedCorrectionValue = 0.0,
|
||||
const bool resizeScriptedCorrection = false
|
||||
const double scriptedCorrectionValue = 0.0,
|
||||
const bool resizeScriptedCorrection = false,
|
||||
const bool scriptOnlySurfaceCorrection = false
|
||||
)
|
||||
: probe(std::move(lifetimeProbe)),
|
||||
correctionValue(scriptedCorrectionValue),
|
||||
resizeCorrection(resizeScriptedCorrection) {
|
||||
resizeCorrection(resizeScriptedCorrection),
|
||||
surfaceCorrectionOnly(scriptOnlySurfaceCorrection) {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,14 +101,16 @@ namespace stellar_solver_architecture_test {
|
||||
const MPI_Comm communicator,
|
||||
std::shared_ptr<LifetimeProbe> probe,
|
||||
const double correctionValue,
|
||||
const bool resizeCorrection
|
||||
const bool resizeCorrection,
|
||||
const bool surfaceCorrectionOnly
|
||||
)
|
||||
: m_operation(std::addressof(operation)),
|
||||
m_preconditioner(std::addressof(preconditioner)),
|
||||
m_communicator(communicator),
|
||||
m_probe(std::move(probe)),
|
||||
m_correctionValue(correctionValue),
|
||||
m_resizeCorrection(resizeCorrection) {
|
||||
m_resizeCorrection(resizeCorrection),
|
||||
m_surfaceCorrectionOnly(surfaceCorrectionOnly) {
|
||||
if (m_probe != nullptr) {
|
||||
m_probe->problemIdentity = std::addressof(operation.GetProblem());
|
||||
}
|
||||
@@ -181,7 +186,17 @@ namespace stellar_solver_architecture_test {
|
||||
m_probe->incomingCorrectionNorms.push_back(GlobalNorm(correction));
|
||||
}
|
||||
|
||||
correction = m_correctionValue;
|
||||
if (m_surfaceCorrectionOnly) {
|
||||
mfem::Vector physicalCorrection(CorrectionSize());
|
||||
physicalCorrection = 0.0;
|
||||
auto physicalDirection = m_operation->GetProblem().GetManifest().stateView(physicalCorrection);
|
||||
mfem::Vector surfaceDirection =
|
||||
physicalDirection.block(mean_field::utils::blocks::surface_deformation_field.parameters_term);
|
||||
surfaceDirection = m_correctionValue;
|
||||
m_operation->NormalizeState(physicalCorrection, correction);
|
||||
} else {
|
||||
correction = m_correctionValue;
|
||||
}
|
||||
if (m_probe != nullptr) {
|
||||
m_probe->returnedCorrectionNorms.push_back(GlobalNorm(correction));
|
||||
}
|
||||
@@ -226,6 +241,7 @@ namespace stellar_solver_architecture_test {
|
||||
std::shared_ptr<LifetimeProbe> m_probe;
|
||||
double m_correctionValue;
|
||||
bool m_resizeCorrection;
|
||||
bool m_surfaceCorrectionOnly;
|
||||
};
|
||||
|
||||
template <
|
||||
@@ -243,7 +259,8 @@ namespace stellar_solver_architecture_test {
|
||||
communicator,
|
||||
std::move(configuration.probe),
|
||||
configuration.correctionValue,
|
||||
configuration.resizeCorrection
|
||||
configuration.resizeCorrection,
|
||||
configuration.surfaceCorrectionOnly
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1013,11 +1030,14 @@ TEST_CASE(
|
||||
event.normalizedState.begin(), event.normalizedState.end()
|
||||
);
|
||||
CHECK(event.iterationSeconds >= 0.0);
|
||||
CHECK(event.geometryPreflightSeconds >= 0.0);
|
||||
CHECK(event.lineSearchSeconds >= 0.0);
|
||||
CHECK(event.trialPreparationSeconds >= 0.0);
|
||||
CHECK(event.metricEvaluationSeconds >= 0.0);
|
||||
CHECK(event.preconditionerRefreshSeconds >= 0.0);
|
||||
CHECK(event.rollbackSeconds >= 0.0);
|
||||
REQUIRE(event.geometryPreflight.has_value());
|
||||
CHECK(event.geometryPreflight->sampledQuadraturePointCount > 0);
|
||||
}
|
||||
);
|
||||
auto newton = solver::nonlinear::Newton(
|
||||
@@ -1050,11 +1070,14 @@ TEST_CASE(
|
||||
CHECK(report.diagnostics().nonFiniteLineSearchTrials == 0);
|
||||
CHECK(report.diagnostics().insufficientDecreaseTrials == 2);
|
||||
CHECK(report.diagnostics().totalLinearSolveSeconds >= 0.0);
|
||||
CHECK(report.diagnostics().totalGeometryPreflightSeconds >= 0.0);
|
||||
CHECK(report.diagnostics().totalLineSearchSeconds >= 0.0);
|
||||
CHECK(report.diagnostics().totalTrialPreparationSeconds >= 0.0);
|
||||
CHECK(report.diagnostics().totalMetricEvaluationSeconds >= 0.0);
|
||||
CHECK(report.diagnostics().totalPreconditionerRefreshSeconds >= 0.0);
|
||||
CHECK(report.diagnostics().totalRollbackSeconds >= 0.0);
|
||||
REQUIRE(report.diagnostics().lastGeometryPreflight.has_value());
|
||||
CHECK(report.diagnostics().lastGeometryPreflight->sampledQuadraturePointCount > 0);
|
||||
CHECK(metricState->next == metricState->evaluations.size());
|
||||
REQUIRE(observerRecord->beforeCalls == 2);
|
||||
REQUIRE(observerRecord->afterCalls == 2);
|
||||
@@ -1105,6 +1128,82 @@ TEST_CASE(
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Newton Geometry Preflight Caps A Surface Step Before Trial Preparation",
|
||||
"[solver][newton][geometry][preflight][backtracking][wiring]"
|
||||
) {
|
||||
using namespace mean_field;
|
||||
using namespace stellar_solver_architecture_test;
|
||||
using Catch::Approx;
|
||||
|
||||
auto finiteElements = makeFiniteElements();
|
||||
REQUIRE(finiteElements.okay());
|
||||
auto discretization = equilibrium::makeStellarDiscretization(
|
||||
std::move(finiteElements),
|
||||
normalization::PhysicalRieszDiagonal{dimensions::LengthValue{utils::RADIUS}, utils::G}
|
||||
);
|
||||
auto context = solver::makeContext(
|
||||
makeModel(), std::move(discretization), preconditioning::makePreconditioner(),
|
||||
ScriptedBackend{nullptr, -10.0, false, true}
|
||||
);
|
||||
|
||||
auto metricState = std::make_shared<MetricSequenceState>();
|
||||
metricState->evaluations = {{.residualNorm = 2.0, .merit = 2.0}, {.residualNorm = 1.0, .merit = 0.5}};
|
||||
std::optional<deformation::LargestSafeNewtonStepSizeEstimate> observedPreflight;
|
||||
auto observer = solver::nonlinear::makeObserver(
|
||||
[](const solver::nonlinear::BeforeIteration &) { },
|
||||
[&observedPreflight](const solver::nonlinear::AfterIteration &event) {
|
||||
observedPreflight = event.geometryPreflight;
|
||||
CHECK(event.geometryPreflightSeconds >= 0.0);
|
||||
CHECK(event.stepAccepted);
|
||||
CHECK(event.lineSearchTrials == 1);
|
||||
}
|
||||
);
|
||||
auto newton = solver::nonlinear::Newton(
|
||||
solver::nonlinear::NewtonOptions{
|
||||
.relativeTolerance = 0.0,
|
||||
.absoluteTolerance = 0.0,
|
||||
.maximumIterations = 1,
|
||||
.linearSolve =
|
||||
{.relativeTolerance = 0.0,
|
||||
.absoluteTolerance = std::numeric_limits<double>::max(),
|
||||
.maximumIterations = 1},
|
||||
.backtracking =
|
||||
{.initialStepLength = 1.0,
|
||||
.contractionFactor = 0.5,
|
||||
.fractionToBoundarySafety = 0.5,
|
||||
.sufficientDecrease = 1.0e-4,
|
||||
.minimumStepLength = 1.0e-8,
|
||||
.maximumTrials = 1}
|
||||
},
|
||||
SequencedMetric{metricState}
|
||||
);
|
||||
|
||||
auto equilibriumSolver = solver::make(context, std::move(newton), std::move(observer));
|
||||
const auto report = equilibriumSolver.evaluate();
|
||||
|
||||
REQUIRE_FALSE(report.converged());
|
||||
CHECK(report.failure().reason == solver::StellarEquilibriumFailureReason::iteration_limit);
|
||||
CHECK(report.diagnostics().attemptedNonlinearIterations == 1);
|
||||
CHECK(report.diagnostics().acceptedNonlinearIterations == 1);
|
||||
CHECK(report.diagnostics().totalLineSearchTrials == 1);
|
||||
CHECK(report.diagnostics().inadmissibleLineSearchTrials == 0);
|
||||
CHECK(report.diagnostics().geometryLimitedIterations == 1);
|
||||
REQUIRE(report.diagnostics().lastGeometryPreflight.has_value());
|
||||
const auto &preflight = *report.diagnostics().lastGeometryPreflight;
|
||||
CHECK(preflight.limitedByGeometry);
|
||||
CHECK(preflight.sampledQuadraturePointCount > 0);
|
||||
CHECK(preflight.minimumDeterminantAtAcceptedState > 0.0);
|
||||
CHECK(preflight.minimumDeterminantAtMaximumStepSize <= 0.0);
|
||||
CHECK(preflight.stepSize > 0.0);
|
||||
CHECK(preflight.stepSize < 1.0);
|
||||
CHECK(preflight.stepSize == Approx(0.5 * preflight.boundaryStepSize));
|
||||
CHECK(report.diagnostics().lastAcceptedStepLength == Approx(preflight.stepSize));
|
||||
REQUIRE(observedPreflight.has_value());
|
||||
CHECK(observedPreflight->stepSize == Approx(preflight.stepSize));
|
||||
CHECK(report.lastAcceptedCheckpointView().valid());
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"An Accepted Final Newton Step Reports The Iteration Limit To Its Observer",
|
||||
"[solver][newton][iteration-limit][observer][checkpoint]"
|
||||
|
||||
Reference in New Issue
Block a user