diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.h index 1a980373a5e..26b4ffadd93 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.h @@ -55,6 +55,10 @@ class BaseElementLinearFEMForceField : public sofa::component::solidmechanics::f using StrainDisplacement = typename trait::StrainDisplacement; using Real = typename trait::Real; +public: + using AssembledStiffnessMatrix = sofa::type::Mat< + trait::NumberOfDofsInElement, trait::NumberOfDofsInElement, Real>; + protected: BaseElementLinearFEMForceField(); @@ -70,6 +74,14 @@ class BaseElementLinearFEMForceField : public sofa::component::solidmechanics::f * List of precomputed element stiffness matrices */ sofa::Data > d_elementStiffness; + + /** + * Contiguous buffer of assembled stiffness matrices (one per element). + * Extracted from d_elementStiffness for cache-friendly access in the hot path. + * This avoids loading the full FactorizedElementStiffness struct (~15 KB per element) + * when only the assembled matrix (~4.6 KB) is needed. + */ + sofa::type::vector m_assembledStiffnessMatrices; }; #if !defined(ELASTICITY_COMPONENT_BASE_ELEMENT_LINEAR_FEM_FORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.inl index de380c5e4cc..e7827cfc55e 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/BaseElementLinearFEMForceField.inl @@ -100,6 +100,13 @@ void BaseElementLinearFEMForceField::precomputeElementSt const std::array, trait::NumberOfNodesInElement> nodesCoordinates = extractNodesVectorFromGlobalVector(element, restPositionAccessor.ref()); elementStiffness[elementId] = integrate(nodesCoordinates, elasticityTensor); }); + + // Extract assembled matrices into a contiguous buffer for cache-friendly access + m_assembledStiffnessMatrices.resize(elements.size()); + for (std::size_t i = 0; i < elements.size(); ++i) + { + m_assembledStiffnessMatrices[i] = elementStiffness[i].getAssembledMatrix(); + } } } diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementCorotationalFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementCorotationalFEMForceField.inl index a3a74a36a81..0298f2e4247 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementCorotationalFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementCorotationalFEMForceField.inl @@ -86,7 +86,7 @@ void ElementCorotationalFEMForceField::computeElementsFo { const auto& elements = trait::FiniteElement::getElementSequence(*this->l_topology); auto restPositionAccessor = this->mstate->readRestPositions(); - auto elementStiffness = sofa::helper::getReadAccessor(this->d_elementStiffness); + const auto& assembledMatrices = this->m_assembledStiffnessMatrices; for (std::size_t elementId = range.start; elementId < range.end; ++elementId) { @@ -112,7 +112,7 @@ void ElementCorotationalFEMForceField::computeElementsFo transformedDisplacement = elementRotation.multTranspose(elementNodesCoordinates[j] - t) - (restElementNodesCoordinates[j] - t0); } - const auto& stiffnessMatrix = elementStiffness[elementId]; + const auto& stiffnessMatrix = assembledMatrices[elementId]; auto& elementForce = elementForces[elementId]; elementForce = stiffnessMatrix * displacement; @@ -134,7 +134,7 @@ void ElementCorotationalFEMForceField::computeElementsFo const sofa::VecDeriv_t& nodeDx) { const auto& elements = trait::FiniteElement::getElementSequence(*this->l_topology); - auto elementStiffness = sofa::helper::getReadAccessor(this->d_elementStiffness); + const auto& assembledMatrices = this->m_assembledStiffnessMatrices; for (std::size_t elementId = range.start; elementId < range.end; ++elementId) { @@ -150,7 +150,7 @@ void ElementCorotationalFEMForceField::computeElementsFo rotated_dx = elementRotation.multTranspose(nodeDx[element[n]]); } - const auto& stiffnessMatrix = elementStiffness[elementId]; + const auto& stiffnessMatrix = assembledMatrices[elementId]; auto& df = elementForcesDeriv[elementId]; df = stiffnessMatrix * element_dx; diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementLinearSmallStrainFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementLinearSmallStrainFEMForceField.inl index fc58db7abe4..191de07c12c 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementLinearSmallStrainFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/ElementLinearSmallStrainFEMForceField.inl @@ -49,12 +49,12 @@ void ElementLinearSmallStrainFEMForceField::computeEleme { const auto& elements = trait::FiniteElement::getElementSequence(*this->l_topology); auto restPositionAccessor = this->mstate->readRestPositions(); - auto elementStiffness = sofa::helper::getReadAccessor(this->d_elementStiffness); + const auto& assembledMatrices = this->m_assembledStiffnessMatrices; for (std::size_t elementId = range.start; elementId < range.end; ++elementId) { const auto& element = elements[elementId]; - const auto& stiffnessMatrix = elementStiffness[elementId]; + const auto& stiffnessMatrix = assembledMatrices[elementId]; typename trait::ElementDisplacement displacement{ sofa::type::NOINIT }; @@ -79,12 +79,12 @@ void ElementLinearSmallStrainFEMForceField::computeEleme const sofa::VecDeriv_t& nodeDx) { const auto& elements = trait::FiniteElement::getElementSequence(*this->l_topology); - auto elementStiffness = sofa::helper::getReadAccessor(this->d_elementStiffness); + const auto& assembledMatrices = this->m_assembledStiffnessMatrices; for (std::size_t elementId = range.start; elementId < range.end; ++elementId) { const auto& element = elements[elementId]; - const auto& stiffnessMatrix = elementStiffness[elementId]; + const auto& stiffnessMatrix = assembledMatrices[elementId]; const std::array, trait::NumberOfNodesInElement> elementNodesDx = extractNodesVectorFromGlobalVector(element, nodeDx); diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FEMForceField.inl index 41b436a3ca2..656ffc47d92 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FEMForceField.inl @@ -208,7 +208,7 @@ template sofa::simulation::ForEachExecutionPolicy FEMForceField::getExecutionPolicy( const sofa::Data& strategy) const { - auto computeForceStrategyAccessor = sofa::helper::getReadAccessor(d_computeForceStrategy); + auto computeForceStrategyAccessor = sofa::helper::getReadAccessor(strategy); const auto& computeForceStrategy = computeForceStrategyAccessor->key(); return (computeForceStrategy == parallelComputeStrategy)