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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user