Snapshot optimized solver and audit diagnostics before numerical experiments
This commit is contained in:
@@ -601,6 +601,15 @@ TEST_CASE(
|
||||
CHECK(preparedOperator.IsPrepared());
|
||||
CHECK(preparedOperator.GetResidualPreparationCount() == 2);
|
||||
CHECK(preparedOperator.GetResidualApplicationCount() == 1);
|
||||
mfem::Vector updatedResidual, referenceResidual;
|
||||
preparedOperator.BuildResidual(updatedResidual);
|
||||
CHECK(preparedOperator.PrepareReference().DidAnyWork());
|
||||
preparedOperator.BuildResidual(referenceResidual);
|
||||
CHECK(gravity_displacement_force_test_utils::relative_difference(
|
||||
updatedResidual, referenceResidual, f.mesh->GetComm()) < 2.0e-12);
|
||||
CHECK_FALSE(preparedOperator.PrepareReference().DidAnyWork());
|
||||
CHECK(preparedOperator.Prepare().DidAnyWork());
|
||||
CHECK_FALSE(preparedOperator.Prepare().DidAnyWork());
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
@@ -665,6 +674,19 @@ TEST_CASE(
|
||||
densityDirectionReduced, displacementDirectionReduced, gravityGradientDirectionReduced, completeAction
|
||||
);
|
||||
|
||||
mfem::Vector retainedAction;
|
||||
preparedOperator.ApplyCompleteJacobianActionReference(
|
||||
densityDirectionReduced, displacementDirectionReduced, gravityGradientDirectionReduced, retainedAction);
|
||||
CHECK(preparedOperator.GetFastElementCount() > 0);
|
||||
CHECK(preparedOperator.GetTensorElementCount() == preparedOperator.GetFastElementCount());
|
||||
CHECK(gravity_displacement_force_test_utils::relative_difference(
|
||||
completeAction, retainedAction, f.mesh->GetComm()) < 2.0e-12);
|
||||
|
||||
preparedOperator.ApplyCompleteJacobianActionCachedReference(
|
||||
densityDirectionReduced, displacementDirectionReduced, gravityGradientDirectionReduced, retainedAction);
|
||||
CHECK(gravity_displacement_force_test_utils::relative_difference(
|
||||
completeAction, retainedAction, f.mesh->GetComm()) < 2.0e-12);
|
||||
|
||||
mfem::Vector summedColumns(densityAction);
|
||||
summedColumns += gravityAction;
|
||||
summedColumns += displacementAction;
|
||||
|
||||
@@ -312,6 +312,10 @@ TEST_CASE(
|
||||
operation.ApplyCompleteJacobianAction(
|
||||
reducedDensityDirection, reducedDisplacementDirection, angularVelocityDirection, completeAction
|
||||
);
|
||||
mfem::Vector preparedReference;
|
||||
operation.ApplyCompleteJacobianActionReference(
|
||||
reducedDensityDirection, reducedDisplacementDirection, angularVelocityDirection, preparedReference);
|
||||
CHECK(angular_momentum_test_utils::relativeError(completeAction(0), preparedReference(0)) < 2.0e-11);
|
||||
CHECK(
|
||||
angular_momentum_test_utils::relativeError(
|
||||
completeAction(0), densityAction(0) + geometryAction(0) + angularVelocityAction(0)
|
||||
@@ -409,10 +413,26 @@ TEST_CASE(
|
||||
operation.Prepare(0.52, dependencies);
|
||||
const auto preparationCount = operation.GetPreparationCount();
|
||||
const double moment = operation.GetMomentOfInertia();
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == 0);
|
||||
const auto rhoDirection = gravityContext.GetDensityMap().gather(
|
||||
angular_momentum_test_utils::projectDensityDirection(finiteElements, 0.67));
|
||||
const auto uDirection = gravityContext.GetDisplacementMap().gather(
|
||||
angular_momentum_test_utils::projectDisplacementDirection(finiteElements, -0.53));
|
||||
auto checkRows = [&](std::uint64_t expectedBuilds) {
|
||||
REQUIRE(operation.PrepareJacobianRows());
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == expectedBuilds);
|
||||
mfem::Vector actual, reference;
|
||||
operation.ApplyCompleteJacobianAction(rhoDirection, uDirection, -0.19, actual);
|
||||
operation.ApplyCompleteJacobianActionReference(rhoDirection, uDirection, -0.19, reference);
|
||||
CHECK(angular_momentum_test_utils::relativeError(actual(0), reference(0)) < 2.0e-11);
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == expectedBuilds);
|
||||
};
|
||||
checkRows(1);
|
||||
|
||||
const auto repeated = operation.Prepare(0.52, dependencies);
|
||||
CHECK_FALSE(repeated.DidAnyWork());
|
||||
CHECK(operation.GetPreparationCount() == preparationCount);
|
||||
checkRows(1);
|
||||
|
||||
++gravityPotentialRevision;
|
||||
angular_momentum_test_utils::prepareGravityContext(
|
||||
@@ -420,6 +440,7 @@ TEST_CASE(
|
||||
);
|
||||
const auto unrelatedPotential = operation.Prepare(0.52, dependencies);
|
||||
CHECK_FALSE(unrelatedPotential.DidAnyWork());
|
||||
checkRows(1);
|
||||
|
||||
const double residualBeforeRotation = angular_momentum_test_utils::residual(operation);
|
||||
++dependencies.rotation.revision;
|
||||
@@ -429,6 +450,7 @@ TEST_CASE(
|
||||
CHECK_FALSE(rotationOnly.refreshedDensity);
|
||||
CHECK_FALSE(rotationOnly.refreshedGeometry);
|
||||
CHECK(operation.GetMomentOfInertia() == moment);
|
||||
checkRows(1);
|
||||
CHECK(
|
||||
angular_momentum_test_utils::residual(operation) - residualBeforeRotation ==
|
||||
Catch::Approx((0.81 - 0.52) * moment).epsilon(3.0e-15)
|
||||
@@ -443,6 +465,8 @@ TEST_CASE(
|
||||
CHECK(densityOnly.refreshedDensity);
|
||||
CHECK_FALSE(densityOnly.refreshedGeometry);
|
||||
CHECK_FALSE(densityOnly.updatedAngularVelocity);
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == 1);
|
||||
checkRows(2);
|
||||
|
||||
displacement = angular_momentum_test_utils::projectDisplacementDirection(finiteElements, 0.87);
|
||||
++dependencies.displacement.revision;
|
||||
@@ -453,6 +477,8 @@ TEST_CASE(
|
||||
CHECK(geometryOnly.refreshedGeometry);
|
||||
CHECK_FALSE(geometryOnly.refreshedDensity);
|
||||
CHECK_FALSE(geometryOnly.updatedAngularVelocity);
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == 2);
|
||||
checkRows(3);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
@@ -488,6 +514,8 @@ TEST_CASE(
|
||||
const auto initial = operation.TryPrepare(angularVelocity, dependencies);
|
||||
REQUIRE(initial.has_value());
|
||||
const std::uint64_t initialPreparationCount = operation.GetPreparationCount();
|
||||
REQUIRE(operation.PrepareJacobianRows());
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == 1);
|
||||
|
||||
const std::uint64_t successfulPreparations = initialPreparationCount;
|
||||
|
||||
@@ -513,6 +541,8 @@ TEST_CASE(
|
||||
const auto recovered = operation.TryPrepare(angularVelocity, dependencies);
|
||||
REQUIRE(recovered.has_value());
|
||||
CHECK(operation.IsPrepared());
|
||||
REQUIRE(operation.PrepareJacobianRows());
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == 2);
|
||||
|
||||
++dependencies.rotation.revision;
|
||||
const auto nonFiniteAngularVelocity = operation.TryPrepare(std::numeric_limits<double>::quiet_NaN(), dependencies);
|
||||
@@ -527,4 +557,6 @@ TEST_CASE(
|
||||
++dependencies.rotation.revision;
|
||||
REQUIRE(operation.TryPrepare(angularVelocity, dependencies).has_value());
|
||||
CHECK(operation.IsPrepared());
|
||||
REQUIRE(operation.PrepareJacobianRows());
|
||||
CHECK(operation.GetJacobianRowPreparationCount() == 3);
|
||||
}
|
||||
|
||||
@@ -526,6 +526,18 @@ namespace prepared_barotropic_closure_test_utils {
|
||||
|
||||
const MPI_Comm communicator = f.mesh->GetComm();
|
||||
|
||||
mfem::Vector retained, enthalpyOnly, displacementOnly;
|
||||
preparedOperator.MultReference(densityVariation, enthalpyVariation, displacementVariation, retained);
|
||||
preparedOperator.ApplyEnthalpyJacobianAction(enthalpyVariation, enthalpyOnly);
|
||||
preparedOperator.ApplyDisplacementJacobianAction(displacementVariation, displacementOnly);
|
||||
CHECK(relative_error(preparedCompleteAction, retained, communicator) < 2.0e-12);
|
||||
CHECK(relative_error(enthalpyOnly, referenceEnthalpyAction, communicator) < 2.0e-12);
|
||||
CHECK(relative_error(displacementOnly, referenceDisplacementAction, communicator) < 2.0e-12);
|
||||
preparedOperator.ApplyEnthalpyJacobianAction(zeroEnthalpy, enthalpyOnly);
|
||||
preparedOperator.ApplyDisplacementJacobianAction(zeroDisplacement, displacementOnly);
|
||||
CHECK(enthalpyOnly.Norml2() == 0.0);
|
||||
CHECK(displacementOnly.Norml2() == 0.0);
|
||||
|
||||
CHECK(relative_error(preparedResidual, referenceResidual, communicator) < 2.0e-12);
|
||||
CHECK(relative_error(preparedDensityAction, referenceDensityAction, communicator) < 2.0e-12);
|
||||
CHECK(relative_error(preparedEnthalpyAction, referenceEnthalpyAction, communicator) < 2.0e-12);
|
||||
@@ -831,6 +843,16 @@ namespace prepared_barotropic_closure_test_utils {
|
||||
mfem::Vector preparedAction;
|
||||
preparedOperator.BuildResidual(preparedResidual);
|
||||
preparedOperator.Mult(densityVariation, enthalpyVariation, displacementVariation, preparedAction);
|
||||
CHECK(preparedOperator.GetTensorElementCount() > 0);
|
||||
mfem::Vector cached, tensorColumn, cachedColumn;
|
||||
preparedOperator.MultCachedReference(densityVariation, enthalpyVariation, displacementVariation, cached);
|
||||
CHECK(relative_error(preparedAction, cached, communicator) < 2.0e-11);
|
||||
preparedOperator.ApplyEnthalpyJacobianAction(enthalpyVariation, tensorColumn);
|
||||
preparedOperator.ApplyEnthalpyJacobianAction(enthalpyVariation, cachedColumn, false);
|
||||
CHECK(relative_error(tensorColumn, cachedColumn, communicator) < 2.0e-11);
|
||||
preparedOperator.ApplyDisplacementJacobianAction(displacementVariation, tensorColumn);
|
||||
preparedOperator.ApplyDisplacementJacobianAction(displacementVariation, cachedColumn, false);
|
||||
CHECK(relative_error(tensorColumn, cachedColumn, communicator) < 2.0e-11);
|
||||
|
||||
mfem::Vector fullReferenceResidual;
|
||||
mean_field::operators::kernels::apply_barotropic_closure(
|
||||
|
||||
@@ -69,6 +69,7 @@ TEST_CASE(
|
||||
REQUIRE(f.okay());
|
||||
|
||||
operators::PreparedMappedGravitySourceOperator operation(f, *f.domainMapperStateless);
|
||||
operators::PreparedMappedGravitySourceOperator oldWeights(f, *f.domainMapperStateless);
|
||||
const mfem::Vector densityTrue = prepared_test::make_deterministic_vector(f.densityFes->GetTrueVSize(), 0.41);
|
||||
const mfem::Vector density = operation.GetDensityMap().gather(densityTrue);
|
||||
const mfem::Vector displacementTrue = prepared_test::make_displacement(f, 0.4);
|
||||
@@ -81,6 +82,21 @@ TEST_CASE(
|
||||
mfem::Vector baselineVariation;
|
||||
operation.Mult(density, baselineAction);
|
||||
operation.MultDisplacementVariationTrue(densityTrue, directionTrue, baselineVariation);
|
||||
REQUIRE(operation.GetTensorVariationElementCount() > 0);
|
||||
mfem::Vector pointwiseVariation, zeroDirection(directionTrue), zeroVariation;
|
||||
operation.MultDisplacementVariationTrueReference(densityTrue, directionTrue, pointwiseVariation);
|
||||
CHECK(prepared_test::relative_error(baselineVariation, pointwiseVariation, communicator) < 2.0e-12);
|
||||
zeroDirection = 0.0;
|
||||
operation.MultDisplacementVariationTrue(densityTrue, zeroDirection, zeroVariation);
|
||||
CHECK(zeroVariation.Norml2() == 0.0);
|
||||
operation.MultDisplacementVariationTrue(densityTrue, directionTrue, pointwiseVariation);
|
||||
CHECK(prepared_test::relative_error(baselineVariation, pointwiseVariation, communicator) < 2.0e-14);
|
||||
oldWeights.PrepareReference(displacement);
|
||||
mfem::Vector oldAction, oldVariation;
|
||||
oldWeights.Mult(density, oldAction);
|
||||
oldWeights.MultDisplacementVariationTrue(densityTrue, directionTrue, oldVariation);
|
||||
CHECK(prepared_test::relative_error(baselineAction, oldAction, communicator) < 2.0e-14);
|
||||
CHECK(prepared_test::relative_error(baselineVariation, oldVariation, communicator) < 2.0e-14);
|
||||
|
||||
const mfem::Vector primalDisplacementTrue = prepared_test::make_displacement(f, 1.0);
|
||||
operation.PreparePrimal(operation.GetDisplacementMap().gather(primalDisplacementTrue));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -361,3 +361,80 @@ TEST_CASE(
|
||||
CHECK(recovered->preparedResidual);
|
||||
CHECK(preparedOperator.IsPrepared());
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Hydrostatic Tensor Preparation Matches Pointwise Preparation And Rebuilds On Mode Changes",
|
||||
tags::barotrope_hydrostatic_prepared_residual &tags::unit
|
||||
) {
|
||||
const auto args = test_utils::setup_args();
|
||||
auto f = mean_field::fem::setup_fem(args.mesh_file, args, 0);
|
||||
REQUIRE(f.okay());
|
||||
using namespace prepared_hydrostatic_test_utils;
|
||||
mean_field::operators::PreparedHydrostaticEquilibriumOperator fast(f, *f.domainMapperStateless);
|
||||
mean_field::operators::PreparedHydrostaticEquilibriumOperator reference(f, *f.domainMapperStateless);
|
||||
auto h = make_enthalpy(f), phi = make_gravity_potential(f);
|
||||
const auto dh = make_enthalpy(f, 0.53), dp = make_gravity_potential(f, 0.71);
|
||||
const auto du = field_dof_test_utils::make_supported_displacement(f, 0.31);
|
||||
const auto rotation = make_rotation();
|
||||
auto dependencies = make_dependencies();
|
||||
|
||||
for (double scale : {0.0, 0.42, 0.73}) {
|
||||
CAPTURE(scale);
|
||||
const auto displacement = field_dof_test_utils::make_supported_displacement(f, scale);
|
||||
h *= 1.01; phi *= 0.99;
|
||||
++dependencies.displacement.revision;
|
||||
++dependencies.enthalpy.revision;
|
||||
++dependencies.gravityPotential.revision;
|
||||
const auto state = make_state(h, phi, displacement, 0.39);
|
||||
REQUIRE(fast.Prepare(state, dependencies, rotation).DidAnyWork());
|
||||
REQUIRE(reference.PrepareReference(state, dependencies, rotation).DidAnyWork());
|
||||
CHECK(fast.GetTensorDisplacementElementCount() > 0);
|
||||
const auto compare = [&](auto &&apply) {
|
||||
mfem::Vector a, b;
|
||||
apply(fast, a); apply(reference, b);
|
||||
CHECK(gravity_prepared_test_utils::relative_error(a, b, f.mesh->GetComm()) < 2.0e-11);
|
||||
};
|
||||
compare([](auto &op, auto &out) { op.BuildResidual(out); });
|
||||
compare([&](auto &op, auto &out) { op.ApplyEnthalpyJacobianAction(dh, out); });
|
||||
compare([&](auto &op, auto &out) { op.ApplyGravityPotentialJacobianAction(dp, out); });
|
||||
compare([](auto &op, auto &out) { op.ApplyBernoulliConstantJacobianAction(0.13, out); });
|
||||
compare([&](auto &op, auto &out) { op.ApplyDisplacementJacobianAction(du, out); });
|
||||
compare([&](auto &op, auto &out) { op.ApplyCompleteJacobianAction(dh, dp, 0.13, du, out); });
|
||||
compare([](auto &op, auto &out) { op.AssembleEnthalpyJacobianDiagonal(out); });
|
||||
CHECK_FALSE(fast.Prepare(state, dependencies, rotation).DidAnyWork());
|
||||
CHECK_FALSE(reference.PrepareReference(state, dependencies, rotation).DidAnyWork());
|
||||
|
||||
CHECK(fast.PrepareReference(state, dependencies, rotation).DidAnyWork());
|
||||
compare([](auto &op, auto &out) { op.BuildResidual(out); });
|
||||
CHECK_FALSE(fast.PrepareReference(state, dependencies, rotation).DidAnyWork());
|
||||
CHECK(fast.Prepare(state, dependencies, rotation).DidAnyWork());
|
||||
compare([&](auto &op, auto &out) { op.ApplyCompleteJacobianAction(dh, dp, 0.13, du, out); });
|
||||
CHECK_FALSE(fast.Prepare(state, dependencies, rotation).DidAnyWork());
|
||||
}
|
||||
|
||||
mfem::ParGridFunction foldedField(f.displacementFes.get());
|
||||
mfem::VectorFunctionCoefficient fold(3, [](const mfem::Vector &x, mfem::Vector &u) {
|
||||
u = x; u *= -2.0;
|
||||
});
|
||||
foldedField.ProjectCoefficient(fold);
|
||||
mfem::Vector foldedTrue; foldedField.GetTrueDofs(foldedTrue);
|
||||
const auto folded = fast.GetDisplacementMap().gather(foldedTrue);
|
||||
++dependencies.displacement.revision;
|
||||
const auto rejectedState = make_state(h, phi, folded, 0.39);
|
||||
const auto rejected = fast.TryPrepare(rejectedState, dependencies, rotation);
|
||||
const auto referenceRejected = reference.TryPrepareReference(rejectedState, dependencies, rotation);
|
||||
REQUIRE_FALSE(rejected.has_value());
|
||||
REQUIRE_FALSE(referenceRejected.has_value());
|
||||
CHECK(rejected.error().reason == referenceRejected.error().reason);
|
||||
CHECK(rejected.error().mappingStatus == mean_field::mapping::MappingStatus::non_positive_determinant);
|
||||
CHECK_FALSE(fast.IsPrepared());
|
||||
CHECK_FALSE(reference.IsPrepared());
|
||||
|
||||
const auto recovered = make_state(h, phi, du, 0.39);
|
||||
++dependencies.displacement.revision;
|
||||
REQUIRE(fast.TryPrepare(recovered, dependencies, rotation).has_value());
|
||||
REQUIRE(reference.TryPrepareReference(recovered, dependencies, rotation).has_value());
|
||||
mfem::Vector a, b;
|
||||
fast.BuildResidual(a); reference.BuildResidual(b);
|
||||
CHECK(gravity_prepared_test_utils::relative_error(a, b, f.mesh->GetComm()) < 2.0e-11);
|
||||
}
|
||||
|
||||
@@ -198,6 +198,16 @@ TEST_CASE(
|
||||
CHECK(statistics.applications == 3);
|
||||
CHECK(centeredDifferenceError < 2.0e-7);
|
||||
CHECK(linearityError < 5.0e-12);
|
||||
int stellarElements = 0;
|
||||
preparedOperator.VisitMappedGeometryRules([&](int, const mfem::IntegrationRule &) { ++stellarElements; });
|
||||
CHECK(preparedOperator.GetFastDisplacementElementCount() == stellarElements);
|
||||
mfem::Vector preparedReference;
|
||||
preparedOperator.ApplyDisplacementJacobianActionReference(firstVariation, preparedReference);
|
||||
CHECK(prepared_hydrostatic_displacement_test_utils::relative_error(
|
||||
firstAction, preparedReference, f.mesh->GetComm()) < 2.0e-11);
|
||||
preparedOperator.ApplyDisplacementJacobianActionReference(secondVariation, preparedReference);
|
||||
CHECK(prepared_hydrostatic_displacement_test_utils::relative_error(
|
||||
secondAction, preparedReference, f.mesh->GetComm()) < 2.0e-11);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
@@ -344,4 +354,13 @@ TEST_CASE(
|
||||
CHECK(displacementStatistics.applications == 4);
|
||||
CHECK(geometryReferenceError < 2.0e-7);
|
||||
CHECK(geometryEffect > 1.0e-8);
|
||||
mfem::Vector preparedReference;
|
||||
preparedOperator.ApplyDisplacementJacobianActionReference(displacementVariation, preparedReference);
|
||||
CHECK(prepared_hydrostatic_displacement_test_utils::relative_error(
|
||||
geometryUpdatedAction, preparedReference, f.mesh->GetComm()) < 2.0e-11);
|
||||
preparedOperator.ApplyDisplacementJacobianActionCachedReference(displacementVariation, preparedReference);
|
||||
CHECK(prepared_hydrostatic_displacement_test_utils::relative_error(
|
||||
geometryUpdatedAction, preparedReference, f.mesh->GetComm()) < 2.0e-11);
|
||||
CHECK(preparedOperator.GetTensorDisplacementElementCount() > 0);
|
||||
CHECK(preparedOperator.GetDisplacementJacobianStatistics().applications == 4);
|
||||
}
|
||||
|
||||
@@ -439,10 +439,26 @@ TEST_CASE(
|
||||
|
||||
massOperator.Prepare({.targetMass = 1.0}, dependencies);
|
||||
const std::uint64_t preparationCount = massOperator.GetPreparationCount();
|
||||
CHECK(massOperator.GetJacobianRowPreparationCount() == 0);
|
||||
const auto rhoDirection = gravityContext.GetDensityMap().gather(
|
||||
mass_normalization_test_utils::make_density_direction(f, 0.67));
|
||||
const auto uDirection = gravityContext.GetDisplacementMap().gather(
|
||||
mass_normalization_test_utils::make_displacement_direction(f, -0.53));
|
||||
auto checkRows = [&](std::uint64_t expectedBuilds) {
|
||||
REQUIRE(massOperator.PrepareJacobianRows());
|
||||
CHECK(massOperator.GetJacobianRowPreparationCount() == expectedBuilds);
|
||||
mfem::Vector actual, reference;
|
||||
massOperator.ApplyCompleteJacobianAction(rhoDirection, uDirection, actual);
|
||||
massOperator.ApplyCompleteJacobianActionReference(rhoDirection, uDirection, reference);
|
||||
CHECK(mass_normalization_test_utils::relative_error(actual(0), reference(0)) < 2.0e-11);
|
||||
CHECK(massOperator.GetJacobianRowPreparationCount() == expectedBuilds);
|
||||
};
|
||||
checkRows(1);
|
||||
|
||||
const auto repeated = massOperator.Prepare({.targetMass = 1.0}, dependencies);
|
||||
CHECK_FALSE(repeated.DidAnyWork());
|
||||
CHECK(massOperator.GetPreparationCount() == preparationCount);
|
||||
checkRows(1);
|
||||
|
||||
++gravityPotentialRevision;
|
||||
mass_normalization_test_utils::prepare_gravity_context(
|
||||
@@ -451,6 +467,7 @@ TEST_CASE(
|
||||
|
||||
const auto potentialOnly = massOperator.Prepare({.targetMass = 1.0}, dependencies);
|
||||
CHECK_FALSE(potentialOnly.DidAnyWork());
|
||||
checkRows(1);
|
||||
|
||||
const double residualBeforeTargetChange = mass_normalization_test_utils::residual_value(massOperator);
|
||||
const double massBeforeTargetChange = massOperator.GetCurrentMass();
|
||||
@@ -463,6 +480,7 @@ TEST_CASE(
|
||||
CHECK_FALSE(targetOnly.refreshedGeometry);
|
||||
CHECK_FALSE(targetOnly.refreshedDensity);
|
||||
CHECK(massOperator.GetCurrentMass() == massBeforeTargetChange);
|
||||
checkRows(1);
|
||||
CHECK(
|
||||
mass_normalization_test_utils::relative_error(
|
||||
mass_normalization_test_utils::residual_value(massOperator) - residualBeforeTargetChange, -0.4
|
||||
@@ -481,6 +499,8 @@ TEST_CASE(
|
||||
CHECK(densityOnly.assembledResidual);
|
||||
CHECK_FALSE(densityOnly.refreshedGeometry);
|
||||
CHECK(massOperator.GetCurrentMass() != massBeforeDensityChange);
|
||||
CHECK(massOperator.GetJacobianRowPreparationCount() == 1);
|
||||
checkRows(2);
|
||||
|
||||
displacement = mass_normalization_test_utils::make_displacement_direction(f, 0.87);
|
||||
++dependencies.displacement.revision;
|
||||
@@ -492,6 +512,8 @@ TEST_CASE(
|
||||
CHECK(geometryOnly.refreshedGeometry);
|
||||
CHECK(geometryOnly.assembledResidual);
|
||||
CHECK_FALSE(geometryOnly.refreshedDensity);
|
||||
CHECK(massOperator.GetJacobianRowPreparationCount() == 2);
|
||||
checkRows(3);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
@@ -587,6 +609,11 @@ TEST_CASE(
|
||||
massOperator.ApplyDisplacementJacobianAction(reducedDisplacementDirection, displacementAction);
|
||||
massOperator.ApplyCompleteJacobianAction(reducedDensityDirection, reducedDisplacementDirection, completeAction);
|
||||
|
||||
mfem::Vector preparedReference;
|
||||
massOperator.ApplyCompleteJacobianActionReference(
|
||||
reducedDensityDirection, reducedDisplacementDirection, preparedReference);
|
||||
CHECK(mass_normalization_test_utils::relative_error(completeAction(0), preparedReference(0)) < 2.0e-11);
|
||||
|
||||
CHECK(
|
||||
mass_normalization_test_utils::relative_error(completeAction(0), densityAction(0) + displacementAction(0)) <
|
||||
2.0e-15
|
||||
|
||||
@@ -439,6 +439,15 @@ TEST_CASE(
|
||||
mfem::Vector kernelDisplacementActionTrue;
|
||||
|
||||
preparedOperator.ApplyDisplacementJacobianAction(displacementDirection, preparedDisplacementAction);
|
||||
REQUIRE(preparedOperator.GetTensorElementCount() > 0);
|
||||
mfem::Vector cachedDisplacementAction;
|
||||
preparedOperator.ApplyDisplacementJacobianActionCachedReference(displacementDirection, cachedDisplacementAction);
|
||||
CHECK(prepared_pressure_force_test_utils::relative_difference(
|
||||
preparedDisplacementAction, cachedDisplacementAction, f.mesh->GetComm()) < 2.0e-12);
|
||||
mfem::Vector retainedDisplacementAction;
|
||||
preparedOperator.ApplyDisplacementJacobianActionReference(displacementDirection, retainedDisplacementAction);
|
||||
CHECK(prepared_pressure_force_test_utils::relative_difference(
|
||||
preparedDisplacementAction, retainedDisplacementAction, f.mesh->GetComm()) < 2.0e-12);
|
||||
|
||||
mean_field::operators::kernels::apply_pressure_force_displacement_action(
|
||||
f, *f.domainMapperStateless, equationOfState, enthalpyTrue, displacementDirectionTrue, displacementTrue,
|
||||
@@ -465,6 +474,30 @@ TEST_CASE(
|
||||
prepared_pressure_force_test_utils::relative_difference(fusedAction, expectedFusedAction, f.mesh->GetComm()) <
|
||||
2.0e-12
|
||||
);
|
||||
|
||||
mfem::Vector originalResidual, referenceResidual, referenceEnthalpy;
|
||||
preparedOperator.BuildResidual(originalResidual);
|
||||
const auto state = mean_field::operators::context::pressure_force::PressureForceStateView{
|
||||
.enthalpy = enthalpy, .displacement = displacement};
|
||||
const auto dependencies = prepared_pressure_force_test_utils::make_dependencies();
|
||||
CHECK(preparedOperator.PrepareReference(state, dependencies).DidAnyWork());
|
||||
preparedOperator.BuildResidual(referenceResidual);
|
||||
preparedOperator.ApplyEnthalpyJacobianAction(enthalpyDirection, referenceEnthalpy);
|
||||
CHECK(prepared_pressure_force_test_utils::relative_difference(
|
||||
originalResidual, referenceResidual, f.mesh->GetComm()) < 2.0e-12);
|
||||
CHECK(prepared_pressure_force_test_utils::relative_difference(
|
||||
preparedEnthalpyAction, referenceEnthalpy, f.mesh->GetComm()) < 2.0e-12);
|
||||
CHECK_FALSE(preparedOperator.PrepareReference(state, dependencies).DidAnyWork());
|
||||
CHECK(preparedOperator.PrepareCachedReference(state, dependencies).DidAnyWork());
|
||||
preparedOperator.BuildResidual(referenceResidual);
|
||||
preparedOperator.ApplyEnthalpyJacobianAction(enthalpyDirection, referenceEnthalpy);
|
||||
CHECK(prepared_pressure_force_test_utils::relative_difference(
|
||||
originalResidual, referenceResidual, f.mesh->GetComm()) < 2.0e-12);
|
||||
CHECK(prepared_pressure_force_test_utils::relative_difference(
|
||||
preparedEnthalpyAction, referenceEnthalpy, f.mesh->GetComm()) < 2.0e-12);
|
||||
CHECK_FALSE(preparedOperator.PrepareCachedReference(state, dependencies).DidAnyWork());
|
||||
CHECK(preparedOperator.Prepare(state, dependencies).DidAnyWork());
|
||||
CHECK_FALSE(preparedOperator.Prepare(state, dependencies).DidAnyWork());
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
|
||||
@@ -551,6 +551,19 @@ TEST_CASE(
|
||||
CHECK(rotationReport.preparedResidual);
|
||||
CHECK(preparedOperator.GetResidualPreparationCount() == 3);
|
||||
CHECK(preparedOperator.GetResidualApplicationCount() == 1);
|
||||
mfem::Vector updatedResidual, referenceResidual;
|
||||
preparedOperator.BuildResidual(updatedResidual);
|
||||
CHECK(preparedOperator.PrepareReference(
|
||||
{.density = density, .displacement = displacement}, dependencies, rotation).DidAnyWork());
|
||||
preparedOperator.BuildResidual(referenceResidual);
|
||||
CHECK(rotational_displacement_force_test_utils::relative_difference(
|
||||
updatedResidual, referenceResidual, f.mesh->GetComm()) < 2.0e-12);
|
||||
CHECK_FALSE(preparedOperator.PrepareReference(
|
||||
{.density = density, .displacement = displacement}, dependencies, rotation).DidAnyWork());
|
||||
CHECK(preparedOperator.Prepare(
|
||||
{.density = density, .displacement = displacement}, dependencies, rotation).DidAnyWork());
|
||||
CHECK_FALSE(preparedOperator.Prepare(
|
||||
{.density = density, .displacement = displacement}, dependencies, rotation).DidAnyWork());
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
@@ -598,6 +611,16 @@ TEST_CASE(
|
||||
|
||||
preparedOperator.ApplyCompleteJacobianAction(densityDirection, displacementDirection, completeAction);
|
||||
|
||||
mfem::Vector retainedAction;
|
||||
preparedOperator.ApplyCompleteJacobianActionReference(densityDirection, displacementDirection, retainedAction);
|
||||
CHECK(preparedOperator.GetFastElementCount() > 0);
|
||||
CHECK(preparedOperator.GetTensorElementCount() == preparedOperator.GetFastElementCount());
|
||||
CHECK(rotational_displacement_force_test_utils::relative_difference(
|
||||
completeAction, retainedAction, f.mesh->GetComm()) < 2.0e-12);
|
||||
preparedOperator.ApplyCompleteJacobianActionCachedReference(densityDirection, displacementDirection, retainedAction);
|
||||
CHECK(rotational_displacement_force_test_utils::relative_difference(
|
||||
completeAction, retainedAction, f.mesh->GetComm()) < 2.0e-12);
|
||||
|
||||
mfem::Vector summedColumns(densityAction);
|
||||
summedColumns += displacementAction;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user