perf(allocations): reduced overall allocations by 95%, increaseed jacobian applicatin by 2x

This commit uses global pre allocated work space to dramatically reduce memory usage and allocation time
This commit is contained in:
2026-09-10 06:50:56 -04:00
parent b3c04d507a
commit 75cc638739
66 changed files with 207183 additions and 99552 deletions

View File

@@ -182,19 +182,17 @@ namespace {
.displacement = *m_displacement_data, .compactification = *m_compactification_data
};
mean_field::mapping::VolumeMappingContext mapping_context;
const mean_field::mapping::MappingStatus status = m_domain_mapper.EvaluateVolume(
mapping_data, transformation, integration_point, m_workspace, mapping_context
mapping_data, transformation, integration_point, m_workspace, m_mapping_context
);
if (status != mean_field::mapping::MappingStatus::valid) {
m_mappingFailure = status;
return 0.0;
}
const double mapping_determinant = mapping_context.mapping.mapping_determinant;
const double mapping_determinant = m_mapping_context.mapping.mapping_determinant;
m_inverse_element_jacobian = mapping_context.quadrature.J_inv;
m_inverse_element_jacobian = m_mapping_context.quadrature.J_inv;
const double value = 4.0 * std::numbers::pi * mean_field::utils::G * mapping_determinant;
if (!std::isfinite(value)) {
@@ -269,6 +267,7 @@ namespace {
std::unique_ptr<mean_field::mapping::ElementCompactificationData> m_compactification_data;
mean_field::mapping::DomainMapper::Workspace m_workspace;
mean_field::mapping::VolumeMappingContext m_mapping_context;
mfem::DenseMatrix m_inverse_element_jacobian;
int m_cached_element_id{-1};
mean_field::mapping::MappingStatus m_mappingFailure{mean_field::mapping::MappingStatus::valid};
@@ -394,8 +393,8 @@ namespace mean_field::operators {
m_has_variation_data = false;
m_displacement_true.SetSize(m_displacement_map.full_size());
m_displacement_map.scatter(displacement, m_displacement_true);
m_elements.clear();
m_elements.reserve(m_fem.mesh->GetNE());
std::size_t prepared_element_count{0};
FrozenMappedGravitySourceCoefficient source_coefficient(m_fem, m_domain_mapper, m_displacement_true);
bool localNonFiniteQuadrature = false;
@@ -407,8 +406,10 @@ namespace mean_field::operators {
continue;
}
m_elements.emplace_back();
ElementPAData &data = m_elements.back();
if (prepared_element_count == m_elements.size()) {
m_elements.emplace_back();
}
ElementPAData &data = m_elements[prepared_element_count++];
data.element_id = element_id;
@@ -438,37 +439,59 @@ namespace mean_field::operators {
const int potential_dof_count = potential_element.GetDof();
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
if (density_element.GetMapType() == mfem::FiniteElement::VALUE) {
data.density_reference = m_fem.GetReferenceTables().GetScalarTable(density_element, integration_rule);
data.density_basis.SetSize(0, 0);
} else {
data.density_reference.reset();
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
}
if (potential_element.GetMapType() == mfem::FiniteElement::VALUE) {
data.potential_reference =
m_fem.GetReferenceTables().GetScalarTable(potential_element, integration_rule);
data.potential_basis.SetSize(0, 0);
} else {
data.potential_reference.reset();
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
}
const int dimension = m_fem.mesh->Dimension();
if (mode == PreparationMode::linearization) {
data.inverse_element_jacobians.SetSize(quadrature_point_count, dimension * dimension);
data.displacement_reference = m_fem.GetReferenceTables().GetScalarTable(
*m_fem.displacementFes->GetFE(element_id), integration_rule
);
}
data.quadrature_data.SetSize(quadrature_point_count);
mfem::Vector density_shape(density_dof_count);
mfem::Vector potential_shape(potential_dof_count);
mfem::Vector density_shape;
mfem::Vector potential_shape;
if (!data.density_reference) {
density_shape.SetSize(density_dof_count);
}
if (!data.potential_reference) {
potential_shape.SetSize(potential_dof_count);
}
for (int quadrature_point = 0; quadrature_point < quadrature_point_count; ++quadrature_point) {
const mfem::IntegrationPoint &integration_point = integration_rule.IntPoint(quadrature_point);
transformation.SetIntPoint(&integration_point);
// CalcPhysShape matches the scalar mixed-mass discretization,
// including the finite-element map type.
density_element.CalcPhysShape(transformation, density_shape);
potential_element.CalcPhysShape(transformation, potential_shape);
for (int i = 0; i < density_dof_count; ++i) {
data.density_basis(quadrature_point, i) = density_shape(i);
// VALUE maps use the shared reference basis. Preserve the
// physical-shape evaluation for every other scalar map type.
if (!data.density_reference) {
density_element.CalcPhysShape(transformation, density_shape);
for (int i = 0; i < density_dof_count; ++i) {
data.density_basis(quadrature_point, i) = density_shape(i);
}
}
for (int i = 0; i < potential_dof_count; ++i) {
data.potential_basis(quadrature_point, i) = potential_shape(i);
if (!data.potential_reference) {
potential_element.CalcPhysShape(transformation, potential_shape);
for (int i = 0; i < potential_dof_count; ++i) {
data.potential_basis(quadrature_point, i) = potential_shape(i);
}
}
const double coefficient_value = source_coefficient.Eval(transformation, integration_point);
@@ -505,6 +528,7 @@ namespace mean_field::operators {
break;
}
}
m_elements.resize(prepared_element_count);
const bool localNonFiniteArithmetic = source_coefficient.HasNonFiniteArithmetic() || localNonFiniteQuadrature;
auto preparationResult = synchronize_preparation_failure(
@@ -555,7 +579,7 @@ namespace mean_field::operators {
m_quadrature_action.SetSize(data.quadrature_data.Size());
// B_density * x_e
data.density_basis.Mult(m_element_input, m_quadrature_action);
data.GetDensityBasis().Mult(m_element_input, m_quadrature_action);
// D * B_density * x_e
for (int q = 0; q < m_quadrature_action.Size(); ++q) {
@@ -565,7 +589,7 @@ namespace mean_field::operators {
m_element_action.SetSize(data.potential_dofs.Size());
// B_potential^T * D * B_density * x_e
data.potential_basis.MultTranspose(m_quadrature_action, m_element_action);
data.GetPotentialBasis().MultTranspose(m_quadrature_action, m_element_action);
if (data.potential_dof_transformation != nullptr) {
data.potential_dof_transformation->TransformDual(m_element_action);
@@ -641,15 +665,15 @@ namespace mean_field::operators {
"Prepared gravity source inverse-Jacobian data has an incompatible size."
);
m_reference_displacement_dshape.SetSize(displacement_element.GetDof(), dimension);
m_reference_displacement_jacobian.SetSize(dimension, dimension);
m_quadrature_variation_action.SetSize(data.integration_rule->GetNPoints());
data.density_basis.Mult(m_element_density, m_quadrature_variation_action);
data.GetDensityBasis().Mult(m_element_density, m_quadrature_variation_action);
for (int quadrature_point = 0; quadrature_point < data.integration_rule->GetNPoints(); ++quadrature_point) {
const mfem::IntegrationPoint &integration_point = data.integration_rule->IntPoint(quadrature_point);
displacement_element.CalcDShape(integration_point, m_reference_displacement_dshape);
mfem::MultAtB(direction_dofs, m_reference_displacement_dshape, m_reference_displacement_jacobian);
mfem::MultAtB(
direction_dofs, data.displacement_reference->GetGradients(quadrature_point),
m_reference_displacement_jacobian
);
double logarithmic_jacobian_variation{0.0};
for (int row = 0; row < dimension; ++row) {
@@ -669,7 +693,7 @@ namespace mean_field::operators {
}
m_element_variation_action.SetSize(data.potential_dofs.Size());
data.potential_basis.MultTranspose(m_quadrature_variation_action, m_element_variation_action);
data.GetPotentialBasis().MultTranspose(m_quadrature_variation_action, m_element_variation_action);
if (data.potential_dof_transformation != nullptr) {
data.potential_dof_transformation->TransformDual(m_element_variation_action);
@@ -714,7 +738,7 @@ namespace mean_field::operators {
m_quadrature_action.SetSize(data.quadrature_data.Size());
data.potential_basis.Mult(m_element_input, m_quadrature_action);
data.GetPotentialBasis().Mult(m_element_input, m_quadrature_action);
for (int q = 0; q < m_quadrature_action.Size(); ++q) {
m_quadrature_action(q) *= data.quadrature_data(q);
@@ -722,7 +746,7 @@ namespace mean_field::operators {
m_element_action.SetSize(data.density_dofs.Size());
data.density_basis.MultTranspose(m_quadrature_action, m_element_action);
data.GetDensityBasis().MultTranspose(m_quadrature_action, m_element_action);
if (data.density_dof_transformation != nullptr) {
data.density_dof_transformation->TransformDual(m_element_action);