Snapshot optimized solver and audit diagnostics before numerical experiments
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -12,6 +13,27 @@ using Catch::Matchers::WithinAbs;
|
||||
namespace prepared_test = gravity_prepared_test_utils;
|
||||
|
||||
namespace {
|
||||
// Deliberately not a KelvinCompactification dynamic type: the prepared
|
||||
// operator must keep arbitrary exterior maps on the general derivative.
|
||||
class DelegatingExteriorMap final : public mapping::compactification::ExteriorDomainMap {
|
||||
public:
|
||||
explicit DelegatingExteriorMap(mapping::compactification::options::KelvinCompactificationOptions options)
|
||||
: kelvin(options) {}
|
||||
mapping::MappingStatus Evaluate(const mapping::compactification::ExteriorMapInput &input,
|
||||
mapping::compactification::ExteriorMapResult &result) const override {
|
||||
return kelvin.Evaluate(input, result);
|
||||
}
|
||||
mapping::MappingStatus EvaluateVariation(const mapping::compactification::ExteriorMapInput &input,
|
||||
const mapping::compactification::ExteriorMapResult &result,
|
||||
const mapping::compactification::ExteriorMapDirection &direction,
|
||||
mapping::compactification::ExteriorMapVariation &variation) const override {
|
||||
return kelvin.EvaluateVariation(input, result, direction, variation);
|
||||
}
|
||||
std::string_view GetName() const noexcept override { return "DelegatingExteriorMap"; }
|
||||
private:
|
||||
mapping::compactification::KelvinCompactification kelvin;
|
||||
};
|
||||
|
||||
[[nodiscard]] mfem::Vector make_folding_displacement(const mean_field::fem::FEM &f) {
|
||||
mfem::ParGridFunction field(f.displacementFes.get());
|
||||
mfem::VectorFunctionCoefficient coefficient(
|
||||
@@ -65,9 +87,15 @@ TEST_CASE(
|
||||
const mfem::Vector displacementTrue = prepared_test::make_displacement(f, scale);
|
||||
const mfem::Vector displacement = preparedOperator.GetDisplacementMap().gather(displacementTrue);
|
||||
preparedOperator.Prepare(displacement);
|
||||
CHECK(preparedOperator.GetFastVariationElementCount() == f.mesh->GetNE());
|
||||
CHECK(preparedOperator.GetTensorVariationElementCount() == f.mesh->GetNE());
|
||||
preparedOperator.MultDisplacementVariationTrue(first, direction, firstAction);
|
||||
|
||||
mfem::Vector referenceAction;
|
||||
preparedOperator.MultDisplacementVariationTrueCachedReference(first, direction, referenceAction);
|
||||
CHECK(prepared_test::relative_error(firstAction, referenceAction, communicator) < 2.0e-11);
|
||||
preparedOperator.MultDisplacementVariationTrueReference(first, direction, referenceAction);
|
||||
CHECK(prepared_test::relative_error(firstAction, referenceAction, communicator) < 2.0e-11);
|
||||
operators::kernels::apply_mapped_hdiv_mass_variation(
|
||||
f, *f.domainMapperStateless, first, displacementTrue, direction, referenceAction
|
||||
);
|
||||
@@ -85,6 +113,39 @@ TEST_CASE(
|
||||
CHECK(preparedOperator.GetPreparationCount() == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("Prepared Hdiv Tangent Retains General Exterior Map Fallback",
|
||||
tags::gravity_prepared_jacobian_accuracy) {
|
||||
auto args = test_utils::setup_args();
|
||||
auto f = fem::setup_fem(args.mesh_file, args, 0);
|
||||
REQUIRE(f.okay());
|
||||
mapping::DomainMapper mapper(args.domain_mapper_options, std::make_unique<DelegatingExteriorMap>(args.kelvin_options));
|
||||
operators::PreparedMappedHDivMassOperator prepared(f, mapper);
|
||||
const auto base = prepared_test::make_displacement(f, 0.7);
|
||||
const auto direction = prepared_test::make_displacement(f, 0.43);
|
||||
const auto flux = prepared_test::make_deterministic_vector(f.gravityFluxFes->GetTrueVSize(), 0.31);
|
||||
prepared.Prepare(prepared.GetDisplacementMap().gather(base));
|
||||
int stellarElements = 0;
|
||||
for (int element = 0; element < f.mesh->GetNE(); ++element)
|
||||
stellarElements += !mapper.IsCompactifiedElement(*f.mesh->GetElementTransformation(element));
|
||||
CHECK(prepared.GetFastVariationElementCount() == stellarElements);
|
||||
mfem::Vector actual, expected;
|
||||
prepared.MultDisplacementVariationTrue(flux, direction, actual);
|
||||
operators::kernels::apply_mapped_hdiv_mass_variation(f, mapper, flux, base, direction, expected);
|
||||
CHECK(prepared_test::relative_error(actual, expected, f.mesh->GetComm()) < 2.0e-11);
|
||||
prepared.PreparePrimal(prepared.GetDisplacementMap().gather(base));
|
||||
CHECK_FALSE(prepared.HasVariationData());
|
||||
CHECK(prepared.GetFastVariationElementCount() == 0);
|
||||
CHECK(prepared.GetFastMassElementCount() == f.mesh->GetNE());
|
||||
mfem::Vector primal, primalReference;
|
||||
const auto reducedFlux = prepared.GetFluxMap().gather(flux);
|
||||
prepared.Mult(reducedFlux, primal);
|
||||
prepared.MultReference(reducedFlux, primalReference);
|
||||
CHECK(prepared_test::relative_error(primal, primalReference, f.mesh->GetComm()) < 2.0e-11);
|
||||
prepared.Prepare(prepared.GetDisplacementMap().gather(base));
|
||||
prepared.MultDisplacementVariationTrue(flux, direction, actual);
|
||||
CHECK(prepared_test::relative_error(actual, expected, f.mesh->GetComm()) < 2.0e-11);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Prepared Mapped Hdiv Mass Reports Invalid Candidate Geometry Without Unwinding",
|
||||
tags::gravity_prepared_unit &tags::geometry
|
||||
@@ -144,6 +205,13 @@ TEST_CASE(
|
||||
mfem::Vector prepared_action;
|
||||
|
||||
prepared_operator.Mult(gravity_gradient, prepared_action);
|
||||
CHECK(prepared_operator.GetFastMassElementCount() == f.mesh->GetNE());
|
||||
mfem::Vector mfemAction;
|
||||
prepared_operator.MultReference(gravity_gradient, mfemAction);
|
||||
CHECK(prepared_test::relative_error(prepared_action, mfemAction, communicator) < 2.0e-11);
|
||||
// Reference calls must restore the optimized mode and leave PA data intact.
|
||||
prepared_operator.Mult(gravity_gradient, mfemAction);
|
||||
CHECK(prepared_test::relative_error(prepared_action, mfemAction, communicator) < 2.0e-14);
|
||||
mfem::Vector reference_action_true;
|
||||
operators::kernels::apply_mapped_hdiv_mass(
|
||||
f, *f.domainMapperStateless, gravity_gradient_true, displacement_true, reference_action_true
|
||||
|
||||
Reference in New Issue
Block a user