Snapshot optimized solver and audit diagnostics before numerical experiments
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user