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

@@ -2,6 +2,7 @@
#include <array>
#include <cmath>
#include <limits>
#include <stdexcept>
#include <type_traits>
#include <catch2/catch_approx.hpp>
@@ -313,6 +314,8 @@ TEST_CASE(
preconditioning::GravityApproximateLDU{}
);
auto chebyshevPrepared = preconditioning::prepare(geometry.finiteElements, geometry.context, chebyshevBlock);
CHECK(prepared.GetDivergenceAssemblyCount() == 1);
CHECK(chebyshevPrepared.GetDivergenceAssemblyCount() == 1);
const auto unchanged = prepared.Refresh(geometry.finiteElements, geometry.context);
const auto unchangedChebyshev = chebyshevPrepared.Refresh(geometry.finiteElements, geometry.context);
@@ -338,6 +341,8 @@ TEST_CASE(
const std::uint64_t sourcePreparations = geometry.context.GetSourceOperator().GetPreparationCount();
const auto changed = prepared.Refresh(geometry.finiteElements, geometry.context);
const auto changedChebyshev = chebyshevPrepared.Refresh(geometry.finiteElements, geometry.context);
CHECK(prepared.GetDivergenceAssemblyCount() == 1);
CHECK(chebyshevPrepared.GetDivergenceAssemblyCount() == 1);
CHECK(changed.geometryChanged);
CHECK_FALSE(changed.discretizationChanged);
@@ -377,6 +382,7 @@ TEST_CASE(
CHECK(reconstructed.rebuiltPotentialSchur);
CHECK(chebyshevPrepared.IsCurrent());
CHECK(chebyshevPrepared.GetMassInverse().GetStatistics().setups == 3);
CHECK(chebyshevPrepared.GetDivergenceAssemblyCount() == 2);
mfem::Vector firstReconstructedAction(chebyshevPrepared.Height());
mfem::Vector secondReconstructedAction(chebyshevPrepared.Height());
@@ -391,3 +397,52 @@ TEST_CASE(
CHECK(std::isfinite(firstReconstructedAction(index)));
}
}
TEST_CASE(
"Fixed Gravity Divergence Cache Preserves Changing Mass Weights And Invalidates",
tags::preconditioning_gravity_integration
) {
const auto args = test_utils::setup_args();
auto f = mean_field::fem::setup_fem(args.mesh_file, args, 0);
REQUIRE(f.okay());
preconditioning::PreparedGravityDivergenceCache cache;
mfem::Vector diagonal(f.gravityFluxFes->GetTrueVSize()); diagonal = 1.0;
const auto x = gravity_prepared_test_utils::make_deterministic_vector(f.gravityPotentialFes->GetTrueVSize(), 0.37);
auto initial = preconditioning::assembleGravityPotentialSchurSurrogate(f, diagonal, &cache);
mfem::Vector initialAction(initial->Height()); initial->Mult(x, initialAction);
REQUIRE(initialAction.Norml2() > 0.0);
REQUIRE(cache.GetBuildCount() == 1);
for (double scale : {2.0, 0.5, 1.0}) {
CAPTURE(scale);
diagonal = scale;
auto fast = preconditioning::assembleGravityPotentialSchurSurrogate(f, diagonal, &cache);
auto reference = preconditioning::assembleGravityPotentialSchurSurrogate(f, diagonal);
mfem::Vector a(fast->Height()), b(reference->Height()), expected(initialAction);
fast->Mult(x, a); reference->Mult(x, b); expected /= scale;
CHECK(gravity_prepared_test_utils::relative_error(a, b, f.mesh->GetComm()) < 2.0e-12);
CHECK(gravity_prepared_test_utils::relative_error(a, expected, f.mesh->GetComm()) < 2.0e-12);
CHECK(cache.GetBuildCount() == 1);
initial->Mult(x, a);
CHECK(gravity_prepared_test_utils::relative_error(a, initialAction, f.mesh->GetComm()) < 2.0e-14);
}
for (double bad : {0.0, -1.0, std::numeric_limits<double>::quiet_NaN()}) {
diagonal = bad;
CHECK_THROWS_AS(
preconditioning::assembleGravityPotentialSchurSurrogate(f, diagonal, &cache), std::invalid_argument);
CHECK(cache.GetBuildCount() == 1);
}
diagonal = 1.0;
const auto checkRebuild = [&] {
auto fast = preconditioning::assembleGravityPotentialSchurSurrogate(f, diagonal, &cache);
auto reference = preconditioning::assembleGravityPotentialSchurSurrogate(f, diagonal);
mfem::Vector a(fast->Height()), b(reference->Height());
fast->Mult(x, a); reference->Mult(x, b);
CHECK(gravity_prepared_test_utils::relative_error(a, b, f.mesh->GetComm()) < 2.0e-12);
};
cache.Clear(); checkRebuild();
CHECK(cache.GetBuildCount() == 2);
f.mesh->NodesUpdated(); checkRebuild();
CHECK(cache.GetBuildCount() == 3);
checkRebuild();
CHECK(cache.GetBuildCount() == 3);
}