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

@@ -4,6 +4,7 @@ module;
#include <cstdint>
#include <expected>
#include <limits>
#include <memory>
#include <optional>
#include <stdexcept>
#include <vector>
@@ -14,6 +15,7 @@ export module mean_field:operators.prepared_angular_momentum;
export import :fem;
export import :mapping.domain_mapper;
export import :mapping.prepared_cache;
export import :model.compiled_fixed_angular_momentum;
export import :operators.context.gravity_field;
@@ -188,15 +190,13 @@ export namespace mean_field::operators {
[[nodiscard]] const PreparedAngularMomentumActionStatistics &GetActionStatistics() const noexcept;
[[nodiscard]] const models::CompiledFixedAngularMomentum &GetCompiledConstraint() const noexcept;
private:
struct QuadraturePointData final {
mfem::IntegrationPoint integrationPoint;
mfem::Vector densityShape;
mapping::VolumeMappingContext mappingContext;
double density{0.0};
double cylindricalRadiusSquared{0.0};
};
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
struct ElementPAData final {
int elementId{-1};
mfem::Array<int> densityDofs;
@@ -205,9 +205,14 @@ export namespace mean_field::operators {
mfem::DofTransformation *densityDofTransformation{nullptr};
mfem::DofTransformation *displacementDofTransformation{nullptr};
mfem::DofTransformation *compactificationDofTransformation{nullptr};
const mfem::IntegrationRule *integrationRule{nullptr};
mfem::Vector baseDisplacement;
mfem::Vector compactification;
std::vector<QuadraturePointData> quadraturePoints;
std::shared_ptr<const fem::ScalarReferenceTable> densityBasis;
mapping::VolumeMappingCache mappingContexts;
mfem::Vector density;
mfem::Vector quadratureWeights;
mfem::Vector cylindricalRadiusSquared;
};
void BuildStaticPlan();

View File

@@ -2,6 +2,7 @@ module;
#include <cstdint>
#include <expected>
#include <memory>
#include <mfem.hpp>
#include <vector>
@@ -97,6 +98,12 @@ export namespace mean_field::operators {
[[nodiscard]] const context::barotropic::BarotropicClosurePreparationStatistics &
GetContextPreparationStatistics() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
struct ConstructionData;
@@ -132,8 +139,11 @@ export namespace mean_field::operators {
mfem::DofTransformation *enthalpyDofTransformation{nullptr};
mfem::DofTransformation *displacementDofTransformation{nullptr};
mfem::DenseMatrix densityBasis;
mfem::DenseMatrix enthalpyBasis;
const mfem::IntegrationRule *integrationRule{nullptr};
std::shared_ptr<const fem::ScalarReferenceTable> densityBasis;
std::shared_ptr<const fem::ScalarReferenceTable> enthalpyBasis;
std::shared_ptr<const fem::ScalarReferenceTable> displacementBasis;
mfem::DenseMatrix inverseElementJacobians;
mfem::Vector weightedResidual;
@@ -169,7 +179,6 @@ export namespace mean_field::operators {
mutable mfem::Vector m_elementDisplacementVariation;
mutable mfem::Vector m_quadratureDisplacementAction;
mutable mfem::Vector m_elementDisplacementAction;
mutable mfem::DenseMatrix m_referenceDShape;
mutable mfem::DenseMatrix m_referenceDisplacementJacobian;
std::uint64_t m_preparationCount{0};

View File

@@ -3,6 +3,7 @@ module;
#include <compare>
#include <cstdint>
#include <expected>
#include <memory>
#include <vector>
#include <mfem.hpp>
@@ -14,6 +15,7 @@ export import :mapping.domain_mapper;
export import :operators.context.gravity_field;
export import :operators.kernels.gravity_displacement_force;
export import :utils.blocks;
import :fem.reference_tables;
export namespace mean_field::operators {
struct PreparedGravityDisplacementForceReport final {
@@ -111,6 +113,12 @@ export namespace mean_field::operators {
[[nodiscard]] const context::gravity_field::GravityFieldLinearizationContext &
GetGravityContext() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
void VerifyPrepared() const;
[[nodiscard]] std::expected<
@@ -133,6 +141,10 @@ export namespace mean_field::operators {
mfem::DofTransformation *gravityGradientDofTransformation{nullptr};
mfem::DofTransformation *displacementDofTransformation{nullptr};
const mfem::IntegrationRule *integrationRule{nullptr};
std::shared_ptr<const fem::ScalarReferenceTable> densityReferenceTable;
std::shared_ptr<const fem::ScalarReferenceTable> displacementReferenceTable;
std::shared_ptr<const fem::VectorReferenceTable> gravityReferenceTable;
mfem::DenseMatrix meshPiolaJacobians;
mfem::DenseMatrix mappingJacobians;
mfem::DenseMatrix inverseMeshJacobians;
mfem::DenseMatrix baseGravityReferenceValues;
@@ -164,16 +176,17 @@ export namespace mean_field::operators {
mutable mfem::Vector m_displacementShape;
mutable mfem::Vector m_baseGravityReferenceValue;
mutable mfem::Vector m_gravityVariationReferenceValue;
mutable mfem::Vector m_gravityVariationReferenceCellValue;
mutable mfem::Vector m_mappedBaseGravity;
mutable mfem::Vector m_mappedGravityVariation;
mutable mfem::Vector m_mappedGeometryVariation;
mutable mfem::Vector m_forceValue;
mutable mfem::DenseMatrix m_gravityGradientShape;
mutable mfem::DenseMatrix m_referenceDisplacementDShape;
mutable mfem::DenseMatrix m_referenceDisplacementJacobian;
mutable mfem::DenseMatrix m_displacementJacobianVariation;
mutable mfem::DenseMatrix m_mappingJacobian;
mutable mfem::DenseMatrix m_inverseMeshJacobian;
mutable mfem::DenseMatrix m_meshPiolaJacobian;
std::uint64_t m_residualPreparationCount{0};
mutable std::uint64_t m_residualApplicationCount{0};

View File

@@ -58,6 +58,12 @@ export namespace mean_field::operators {
[[nodiscard]] const field::FieldDofMap &GetPotentialMap() const noexcept;
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.element_id, *data.integration_rule);
}
}
void MultTranspose(
const mfem::Vector &potential,
mfem::Vector &action
@@ -80,6 +86,10 @@ export namespace mean_field::operators {
const mfem::IntegrationRule *integration_rule{nullptr};
// Rows are quadrature points; columns are element DOFs.
std::shared_ptr<const fem::ScalarReferenceTable> density_reference;
std::shared_ptr<const fem::ScalarReferenceTable> potential_reference;
std::shared_ptr<const fem::ScalarReferenceTable> displacement_reference;
// Non-VALUE map types retain their element-dependent physical basis.
mfem::DenseMatrix density_basis;
mfem::DenseMatrix potential_basis;
mfem::DenseMatrix inverse_element_jacobians;
@@ -87,6 +97,14 @@ export namespace mean_field::operators {
// Contains quadrature weight, mesh Jacobian, mapped Jacobian,
// and 4*pi*G.
mfem::Vector quadrature_data;
[[nodiscard]] const mfem::DenseMatrix &GetDensityBasis() const {
return density_reference ? density_reference->GetValues() : density_basis;
}
[[nodiscard]] const mfem::DenseMatrix &GetPotentialBasis() const {
return potential_reference ? potential_reference->GetValues() : potential_basis;
}
};
[[nodiscard]] GravitySourcePreparationResult TryPrepareImpl(
@@ -119,7 +137,6 @@ export namespace mean_field::operators {
mutable mfem::Vector m_element_displacement_variation;
mutable mfem::Vector m_quadrature_variation_action;
mutable mfem::Vector m_element_variation_action;
mutable mfem::DenseMatrix m_reference_displacement_dshape;
mutable mfem::DenseMatrix m_reference_displacement_jacobian;
mfem::Vector m_displacement_true;

View File

@@ -10,6 +10,7 @@ export module mean_field:operators.prepared_hdiv_mass;
export import :fem;
export import :field.mfem;
export import :mapping.domain_mapper;
import :fem.reference_tables;
export namespace mean_field::operators {
enum class HDivMassPreparationRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
@@ -58,6 +59,12 @@ export namespace mean_field::operators {
[[nodiscard]] const field::FieldDofMap &GetFluxMap() const noexcept;
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementVariationData &data : m_variationElements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
enum class PreparationMode : std::uint8_t { primal, linearization };
@@ -71,6 +78,10 @@ export namespace mean_field::operators {
mfem::Vector baseDisplacement;
mfem::Vector compactification;
const mfem::IntegrationRule *integrationRule{nullptr};
std::shared_ptr<const fem::VectorReferenceTable> gravityReferenceTable;
// Fixed computational-mesh Piola factor, separate from J_map.
mfem::DenseMatrix meshPiolaJacobians;
mfem::Vector referenceWeights;
mfem::DenseMatrix frozenMappingData;
};
@@ -112,7 +123,10 @@ export namespace mean_field::operators {
mutable mfem::Vector m_elementDisplacementVariation;
mutable mfem::Vector m_elementVariationAction;
mutable mfem::Vector m_gravityGradientValue;
mutable mfem::Vector m_gravityReferenceCellValue;
mutable mfem::Vector m_referenceCellDual;
mutable mfem::Vector m_massTensorVariationAction;
mutable mfem::DenseMatrix m_meshPiolaJacobian;
mutable mfem::DenseMatrix m_gravityGradientShape;
mutable mfem::DenseMatrix m_massTensorVariation;
std::uint64_t m_preparation_count{0};

View File

@@ -4,6 +4,7 @@ module;
#include <cstddef>
#include <cstdint>
#include <expected>
#include <memory>
#include <optional>
#include <stdexcept>
#include <vector>
@@ -13,7 +14,9 @@ module;
export module mean_field:operators.prepared_hydrostatic_equilibrium;
export import :fem;
export import :fem.reference_tables;
export import :mapping.domain_mapper;
export import :mapping.prepared_cache;
export import :operators.context.hydrostatic_equilibrium;
export import :physics.rigid_rotation;
@@ -216,6 +219,12 @@ export namespace mean_field::operators {
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
struct ElementPAData {
int elementId{-1};
@@ -232,15 +241,23 @@ export namespace mean_field::operators {
const mfem::IntegrationRule *integrationRule{nullptr};
// Rows are quadrature points and columns are element DOFs.
mfem::DenseMatrix enthalpyBasis;
mfem::DenseMatrix gravityPotentialBasis;
// Immutable reference values and gradients are shared by FE/rule.
std::shared_ptr<const fem::ScalarReferenceTable> enthalpyReferenceTable;
std::shared_ptr<const fem::ScalarReferenceTable> gravityPotentialReferenceTable;
[[nodiscard]] const mfem::DenseMatrix &GetEnthalpyBasis() const {
return enthalpyReferenceTable->GetValues();
}
[[nodiscard]] const mfem::DenseMatrix &GetGravityPotentialBasis() const {
return gravityPotentialReferenceTable->GetValues();
}
// Rows are quadrature points and columns are physical components.
mfem::DenseMatrix physicalPositions;
mfem::Vector quadratureWeights;
std::vector<mapping::VolumeMappingContext> baseMappingContexts;
mapping::VolumeMappingCache baseMappingContexts;
std::optional<mapping::ElementDisplacementData> baseDisplacementData;

View File

@@ -3,6 +3,7 @@ module;
#include <compare>
#include <cstdint>
#include <expected>
#include <memory>
#include <mfem.hpp>
#include <optional>
#include <vector>
@@ -11,6 +12,7 @@ export module mean_field:operators.prepared_mass_normalization;
export import :fem;
export import :mapping.domain_mapper;
export import :mapping.prepared_cache;
export import :model.compiled_fixed_mass;
export import :operators.context.gravity_field;
export import :operators.prepared_constraint;
@@ -187,14 +189,13 @@ export namespace mean_field::operators {
[[nodiscard]] const context::gravity_field::GravityFieldLinearizationContext &
GetGravityContext() const noexcept;
private:
struct QuadraturePointData final {
mfem::IntegrationPoint integrationPoint;
mfem::Vector densityShape;
mapping::VolumeMappingContext mappingContext;
double density{0.0};
};
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
struct ElementPAData final {
int elementId{-1};
@@ -206,10 +207,15 @@ export namespace mean_field::operators {
mfem::DofTransformation *displacementDofTransformation{nullptr};
mfem::DofTransformation *compactificationDofTransformation{nullptr};
const mfem::IntegrationRule *integrationRule{nullptr};
mfem::Vector baseDisplacement;
mfem::Vector compactification;
std::vector<QuadraturePointData> quadraturePoints;
std::shared_ptr<const fem::ScalarReferenceTable> densityBasis;
mapping::VolumeMappingCache mappingContexts;
mfem::Vector density;
mfem::Vector quadratureWeights;
};
void BuildStaticPlan();

View File

@@ -4,6 +4,7 @@ module;
#include <cstddef>
#include <cstdint>
#include <expected>
#include <memory>
#include <optional>
#include <vector>
@@ -13,8 +14,10 @@ export module mean_field:operators.prepared_pressure_force;
export import :eos.polytrope;
export import :fem;
export import :fem.reference_tables;
export import :field.mfem;
export import :mapping.domain_mapper;
export import :mapping.prepared_cache;
export import :operators.context.pressure_force;
export import :utils.blocks;
@@ -168,6 +171,12 @@ export namespace mean_field::operators {
[[nodiscard]]
const fem::FEM &GetFEM() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
struct ConstructionData;
@@ -196,10 +205,13 @@ export namespace mean_field::operators {
const mfem::IntegrationRule *integrationRule{nullptr};
/*
* Rows are quadrature points and columns are enthalpy DOFs.
*/
mfem::DenseMatrix enthalpyBasis;
// Immutable reference values and gradients are shared by FE/rule.
std::shared_ptr<const fem::ScalarReferenceTable> enthalpyReferenceTable;
std::shared_ptr<const fem::ScalarReferenceTable> displacementReferenceTable;
[[nodiscard]] const mfem::DenseMatrix &GetEnthalpyBasis() const {
return enthalpyReferenceTable->GetValues();
}
/*
* Each entry is:
@@ -208,11 +220,9 @@ export namespace mean_field::operators {
* x
* physical dimension.
*/
std::vector<mfem::DenseMatrix> referenceTestGradients;
std::vector<mfem::DenseMatrix> physicalTestGradients;
std::vector<mapping::VolumeMappingContext> baseMappingContexts;
mapping::VolumeMappingCache baseMappingContexts;
std::optional<mapping::ElementDisplacementData> baseDisplacementData;

View File

@@ -113,6 +113,12 @@ export namespace mean_field::operators {
[[nodiscard]] const context::rotational_displacement_force::RotationalDisplacementForceLinearizationContext &
GetContext() const noexcept;
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
for (const ElementPAData &data : m_elements) {
visitor(data.elementId, *data.integrationRule);
}
}
private:
void VerifyPrepared() const;
[[nodiscard]] std::expected<

View File

@@ -269,6 +269,10 @@ export namespace mean_field::operators {
[[nodiscard]] const deformation::PreparedDomainDeformationRuntime &GetDomainDeformation() const noexcept;
[[nodiscard]] const mfem::Vector &GetSurfaceDeformationParameters() const;
[[nodiscard]] const mfem::Vector &GetGeneratedVolumeDisplacement() const;
void BuildVolumeDisplacementDirection(
const mfem::Vector &surfaceDeformationDirection,
mfem::Vector &volumeDisplacementDirection
) const;
[[nodiscard]] const mfem::Vector &GetFullMechanicalResidual() const;
[[nodiscard]] const StellarEquilibriumDependencyStamp &GetGeneratedDisplacementDependency() const;

View File

@@ -2785,6 +2785,22 @@ export namespace mean_field::operators {
return *m_physical;
}
void BuildVolumeDisplacementDirection(
const mfem::Vector &stateDirection,
mfem::Vector &volumeDisplacementDirection
) const {
if (stateDirection.Size() != Width()) {
throw std::invalid_argument(
"The prepared stellar-equilibrium root received a state direction with the wrong size."
);
}
const auto rootDirection = m_manifest.directionView(stateDirection);
m_physical->BuildVolumeDisplacementDirection(
rootDirection.block(utils::blocks::surface_deformation_field.parameters_term),
volumeDisplacementDirection
);
}
template <models::ModelSpecification Specification>
requires ModelType::template
containsSpecification<Specification> [[nodiscard]] const auto &GetPreparedContribution() const noexcept {

View File

@@ -298,6 +298,13 @@ export namespace mean_field::equilibrium {
m_preparedOperator.Mult(direction, action);
}
void BuildVolumeDisplacementDirection(
const mfem::Vector &stateDirection,
mfem::Vector &volumeDisplacementDirection
) const {
m_preparedOperator.BuildVolumeDisplacementDirection(stateDirection, volumeDisplacementDirection);
}
private:
[[nodiscard]] static CompiledSurfaceConstraintType CompileSurfaceConstraint(const ModelType &stellarModel) {
return surface::compilePressureSurfaceConstraint<