feat(preconditioner): major work on preconditioner system

first preconditioner MVP
This commit is contained in:
2026-09-04 07:54:10 -04:00
parent 25510008dd
commit 71423d543f
61 changed files with 15920 additions and 422 deletions

View File

@@ -1,3 +1,4 @@
#include "profile.h"
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
@@ -576,7 +577,8 @@ TEST_CASE(
integrator.AssembleElementVector(elements, *transformation, element_state, element_residual);
mfem::Vector position_test_dofs(velocity_size);
mfem::Vector x_physical(dim);
mapping::MappingPointContext point_context;
mapping::VolumeMappingContext volume_context;
position_test_dofs = 0.0;
const mfem::IntegrationRule &velocity_nodes = velocity_element->GetNodes();
@@ -584,10 +586,14 @@ TEST_CASE(
for (int i = 0; i < velocity_dofs_count; ++i) {
const mfem::IntegrationPoint &node = velocity_nodes.IntPoint(i);
transformation->SetIntPoint(&node);
mapping_evaluator.GetPhysicalPoint(*transformation, node, x_physical);
MFEM_VERIFY(
mapping_evaluator.EvaluatePoint(*transformation, node, point_context) ==
mapping::MappingStatus::valid,
"Centrifugal residual reference encountered an invalid nodal mapping."
);
for (int d = 0; d < dim; ++d) {
position_test_dofs(i + d * velocity_dofs_count) = x_physical(d);
position_test_dofs(i + d * velocity_dofs_count) = point_context.physical_position(d);
}
}
@@ -605,14 +611,17 @@ TEST_CASE(
const mfem::IntegrationPoint &integration_point = reference_rule.IntPoint(q);
transformation->SetIntPoint(&integration_point);
const mapping::VolumeQuadratureContext context =
mapping_evaluator.GetQuadratureContext(*transformation, integration_point);
const double signed_map_determinant = context.detJ;
MFEM_VERIFY(
mapping_evaluator.EvaluateVolume(*transformation, integration_point, volume_context) ==
mapping::MappingStatus::valid,
"Centrifugal residual reference encountered an invalid volume mapping."
);
const double signed_map_determinant = volume_context.quadrature.detJ;
local_minimum_map_determinant = std::min(local_minimum_map_determinant, signed_map_determinant);
local_maximum_map_determinant = std::max(local_maximum_map_determinant, signed_map_determinant);
mapping_evaluator.GetPhysicalPoint(*transformation, integration_point, x_physical);
const mfem::Vector &x_physical = volume_context.mapping.physical_position;
velocity_element->CalcShape(integration_point, velocity_shape);
position_test_value = 0.0;
@@ -634,9 +643,9 @@ TEST_CASE(
const double density_value = density.GetValue(elem_id, integration_point);
local_discrete_reference_action +=
density_value * (position_test_value * centrifugal_acceleration) * context.weight;
density_value * (position_test_value * centrifugal_acceleration) * volume_context.quadrature.weight;
local_continuous_reference_action +=
density_value * (x_physical * centrifugal_acceleration) * context.weight;
density_value * (x_physical * centrifugal_acceleration) * volume_context.quadrature.weight;
}
}
@@ -780,7 +789,8 @@ TEST_CASE(
const int velocity_size = dim * velocity_dofs_count;
mfem::Vector position_test_dofs(velocity_size);
mfem::Vector x_physical(dim);
mapping::MappingPointContext point_context;
mapping::VolumeMappingContext volume_context;
position_test_dofs = 0.0;
const mfem::IntegrationRule &velocity_nodes = velocity_element->GetNodes();
@@ -788,10 +798,14 @@ TEST_CASE(
for (int i = 0; i < velocity_dofs_count; ++i) {
const mfem::IntegrationPoint &node = velocity_nodes.IntPoint(i);
transformation->SetIntPoint(&node);
mapping_evaluator.GetPhysicalPoint(*transformation, node, x_physical);
MFEM_VERIFY(
mapping_evaluator.EvaluatePoint(*transformation, node, point_context) ==
mapping::MappingStatus::valid,
"Centrifugal p-refinement reference encountered an invalid nodal mapping."
);
for (int d = 0; d < dim; ++d) {
position_test_dofs(i + d * velocity_dofs_count) = x_physical(d);
position_test_dofs(i + d * velocity_dofs_count) = point_context.physical_position(d);
}
}
@@ -807,13 +821,16 @@ TEST_CASE(
const mfem::IntegrationPoint &integration_point = reference_rule.IntPoint(q);
transformation->SetIntPoint(&integration_point);
const mapping::VolumeQuadratureContext context =
mapping_evaluator.GetQuadratureContext(*transformation, integration_point);
const double signed_map_determinant = context.detJ;
MFEM_VERIFY(
mapping_evaluator.EvaluateVolume(*transformation, integration_point, volume_context) ==
mapping::MappingStatus::valid,
"Centrifugal p-refinement reference encountered an invalid volume mapping."
);
const double signed_map_determinant = volume_context.quadrature.detJ;
local_minimum_determinant = std::min(local_minimum_determinant, signed_map_determinant);
mapping_evaluator.GetPhysicalPoint(*transformation, integration_point, x_physical);
const mfem::Vector &x_physical = volume_context.mapping.physical_position;
velocity_element->CalcShape(integration_point, velocity_shape);
position_test_value = 0.0;
@@ -838,9 +855,10 @@ TEST_CASE(
const double density_value = density.GetValue(elem_id, integration_point);
local_discrete_action +=
density_value * (position_test_value * centrifugal_acceleration) * context.weight;
local_continuous_action += density_value * (x_physical * centrifugal_acceleration) * context.weight;
local_discrete_action += density_value * (position_test_value * centrifugal_acceleration) *
volume_context.quadrature.weight;
local_continuous_action +=
density_value * (x_physical * centrifugal_acceleration) * volume_context.quadrature.weight;
}
}
@@ -882,6 +900,8 @@ TEST_CASE(
"Centrifugal Virial Position Representation Converges Under H Refinement",
tags::rotation_integrator_convergence
) {
MEAN_FIELD_PROFILE_RESET();
constexpr int dim = 3;
constexpr double concentration = 4.0;
constexpr double minimum_rate = 1.5;
@@ -893,9 +913,12 @@ TEST_CASE(
std::array<std::array<double, refinement_levels.size()>, rotation_fractions.size()> minimum_determinants{};
for (std::size_t refinement_index = 0; refinement_index < refinement_levels.size(); ++refinement_index) {
auto args = test_utils::setup_args();
auto args = test_utils::setup_args();
fem::FEM f = fem::setup_fem(args.mesh_file, args, refinement_levels[refinement_index]);
fem::FEM f = MEAN_FIELD_PROFILE_EVALUATE_WARMUP(
"centrifugal virial: FEM setup", 0,
fem::setup_fem(args.mesh_file, args, refinement_levels[refinement_index])
);
const double radius = utils::RADIUS;
@@ -942,8 +965,11 @@ TEST_CASE(
};
mfem::VectorFunctionCoefficient displacement_coefficient(dim, rotation_displacement);
displacement.ProjectCoefficient(displacement_coefficient);
*f.displacement = displacement;
MEAN_FIELD_PROFILE_CALL_WARMUP(
"centrifugal virial: displacement projection", 0,
displacement.ProjectCoefficient(displacement_coefficient);
*f.displacement = displacement
);
mapping::GridFunctionMappingEvaluator mapping_evaluator(
*f.domainMapperStateless, *f.displacement, *f.compactificationCoordinate
);
@@ -955,9 +981,13 @@ TEST_CASE(
const int reference_order =
2 * std::max(f.displacementFes->GetMaxElementOrder(), f.densityFes->GetMaxElementOrder()) + 16;
double local_discrete_action = 0.0;
double local_continuous_action = 0.0;
double local_minimum_determinant = std::numeric_limits<double>::infinity();
double local_discrete_action = 0.0;
double local_continuous_action = 0.0;
double local_minimum_determinant = std::numeric_limits<double>::infinity();
std::uint64_t nodal_mapping_evaluations = 0;
std::uint64_t quadrature_mapping_evaluations = 0;
MEAN_FIELD_PROFILE_SCOPE_WARMUP("centrifugal virial: integration traversal", 0);
for (int elem_id = 0; elem_id < f.mesh->GetNE(); ++elem_id) {
if (f.mesh->GetAttribute(elem_id) == 3) {
@@ -971,7 +1001,8 @@ TEST_CASE(
const int velocity_size = dim * velocity_dofs_count;
mfem::Vector position_test_dofs(velocity_size);
mfem::Vector x_physical(dim);
mapping::MappingPointContext point_context;
mapping::VolumeMappingContext volume_context;
position_test_dofs = 0.0;
const mfem::IntegrationRule &velocity_nodes = velocity_element->GetNodes();
@@ -979,10 +1010,15 @@ TEST_CASE(
for (int i = 0; i < velocity_dofs_count; ++i) {
const mfem::IntegrationPoint &node = velocity_nodes.IntPoint(i);
transformation->SetIntPoint(&node);
mapping_evaluator.GetPhysicalPoint(*transformation, node, x_physical);
MFEM_VERIFY(
mapping_evaluator.EvaluatePoint(*transformation, node, point_context) ==
mapping::MappingStatus::valid,
"Centrifugal h-refinement reference encountered an invalid nodal mapping."
);
++nodal_mapping_evaluations;
for (int d = 0; d < dim; ++d) {
position_test_dofs(i + d * velocity_dofs_count) = x_physical(d);
position_test_dofs(i + d * velocity_dofs_count) = point_context.physical_position(d);
}
}
@@ -998,13 +1034,17 @@ TEST_CASE(
const mfem::IntegrationPoint &integration_point = reference_rule.IntPoint(q);
transformation->SetIntPoint(&integration_point);
const mapping::VolumeQuadratureContext context =
mapping_evaluator.GetQuadratureContext(*transformation, integration_point);
const double signed_map_determinant = context.detJ;
MFEM_VERIFY(
mapping_evaluator.EvaluateVolume(*transformation, integration_point, volume_context) ==
mapping::MappingStatus::valid,
"Centrifugal h-refinement reference encountered an invalid volume mapping."
);
++quadrature_mapping_evaluations;
const double signed_map_determinant = volume_context.quadrature.detJ;
local_minimum_determinant = std::min(local_minimum_determinant, signed_map_determinant);
mapping_evaluator.GetPhysicalPoint(*transformation, integration_point, x_physical);
const mfem::Vector &x_physical = volume_context.mapping.physical_position;
velocity_element->CalcShape(integration_point, velocity_shape);
position_test_value = 0.0;
@@ -1029,12 +1069,18 @@ TEST_CASE(
const double density_value = density.GetValue(elem_id, integration_point);
local_discrete_action +=
density_value * (position_test_value * centrifugal_acceleration) * context.weight;
local_continuous_action += density_value * (x_physical * centrifugal_acceleration) * context.weight;
local_discrete_action += density_value * (position_test_value * centrifugal_acceleration) *
volume_context.quadrature.weight;
local_continuous_action +=
density_value * (x_physical * centrifugal_acceleration) * volume_context.quadrature.weight;
}
}
MEAN_FIELD_PROFILE_COUNT("centrifugal virial: nodal mapping evaluations", nodal_mapping_evaluations);
MEAN_FIELD_PROFILE_COUNT(
"centrifugal virial: quadrature mapping evaluations", quadrature_mapping_evaluations
);
double global_discrete_action = 0.0;
double global_continuous_action = 0.0;
double global_minimum_determinant = 0.0;
@@ -1054,6 +1100,8 @@ TEST_CASE(
*f.displacement = 0.0;
}
MEAN_FIELD_PROFILE_PRINT(MPI_COMM_WORLD);
for (std::size_t rotation_index = 0; rotation_index < rotation_fractions.size(); ++rotation_index) {
const double error_h = position_errors[rotation_index][0];
const double error_h2 = position_errors[rotation_index][1];