Compare compact gravity applications against full FEM blocks

This commit is contained in:
2026-09-17 10:19:17 -04:00
parent 3307191f2d
commit f77c7d2b29
3 changed files with 40 additions and 1 deletions

View File

@@ -110,6 +110,34 @@ namespace stellar_numerical_strategy_test {
CHECK(relativeDifference(before.residual, after.residual) < 1.e-13);
}
template <typename Context>
void checkGravityApplications(Context &context) {
solver::detail::StellarEquilibriumContextDiagnostics::WithState(context, [&](auto &state, const auto &) {
using Form = typename std::remove_cvref_t<decltype(state.Problem())>::FormType;
const auto partition = solver::MakeGravityBlockPartition<Form>(state.Problem().GetManifest().layout());
solver::PreparedGravitySubsystem compact(*state.normalizedOperator, *state.normalizedInverse,
partition, state.Problem().GetCommunicator());
solver::PreparedGravitySubsystem reference(*state.normalizedOperator, *state.normalizedInverse,
partition, state.Problem().GetCommunicator(), solver::linear::FGMRES{},
solver::RootRestrictedGravityApplications{});
REQUIRE(compact.UsesCompactOperator());
REQUIRE(compact.UsesCompactPreconditioner());
mfem::Vector direction(partition.GravityValueSize()), actual(direction.Size()), expected(direction.Size());
// Dense directions expose ordering/scaling mistakes which a few
// isolated basis vectors may miss in a distributed field block.
for (int trial = 0; trial < 3; ++trial) {
for (int i = 0; i < direction.Size(); ++i)
direction(i) = std::sin(.37*(i+1)*(trial+1)) + .4*std::cos(.11*(i+1)*(trial+2));
compact.GetOperator().Mult(direction, actual);
reference.GetOperator().Mult(direction, expected);
CHECK(relativeDifference(expected, actual) < 2.e-12);
compact.GetPreconditioner().Mult(direction, actual);
reference.GetPreconditioner().Mult(direction, expected);
CHECK(relativeDifference(expected, actual) < 2.e-12);
}
});
}
[[nodiscard]] nonlinear::NewtonOptions oneAttempt() {
// A relative threshold of exactly ||b|| need not stop MFEM before
// its first iteration. Use a separated absolute threshold so this
@@ -151,6 +179,8 @@ TEST_CASE("Production gravity strategies retain optional model borders and resto
CAPTURE(CentralConstraint);
auto context = makeContext<CentralConstraint>();
const auto original = snapshot(context);
checkGravityApplications(context);
checkPreserved(original, snapshot(context));
REQUIRE(original.gravitySize > 0);
REQUIRE(original.retainedSize > 0);
// The fixed mass and angular momentum are always retained. Central