perf(jacobian-action): major updates to jacobian action application by removing redudant quadrature work. ~5x increase in speed

This commit is contained in:
2026-09-02 17:01:50 -04:00
parent 85500fef3b
commit 25510008dd
74 changed files with 8967 additions and 814 deletions

View File

@@ -449,6 +449,65 @@ TEST_CASE(
CHECK_FALSE(geometryOnly.refreshedDensity);
}
TEST_CASE(
"Compiled Fixed Total Mass Is Exactly Equivalent To The Legacy Mass State Adapter",
tags::fixed_total_mass_constraint
) {
using Operator = mean_field::operators::PreparedFixedMass;
STATIC_CHECK(mean_field::operators::PreparedConstraint<Operator>);
mean_field::utils::Args args = test_utils::setup_args();
mean_field::fem::FEM f = mean_field::fem::setup_fem(args.mesh_file, args, 0);
REQUIRE(f.okay());
const mfem::Vector density = mass_normalization_test_utils::make_density(f, 0.53);
const mfem::Vector displacement = mass_normalization_test_utils::make_displacement_direction(f, 0.37);
const mfem::Vector densityDirection = mass_normalization_test_utils::make_density_direction(f, -0.61);
const mfem::Vector displacementDirection = mass_normalization_test_utils::make_displacement_direction(f, 0.43);
const auto dependencies = mass_normalization_test_utils::make_dependencies();
mean_field::operators::context::gravity_field::GravityFieldLinearizationContext gravityContext(
f, *f.domainMapperStateless
);
mass_normalization_test_utils::prepare_gravity_context(gravityContext, f, density, displacement, dependencies);
Operator legacy(f, *f.domainMapperStateless, gravityContext);
Operator compiled(f, *f.domainMapperStateless, gravityContext);
constexpr double targetMass = 1.31;
const mean_field::models::CompiledFixedMass fixedMass = mean_field::models::compileConstraint(
mean_field::models::FixedTotalMass{mean_field::dimensions::MassValue{targetMass}}
);
const auto legacyReport = legacy.Prepare({.targetMass = targetMass}, dependencies);
const auto compiledReport = compiled.Prepare(fixedMass, dependencies);
CHECK(legacyReport == compiledReport);
CHECK(legacy.GetPreparationCount() == compiled.GetPreparationCount());
CHECK(legacy.GetCurrentMass() == compiled.GetCurrentMass());
CHECK(legacy.GetTargetMass() == compiled.GetTargetMass());
CHECK(
mass_normalization_test_utils::residual_value(legacy) == mass_normalization_test_utils::residual_value(compiled)
);
const mfem::Vector reducedDensityDirection = gravityContext.GetDensityMap().gather(densityDirection);
const mfem::Vector reducedDisplacementDirection = gravityContext.GetDisplacementMap().gather(displacementDirection);
mfem::Vector legacyAction;
mfem::Vector compiledAction;
legacy.ApplyCompleteJacobianAction(reducedDensityDirection, reducedDisplacementDirection, legacyAction);
compiled.ApplyJacobian(
{.densityVariation = reducedDensityDirection, .displacementVariation = reducedDisplacementDirection},
compiledAction
);
REQUIRE(legacyAction.Size() == 1);
REQUIRE(compiledAction.Size() == 1);
CHECK(legacyAction(0) == compiledAction(0));
CHECK(legacy.GetActionStatistics().completeApplications == compiled.GetActionStatistics().completeApplications);
}
TEST_CASE(
"Prepared Mass Normalization Complete Action And Coupled Routing Are Exact",
tags::barotrope_mass_normalization_jacobian
@@ -524,6 +583,19 @@ TEST_CASE(
}
}
mfem::Vector residualDual(layout.residual_offsets().Last());
residualDual = 0.0;
residualDual(massOffset) = -0.83;
mfem::Vector stateDual;
adapter.MultTranspose(residualDual, stateDual);
REQUIRE(stateDual.Size() == direction.Size());
const double forwardPairing = coupledAction * residualDual;
const double transposePairing = direction * stateDual;
CHECK(mass_normalization_test_utils::relative_error(transposePairing, forwardPairing) < 2.0e-12);
CHECK(massOperator.GetActionStatistics().transposeApplications == 1);
CHECK(&massOperator.GetFEM() == &f);
CHECK(&massOperator.GetGravityContext() == &gravityContext);
CHECK(adapter.GetLayout().residual_offsets().Last() == layout.residual_offsets().Last());