perf(jacobian-action): major updates to jacobian action application by removing redudant quadrature work. ~5x increase in speed
This commit is contained in:
204
tests/operators/root_manifest.cpp
Normal file
204
tests/operators/root_manifest.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <mfem.hpp>
|
||||
|
||||
import mean_field;
|
||||
import test_helpers;
|
||||
|
||||
namespace {
|
||||
using CanonicalModel = mean_field::models::
|
||||
Model<mean_field::eos::Polytrope, mean_field::models::FixedTotalMass, mean_field::surface::Isobaric>;
|
||||
|
||||
using PermutedModel = mean_field::models::
|
||||
Model<mean_field::models::FixedTotalMass, mean_field::surface::Isobaric, mean_field::eos::Polytrope>;
|
||||
|
||||
using CentralDensityModel = mean_field::models::Model<
|
||||
mean_field::models::FixedCentralDensity,
|
||||
mean_field::surface::Isobaric,
|
||||
mean_field::eos::Polytrope,
|
||||
mean_field::models::FixedTotalMass>;
|
||||
|
||||
using Form = mean_field::utils::blocks::surface_deformed_stellar_equilibrium_form;
|
||||
using JacobianForm = mean_field::utils::blocks::surface_deformed_stellar_equilibrium_jacobian_form;
|
||||
using Manifest = mean_field::operators::CompiledRootManifest<CanonicalModel, Form, JacobianForm>;
|
||||
using CentralForm = mean_field::utils::blocks::central_density_bordered_stellar_equilibrium_form;
|
||||
using CentralJacobianForm = mean_field::utils::blocks::central_density_bordered_stellar_equilibrium_jacobian_form;
|
||||
using CentralManifest =
|
||||
mean_field::operators::CompiledRootManifest<CentralDensityModel, CentralForm, CentralJacobianForm>;
|
||||
|
||||
[[nodiscard]] Manifest make_manifest() {
|
||||
const std::array<int, Form::value_block_count> valueSizes{2, 3, 4, 5, 6, 1};
|
||||
const std::array<int, Form::residual_block_count> residualSizes{4, 5, 2, 3, 6, 1};
|
||||
return {valueSizes, residualSizes, 2.5, 0.125, 3};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE(
|
||||
"Model Values Are Stored In Canonical Specification Order",
|
||||
tags::model_specification_type_contract
|
||||
) {
|
||||
STATIC_CHECK(std::same_as<CanonicalModel, PermutedModel>);
|
||||
STATIC_CHECK(CanonicalModel::symbolicallySquare);
|
||||
STATIC_CHECK(CanonicalModel::hasCompleteRootCompiler);
|
||||
STATIC_CHECK(CanonicalModel::compilationClass == mean_field::models::ModelCompilationClass::isolated_root);
|
||||
STATIC_CHECK(CentralDensityModel::symbolicallySquare);
|
||||
STATIC_CHECK(CentralDensityModel::hasCompleteRootCompiler);
|
||||
STATIC_CHECK(CentralDensityModel::compilationClass == mean_field::models::ModelCompilationClass::isolated_root);
|
||||
|
||||
const mean_field::eos::Polytrope equationOfState{2.0, 0.75};
|
||||
const mean_field::surface::Isobaric surface{mean_field::dimensions::PressureValue{0.125}};
|
||||
const mean_field::models::FixedTotalMass mass{mean_field::dimensions::MassValue{1.75}};
|
||||
|
||||
const CanonicalModel model{mass, surface, equationOfState};
|
||||
|
||||
CHECK(model.specification<mean_field::eos::Polytrope>().polytropic_index() == 2.0);
|
||||
CHECK(model.specification<mean_field::surface::Isobaric>().targetPressure().value() == 0.125);
|
||||
CHECK(
|
||||
model.specification<mean_field::models::FixedTotalMass>().targetMass() ==
|
||||
mean_field::dimensions::MassValue{1.75}
|
||||
);
|
||||
|
||||
const auto descriptors = model.runtimeSpecificationDescriptors();
|
||||
REQUIRE(descriptors.size() == 3);
|
||||
CHECK(descriptors[0].specification.name == "Polytrope");
|
||||
CHECK(descriptors[1].specification.name == "IsobaricSurface");
|
||||
CHECK(descriptors[2].specification.name == "FixedTotalMass");
|
||||
CHECK(descriptors[0].canonicalIndex == 0);
|
||||
CHECK(descriptors[1].canonicalIndex == 1);
|
||||
CHECK(descriptors[2].canonicalIndex == 2);
|
||||
CHECK(descriptors[0].hasRootCompiler);
|
||||
CHECK(descriptors[1].hasRootCompiler);
|
||||
CHECK(descriptors[2].hasRootCompiler);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Central Density Root Manifest Appends A Carrier Phase Row And Solver Border",
|
||||
tags::root_manifest_type_contract
|
||||
) {
|
||||
const std::array<int, CentralForm::value_block_count> valueSizes{2, 3, 4, 5, 6, 1, 1};
|
||||
const std::array<int, CentralForm::residual_block_count> residualSizes{4, 5, 2, 3, 6, 1, 1};
|
||||
const CentralManifest manifest(
|
||||
valueSizes, residualSizes, 2.5, 0.125, 3,
|
||||
mean_field::operators::CentralDensityManifestInput{
|
||||
.targetDensity = 8.0, .targetEnthalpy = 2.0, .centerDofCount = 1
|
||||
}
|
||||
);
|
||||
|
||||
CHECK(manifest.layout().value_offsets().Last() == 22);
|
||||
CHECK(manifest.layout().residual_offsets().Last() == 22);
|
||||
REQUIRE(manifest.valueBlocks().size() == 7);
|
||||
REQUIRE(manifest.residualBlocks().size() == 7);
|
||||
CHECK(manifest.valueBlocks()[6].stableId == "fixed_central_density.border");
|
||||
CHECK(manifest.valueBlocks()[6].symbol == "lambda_rho_c");
|
||||
CHECK(manifest.valueBlocks()[6].columnPolicy == mean_field::operators::RootColumnPolicy::solver_border);
|
||||
CHECK(manifest.residualBlocks()[6].stableId == "fixed_central_density.residual");
|
||||
CHECK(manifest.residualBlocks()[6].symbol == "R_rho_c");
|
||||
CHECK(manifest.residualBlocks()[6].scale == 2.0);
|
||||
|
||||
const auto constraints = manifest.constraints();
|
||||
REQUIRE(constraints.size() == 3);
|
||||
CHECK(constraints[2].stableId == "FixedCentralDensity");
|
||||
CHECK(constraints[2].role == mean_field::models::SpecificationRole::phase_condition);
|
||||
CHECK(constraints[2].valueBlock == 6);
|
||||
CHECK(constraints[2].residualBlock == 6);
|
||||
CHECK(constraints[2].target == 8.0);
|
||||
REQUIRE(constraints[2].carrierTarget.has_value());
|
||||
CHECK(*constraints[2].carrierTarget == 2.0);
|
||||
CHECK(constraints[2].residualScale == 2.0);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Compiled Root Manifest Centralizes Canonical Blocks Provenance And Scaling",
|
||||
tags::root_manifest_type_contract
|
||||
) {
|
||||
const Manifest manifest = make_manifest();
|
||||
|
||||
STATIC_CHECK(Manifest::symbolicallySquare);
|
||||
STATIC_CHECK(Manifest::compilationClass == mean_field::models::ModelCompilationClass::isolated_root);
|
||||
|
||||
CHECK(manifest.layout().value_offsets().Last() == 21);
|
||||
CHECK(manifest.layout().residual_offsets().Last() == 21);
|
||||
|
||||
const auto values = manifest.valueBlocks();
|
||||
const auto residuals = manifest.residualBlocks();
|
||||
|
||||
REQUIRE(values.size() == 6);
|
||||
REQUIRE(residuals.size() == 6);
|
||||
CHECK(values[0].stableId == "density");
|
||||
CHECK(values[0].symbol == "rho");
|
||||
CHECK(values[1].stableId == "surface_deformation");
|
||||
CHECK(values[5].stableId == "fixed_total_mass.multiplier");
|
||||
CHECK(values[5].symbol == "C");
|
||||
CHECK(values[5].provenance == mean_field::operators::RootBlockProvenance::model_specification);
|
||||
CHECK(values[5].source == "FixedTotalMass");
|
||||
CHECK(values[5].columnPolicy == mean_field::operators::RootColumnPolicy::existing_physical_multiplier);
|
||||
|
||||
CHECK(residuals[5].stableId == "fixed_total_mass.residual");
|
||||
CHECK(residuals[5].symbol == "R_M");
|
||||
CHECK(residuals[5].rowInjection == mean_field::operators::RootRowInjection::append_global);
|
||||
CHECK(residuals[5].scalePolicy == mean_field::operators::RootScalePolicy::target_relative);
|
||||
CHECK(residuals[5].scale == 2.5);
|
||||
|
||||
const auto replacements = manifest.rowReplacements();
|
||||
REQUIRE(replacements.size() == 1);
|
||||
CHECK(replacements[0].sourceSpecification == "IsobaricSurface");
|
||||
CHECK(replacements[0].replacedRowCount == 3);
|
||||
CHECK(replacements[0].carrierResidualBlock == 4);
|
||||
|
||||
const auto constraints = manifest.constraints();
|
||||
REQUIRE(constraints.size() == 2);
|
||||
CHECK(constraints[0].stableId == "FixedTotalMass");
|
||||
CHECK(constraints[0].valueBlock == 5);
|
||||
CHECK(constraints[0].residualBlock == 5);
|
||||
CHECK(constraints[0].target == 2.5);
|
||||
CHECK(constraints[0].residualScale == 2.5);
|
||||
CHECK(constraints[1].stableId == "IsobaricSurface");
|
||||
CHECK(constraints[1].rowInjection == mean_field::operators::RootRowInjection::replace_carrier_rows);
|
||||
CHECK(constraints[1].target == 0.125);
|
||||
CHECK_FALSE(constraints[1].carrierTarget.has_value());
|
||||
|
||||
const auto report = manifest.fixedMassReport(2.75);
|
||||
CHECK(report.achieved == 2.75);
|
||||
CHECK(report.dimensionalResidual == 0.25);
|
||||
CHECK(report.scaledResidual == 0.1);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Typed Root Views Resolve Blocks Through The Compiled Manifest",
|
||||
tags::root_manifest_type_contract
|
||||
) {
|
||||
const Manifest manifest = make_manifest();
|
||||
|
||||
mfem::Vector state(manifest.layout().value_offsets().Last());
|
||||
for (int index = 0; index < state.Size(); ++index) {
|
||||
state(index) = static_cast<double>(index + 1);
|
||||
}
|
||||
|
||||
const auto stateView = manifest.stateView(state);
|
||||
const mfem::Vector density = stateView.block(mean_field::utils::blocks::density_field.mass_term);
|
||||
const mfem::Vector surface = stateView.block(mean_field::utils::blocks::surface_deformation_field.parameters_term);
|
||||
const mfem::Vector multiplier =
|
||||
stateView.block(mean_field::utils::blocks::fixed_total_mass_constraint.mass_normalization_term);
|
||||
|
||||
REQUIRE(density.Size() == 2);
|
||||
REQUIRE(surface.Size() == 3);
|
||||
REQUIRE(multiplier.Size() == 1);
|
||||
CHECK(density(0) == 1.0);
|
||||
CHECK(surface(0) == 3.0);
|
||||
CHECK(multiplier(0) == 21.0);
|
||||
|
||||
mfem::Vector residual(manifest.layout().residual_offsets().Last());
|
||||
residual = 0.0;
|
||||
const auto residualView = manifest.residualView(residual);
|
||||
mfem::Vector massResidual(1);
|
||||
massResidual(0) = -0.375;
|
||||
residualView.assign(mean_field::utils::blocks::fixed_total_mass_constraint.mass_normalization_term, massResidual);
|
||||
CHECK(residual(20) == -0.375);
|
||||
|
||||
mfem::Vector wrongState(state.Size() - 1);
|
||||
CHECK_THROWS_AS(manifest.stateView(wrongState), std::invalid_argument);
|
||||
}
|
||||
Reference in New Issue
Block a user