TetrahedronFEMForceField
Tetrahedral finite elements. Compute Finite Element forces based on tetrahedral elements. Corotational methods are based on a rotation from world-space to material-space.
TetrahedronFEMForceField computes finite element forces using tetrahedral elements for deformable object simulation in SOFA, supporting small and large displacement formulations with corotational methods.
- module
- Sofa.Component.SolidMechanics.FEM.Elastic
- namespace
- sofa::component::solidmechanics::fem::elastic
- include
- sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.h
- inherits
-
- BaseLinearElasticityFEMForceField
- templates
-
- sofa::defaulttype::Vec3Types
- description
Mathematical and Physical Description of TetrahedronFEMForceField Component
Overview
The TetrahedronFEMForceField is a computational model used in solid mechanics simulations, specifically within the Simulation Open-Framework Architecture (SOFA). It employs Finite Element Method (FEM) to compute forces on tetrahedral elements of deformable objects. This component supports both small and large displacements methods, as well as various corotational approaches for handling rotations between world space and material space.
Material Model
The underlying assumption is that the solid object behaves according to a linear elastic model. For an isotropic linear elastic material with Young's modulus $E$ and Poisson’s ratio $
u$, the material stiffness matrix $K$ in terms of Lamé parameters ($ ilde{oldsymbol{C}} = ext{diag}( ilde{oldsymbol{C}}{11}, ilde{oldsymbol{C}}{22}, ilde{oldsymbol{C}}{33}, ilde{oldsymbol{C}}{44})$) is given by:
where $\lambda = E \nu / ((1+\nu)(1-2\nu))$ and $\mu = E/(2(1+
u))$. Here, $\tilde{\boldsymbol{C}}$ is a diagonal matrix representing the material properties in Voigt notation.
Displacement Methods
Small Displacements (Linear)
The small displacements method assumes that deformations are small enough for linear approximations. The strain-displacement relationship is given by:
$$ \boldsymbol{\varepsilon} = \frac{1}{2}(\boldsymbol{\nabla u} + (\boldsymbol{\nabla u})^T) $$where $\boldsymbol{u}$ is the displacement vector and $\boldsymbol{\varepsilon}$ represents the strain tensor.
Large Displacements (Corotational Methods)
The large displacements method can handle significant deformations by rotating between world space and material space. The rotation matrix $R$ aligns the deformed configuration with the initial one, and the strains are computed in this rotated frame:
$$ \boldsymbol{F} = R J $$where $J$ is the deformation gradient in the corotational frame.
Strain-Displacement Matrix ($\mathbf{B}$)
The strain-displacement matrix $B$ links nodal displacements to strains within each tetrahedron. For an element with four vertices, the displacement vector $\boldsymbol{d} \in \mathbb{R}^{12}$ (with 3 components per vertex) and the strain vector $\boldsymbol{\varepsilon} \in \mathbb{R}^6$ are related by:
$$ \boldsymbol{\varepsilon} = B \cdot \boldsymbol{d} $$where $B \in \mathbb{R}^{6 \times 12}$ is the strain-displacement matrix specific to each tetrahedral element.
Stiffness Matrix ($\mathbf{K}$)
The stiffness matrix $K$ for an individual element in corotational methods can be expressed as:
$$ K = R B^T \tilde{C} B R^T $$where $R$ is the rotation matrix, $B$ is the strain-displacement matrix, and $\tilde{C}$ is the material stiffness matrix. For small displacements, the rotation matrix $R$ can be omitted.
Force Computation
The internal forces $\boldsymbol{f}_{int}$ are computed using the stiffness matrices and nodal displacements:
$$ \boldsymbol{f}_{int} = K (\boldsymbol{u}_d - \boldsymbol{u}_0) $$where $\boldsymbol{u}_d$ is the current displacement vector, and $\boldsymbol{u}_0$ represents the initial positions.
Plasticity Model
The component supports plasticity models to simulate irreversible deformation. For instance, a creep factor $\eta$ can be defined as:
$$ \dot{p} = \eta (|\varepsilon_{\text{eff}}| - \sigma_y) $$where $p$ is the accumulated plastic strain, $\eta$ is the creep rate, and $\sigma_y$ is the yield threshold.
Visualization (Von Mises Stress)
The component can compute Von Mises stress for visualization purposes. The von Mises equivalent stress $\sigma_{VM}$ is given by:
$$ \sigma_{VM} = \sqrt{\frac{3}{2}\boldsymbol{s}:\boldsymbol{s}} $$where $s$ is the deviatoric stress tensor.
Summary
The TetrahedronFEMForceField component provides a versatile framework for simulating linear elastic materials using tetrahedral elements. It supports both small and large deformation regimes, with corotational methods to handle rotations accurately. This makes it suitable for applications ranging from biomedical simulations to real-time virtual material handling.
Data Fields
| Name | Type | Default | Help |
|---|---|---|---|
data |
DataTypes | |
|
d_updateStiffnessMatrix |
bool | |
|
d_assembling |
bool | |
|
d_gatherPt |
sofa::helper::OptionsGroup | |
number of dof accumulated per threads during the gather operation (Only use in GPU version) |
d_gatherBsize |
sofa::helper::OptionsGroup | |
number of dof accumulated per threads during the gather operation (Only use in GPU version) |
d_drawHeterogeneousTetra |
bool | |
Draw Heterogeneous Tetra in different color |
d_computeVonMisesStress |
int | |
compute and display von Mises stress: 0: no computations, 1: using corotational strain, 2: using full Green strain. Set listening=1 |
d_showStressAlpha |
float | |
Alpha for vonMises visualisation |
d_showVonMisesStressPerNode |
bool | |
draw points showing vonMises stress interpolated in nodes |
d_showVonMisesStressPerNodeColorMap |
bool | |
draw elements showing vonMises stress interpolated in nodes |
d_showVonMisesStressPerElement |
bool | |
draw triangles showing vonMises stress interpolated in elements |
d_updateStiffness |
bool | |
update structures (precomputed in init) using stiffness parameters in each iteration (set listening=1) |
Methods
int
getRestVolume
()
void
getRotation
(Mat33 & R, int nodeIdx)
void
getRotations
(int & vecR)
void
getRotations
(linearalgebra::BaseMatrix * rotations, int offset)
const int &
getRotations
()
void
setComputeGlobalMatrix
(bool val)
const Transformation &
getActualTetraRotation
(int index)
const Transformation &
getInitialTetraRotation
(int index)
const MaterialStiffness &
getMaterialStiffness
(TetrahedronID tetraId)
const StrainDisplacement &
getStrainDisplacement
(TetrahedronID tetraId)
const int &
getRotatedInitialElements
(TetrahedronID tetraId)
void
setMethod
(int methodName)
void
setUpdateStiffnessMatrix
(bool val)
void
reset
()
void
init
()
void
reinit
()
void
addForce
(const core::MechanicalParams * mparams, int & d_f, const int & d_x, const int & d_v)
void
addDForce
(const core::MechanicalParams * mparams, int & d_df, const int & d_dx)
SReal
getPotentialEnergy
(const core::MechanicalParams * , const int & x)
void
addKToMatrix
(sofa::linearalgebra::BaseMatrix * m, SReal kFactor, unsigned int & offset)
void
buildStiffnessMatrix
(core::behavior::StiffnessMatrix * matrix)
void
buildDampingMatrix
(core::behavior::DampingMatrix * )
void
draw
(const core::visual::VisualParams * vparams)
void
computeBBox
(const core::ExecParams * params, bool onlyVisible)
void
getElementStiffnessMatrix
(int * stiffness, int nodeIdx)
void
computeStrainDisplacement
(StrainDisplacement & J, int a, int b, int c, int d)
int
peudo_determinant_for_coef
(const int & M)
void
computeStiffnessMatrix
(StiffnessMatrix & S, StiffnessMatrix & SR, const MaterialStiffness & K, const StrainDisplacement & J, const Transformation & Rot)
void
computeMaterialStiffness
(int i, int & a, int & b, int & c, int & d)
virtual
void
computeForce
(Displacement & F, const Displacement & Depl, VoigtTensor & plasticStrain, const MaterialStiffness & K, const StrainDisplacement & J)
void
computeForce
(Displacement & F, const Displacement & Depl, const MaterialStiffness & K, const StrainDisplacement & J, SReal fact)
void
initSmall
(int i, int & a, int & b, int & c, int & d)
void
accumulateForceSmall
(int & f, const int & p, int elementIt, int elementIndex)
void
applyStiffnessSmall
(int & f, const int & x, int i, int a, int b, int c, int d, SReal fact)
void
initLarge
(int i, int & a, int & b, int & c, int & d)
void
computeRotationLarge
(Transformation & r, const int & p, const int & a, const int & b, const int & c)
void
accumulateForceLarge
(int & f, const int & p, int elementIt, int elementIndex)
void
initPolar
(int i, int & a, int & b, int & c, int & d)
void
accumulateForcePolar
(int & f, const int & p, int elementIt, int elementIndex)
void
initSVD
(int i, int & a, int & b, int & c, int & d)
void
accumulateForceSVD
(int & f, const int & p, int elementIt, int elementIndex)
void
applyStiffnessCorotational
(int & f, const int & x, int i, int a, int b, int c, int d, SReal fact)
void
handleTopologyChange
()
void
computeVonMisesStress
()
bool
isComputeVonMisesStressMethodSet
()
void
computeMinMaxFromYoungsModulus
()
void
drawTrianglesFromTetrahedra
(const core::visual::VisualParams * vparams, bool showVonMisesStressPerElement, bool drawVonMisesStress, const int & x, const int & youngModulus, bool heterogeneous, int minVM, int maxVM, int vM)
virtual
void
drawTrianglesFromRangeOfTetrahedra
(const int & range, const core::visual::VisualParams * vparams, bool showVonMisesStressPerElement, bool drawVonMisesStress, bool showWireFrame, const int & x, const int & youngModulus, bool heterogeneous, int minVM, int maxVM, int vM)
virtual
void
handleEvent
(core::objectmodel::Event * event)
{
"name": "TetrahedronFEMForceField",
"namespace": "sofa::component::solidmechanics::fem::elastic",
"module": "Sofa.Component.SolidMechanics.FEM.Elastic",
"include": "sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.h",
"doc": "Tetrahedral finite elements.\n\nCompute Finite Element forces based on tetrahedral elements.\n Corotational methods are based on a rotation from world-space to material-space.",
"inherits": [
"BaseLinearElasticityFEMForceField"
],
"templates": [
"sofa::defaulttype::Vec3Types"
],
"data_fields": [
{
"name": "data",
"type": "DataTypes"
},
{
"name": "d_updateStiffnessMatrix",
"type": "bool",
"xmlname": "updateStiffnessMatrix",
"help": ""
},
{
"name": "d_assembling",
"type": "bool",
"xmlname": "computeGlobalMatrix",
"help": ""
},
{
"name": "d_gatherPt",
"type": "sofa::helper::OptionsGroup",
"xmlname": "gatherPt",
"help": "number of dof accumulated per threads during the gather operation (Only use in GPU version)"
},
{
"name": "d_gatherBsize",
"type": "sofa::helper::OptionsGroup",
"xmlname": "gatherBsize",
"help": "number of dof accumulated per threads during the gather operation (Only use in GPU version)"
},
{
"name": "d_drawHeterogeneousTetra",
"type": "bool",
"xmlname": "drawHeterogeneousTetra",
"help": "Draw Heterogeneous Tetra in different color"
},
{
"name": "d_computeVonMisesStress",
"type": "int",
"xmlname": "computeVonMisesStress",
"help": "compute and display von Mises stress: 0: no computations, 1: using corotational strain, 2: using full Green strain. Set listening=1"
},
{
"name": "d_showStressAlpha",
"type": "float",
"xmlname": "showStressAlpha",
"help": "Alpha for vonMises visualisation"
},
{
"name": "d_showVonMisesStressPerNode",
"type": "bool",
"xmlname": "showVonMisesStressPerNode",
"help": "draw points showing vonMises stress interpolated in nodes"
},
{
"name": "d_showVonMisesStressPerNodeColorMap",
"type": "bool",
"xmlname": "showVonMisesStressPerNodeColorMap",
"help": "draw elements showing vonMises stress interpolated in nodes"
},
{
"name": "d_showVonMisesStressPerElement",
"type": "bool",
"xmlname": "showVonMisesStressPerElement",
"help": "draw triangles showing vonMises stress interpolated in elements"
},
{
"name": "d_updateStiffness",
"type": "bool",
"xmlname": "updateStiffness",
"help": "update structures (precomputed in init) using stiffness parameters in each iteration (set listening=1)"
}
],
"links": [],
"methods": [
{
"name": "getRestVolume",
"return_type": "int",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getRotation",
"return_type": "void",
"params": [
{
"name": "R",
"type": "Mat33 &"
},
{
"name": "nodeIdx",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getRotations",
"return_type": "void",
"params": [
{
"name": "vecR",
"type": "int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getRotations",
"return_type": "void",
"params": [
{
"name": "rotations",
"type": "linearalgebra::BaseMatrix *"
},
{
"name": "offset",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getRotations",
"return_type": "const int &",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "setComputeGlobalMatrix",
"return_type": "void",
"params": [
{
"name": "val",
"type": "bool"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getActualTetraRotation",
"return_type": "const Transformation &",
"params": [
{
"name": "index",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getInitialTetraRotation",
"return_type": "const Transformation &",
"params": [
{
"name": "index",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getMaterialStiffness",
"return_type": "const MaterialStiffness &",
"params": [
{
"name": "tetraId",
"type": "TetrahedronID"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getStrainDisplacement",
"return_type": "const StrainDisplacement &",
"params": [
{
"name": "tetraId",
"type": "TetrahedronID"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getRotatedInitialElements",
"return_type": "const int &",
"params": [
{
"name": "tetraId",
"type": "TetrahedronID"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "setMethod",
"return_type": "void",
"params": [
{
"name": "methodName",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "setUpdateStiffnessMatrix",
"return_type": "void",
"params": [
{
"name": "val",
"type": "bool"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "reset",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "init",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "reinit",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "addForce",
"return_type": "void",
"params": [
{
"name": "mparams",
"type": "const core::MechanicalParams *"
},
{
"name": "d_f",
"type": "int &"
},
{
"name": "d_x",
"type": "const int &"
},
{
"name": "d_v",
"type": "const int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "addDForce",
"return_type": "void",
"params": [
{
"name": "mparams",
"type": "const core::MechanicalParams *"
},
{
"name": "d_df",
"type": "int &"
},
{
"name": "d_dx",
"type": "const int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getPotentialEnergy",
"return_type": "SReal",
"params": [
{
"name": "",
"type": "const core::MechanicalParams *"
},
{
"name": "x",
"type": "const int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "addKToMatrix",
"return_type": "void",
"params": [
{
"name": "m",
"type": "sofa::linearalgebra::BaseMatrix *"
},
{
"name": "kFactor",
"type": "SReal"
},
{
"name": "offset",
"type": "unsigned int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "buildStiffnessMatrix",
"return_type": "void",
"params": [
{
"name": "matrix",
"type": "core::behavior::StiffnessMatrix *"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "buildDampingMatrix",
"return_type": "void",
"params": [
{
"name": "",
"type": "core::behavior::DampingMatrix *"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "draw",
"return_type": "void",
"params": [
{
"name": "vparams",
"type": "const core::visual::VisualParams *"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "computeBBox",
"return_type": "void",
"params": [
{
"name": "params",
"type": "const core::ExecParams *"
},
{
"name": "onlyVisible",
"type": "bool"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getElementStiffnessMatrix",
"return_type": "void",
"params": [
{
"name": "stiffness",
"type": "int *"
},
{
"name": "nodeIdx",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "computeStrainDisplacement",
"return_type": "void",
"params": [
{
"name": "J",
"type": "StrainDisplacement &"
},
{
"name": "a",
"type": "int"
},
{
"name": "b",
"type": "int"
},
{
"name": "c",
"type": "int"
},
{
"name": "d",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "peudo_determinant_for_coef",
"return_type": "int",
"params": [
{
"name": "M",
"type": "const int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeStiffnessMatrix",
"return_type": "void",
"params": [
{
"name": "S",
"type": "StiffnessMatrix &"
},
{
"name": "SR",
"type": "StiffnessMatrix &"
},
{
"name": "K",
"type": "const MaterialStiffness &"
},
{
"name": "J",
"type": "const StrainDisplacement &"
},
{
"name": "Rot",
"type": "const Transformation &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeMaterialStiffness",
"return_type": "void",
"params": [
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int &"
},
{
"name": "b",
"type": "int &"
},
{
"name": "c",
"type": "int &"
},
{
"name": "d",
"type": "int &"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeForce",
"return_type": "void",
"params": [
{
"name": "F",
"type": "Displacement &"
},
{
"name": "Depl",
"type": "const Displacement &"
},
{
"name": "plasticStrain",
"type": "VoigtTensor &"
},
{
"name": "K",
"type": "const MaterialStiffness &"
},
{
"name": "J",
"type": "const StrainDisplacement &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeForce",
"return_type": "void",
"params": [
{
"name": "F",
"type": "Displacement &"
},
{
"name": "Depl",
"type": "const Displacement &"
},
{
"name": "K",
"type": "const MaterialStiffness &"
},
{
"name": "J",
"type": "const StrainDisplacement &"
},
{
"name": "fact",
"type": "SReal"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "initSmall",
"return_type": "void",
"params": [
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int &"
},
{
"name": "b",
"type": "int &"
},
{
"name": "c",
"type": "int &"
},
{
"name": "d",
"type": "int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "accumulateForceSmall",
"return_type": "void",
"params": [
{
"name": "f",
"type": "int &"
},
{
"name": "p",
"type": "const int &"
},
{
"name": "elementIt",
"type": "int"
},
{
"name": "elementIndex",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "applyStiffnessSmall",
"return_type": "void",
"params": [
{
"name": "f",
"type": "int &"
},
{
"name": "x",
"type": "const int &"
},
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int"
},
{
"name": "b",
"type": "int"
},
{
"name": "c",
"type": "int"
},
{
"name": "d",
"type": "int"
},
{
"name": "fact",
"type": "SReal"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "initLarge",
"return_type": "void",
"params": [
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int &"
},
{
"name": "b",
"type": "int &"
},
{
"name": "c",
"type": "int &"
},
{
"name": "d",
"type": "int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeRotationLarge",
"return_type": "void",
"params": [
{
"name": "r",
"type": "Transformation &"
},
{
"name": "p",
"type": "const int &"
},
{
"name": "a",
"type": "const int &"
},
{
"name": "b",
"type": "const int &"
},
{
"name": "c",
"type": "const int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "accumulateForceLarge",
"return_type": "void",
"params": [
{
"name": "f",
"type": "int &"
},
{
"name": "p",
"type": "const int &"
},
{
"name": "elementIt",
"type": "int"
},
{
"name": "elementIndex",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "initPolar",
"return_type": "void",
"params": [
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int &"
},
{
"name": "b",
"type": "int &"
},
{
"name": "c",
"type": "int &"
},
{
"name": "d",
"type": "int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "accumulateForcePolar",
"return_type": "void",
"params": [
{
"name": "f",
"type": "int &"
},
{
"name": "p",
"type": "const int &"
},
{
"name": "elementIt",
"type": "int"
},
{
"name": "elementIndex",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "initSVD",
"return_type": "void",
"params": [
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int &"
},
{
"name": "b",
"type": "int &"
},
{
"name": "c",
"type": "int &"
},
{
"name": "d",
"type": "int &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "accumulateForceSVD",
"return_type": "void",
"params": [
{
"name": "f",
"type": "int &"
},
{
"name": "p",
"type": "const int &"
},
{
"name": "elementIt",
"type": "int"
},
{
"name": "elementIndex",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "applyStiffnessCorotational",
"return_type": "void",
"params": [
{
"name": "f",
"type": "int &"
},
{
"name": "x",
"type": "const int &"
},
{
"name": "i",
"type": "int"
},
{
"name": "a",
"type": "int"
},
{
"name": "b",
"type": "int"
},
{
"name": "c",
"type": "int"
},
{
"name": "d",
"type": "int"
},
{
"name": "fact",
"type": "SReal"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "handleTopologyChange",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeVonMisesStress",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "isComputeVonMisesStressMethodSet",
"return_type": "bool",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "computeMinMaxFromYoungsModulus",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "drawTrianglesFromTetrahedra",
"return_type": "void",
"params": [
{
"name": "vparams",
"type": "const core::visual::VisualParams *"
},
{
"name": "showVonMisesStressPerElement",
"type": "bool"
},
{
"name": "drawVonMisesStress",
"type": "bool"
},
{
"name": "x",
"type": "const int &"
},
{
"name": "youngModulus",
"type": "const int &"
},
{
"name": "heterogeneous",
"type": "bool"
},
{
"name": "minVM",
"type": "int"
},
{
"name": "maxVM",
"type": "int"
},
{
"name": "vM",
"type": "int"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "drawTrianglesFromRangeOfTetrahedra",
"return_type": "void",
"params": [
{
"name": "range",
"type": "const int &"
},
{
"name": "vparams",
"type": "const core::visual::VisualParams *"
},
{
"name": "showVonMisesStressPerElement",
"type": "bool"
},
{
"name": "drawVonMisesStress",
"type": "bool"
},
{
"name": "showWireFrame",
"type": "bool"
},
{
"name": "x",
"type": "const int &"
},
{
"name": "youngModulus",
"type": "const int &"
},
{
"name": "heterogeneous",
"type": "bool"
},
{
"name": "minVM",
"type": "int"
},
{
"name": "maxVM",
"type": "int"
},
{
"name": "vM",
"type": "int"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "handleEvent",
"return_type": "void",
"params": [
{
"name": "event",
"type": "core::objectmodel::Event *"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
}
],
"title": "Tetrahedron FEM Force Field",
"category": [
"Solid Mechanics"
],
"briefDescription": "Computes finite element forces based on tetrahedral elements for solid mechanics simulations.",
"description": "This component calculates finite element forces using a tetrahedral mesh for solid object simulation. It implements both small and large displacement formulations, including corotational methods that use rotations to transform between world space and material space.\n\nKey Features:\n- Supports 'small', 'large', 'polar' and 'svd' displacement methods\n- Can compute Von Mises stress for visualization\n- Allows setting local stiffness factors per element \n- Provides accessors for retrieving rotation matrices, stiffness matrices etc. of individual tetrahedra\n- Implements full system matrix assembly support\n- Supports plasticity models like those in \"Interactive Virtual Materials\" paper\n\nThe component computes forces based on a specified material model (linear elasticity by default) and applies them to the deformable object. It can be used for simulating soft tissues, virtual materials etc. in real-time or offline physics simulations.",
"parameters": [
{
"name": "method",
"type": "string",
"defaultValue": "'small'",
"description": "Displacement method: 'small', 'large' (QR), 'polar' or 'svd'"
},
{
"name": "localStiffnessFactor",
"type": "vector<Real>",
"defaultValue": "",
"description": "Allows specifying different stiffness per element"
},
{
"name": "youngModulus",
"type": "Real or vector<Real>",
"defaultValue": "1000.0",
"description": "Young's modulus of the material (or per element)"
},
{
"name": "poissonRatio",
"type": "Real or vector<Real>",
"defaultValue": "0.3",
"description": "Poisson ratio of the material (or per element)"
},
{
"name": "updateStiffnessMatrix",
"type": "bool",
"defaultValue": "false",
"description": "Update stiffness matrices each iteration"
},
{
"name": "assembling",
"type": "bool",
"defaultValue": "false",
"description": "Enable full system matrix assembly support"
},
{
"name": "plasticMaxThreshold",
"type": "Real",
"defaultValue": "0.01",
"description": "Plasticity max threshold (2-norm of strain)"
},
{
"name": "plasticYieldThreshold",
"type": "Real",
"defaultValue": "0.03",
"description": "Plastic yield threshold"
},
{
"name": "plasticCreep",
"type": "Real",
"defaultValue": "1e-4",
"description": "Plastic creep factor [0,1]"
}
],
"inputs": [
{
"name": "position",
"description": "Current positions of the object's points",
"type": "vector<Vec3>"
},
{
"name": "velocity",
"description": "Current velocities of the object's points",
"type": "vector<Vec3>"
}
],
"outputs": [
{
"name": "force",
"description": "Calculated forces applied to each point",
"type": "vector<Vec3>"
}
],
"maths": "## Mathematical and Physical Description of TetrahedronFEMForceField Component\n\n### Overview\nThe **TetrahedronFEMForceField** is a computational model used in solid mechanics simulations, specifically within the Simulation Open-Framework Architecture (SOFA). It employs Finite Element Method (FEM) to compute forces on tetrahedral elements of deformable objects. This component supports both small and large displacements methods, as well as various corotational approaches for handling rotations between world space and material space.\n\n### Material Model\nThe underlying assumption is that the solid object behaves according to a linear elastic model. For an isotropic linear elastic material with Young's modulus $E$ and Poisson’s ratio $\nu$, the material stiffness matrix $K$ in terms of Lamé parameters ($\tilde{\boldsymbol{C}} = \text{diag}(\tilde{\boldsymbol{C}}_{11}, \tilde{\boldsymbol{C}}_{22}, \tilde{\boldsymbol{C}}_{33}, \tilde{\boldsymbol{C}}_{44})$) is given by:\n\n\\[\n \\tilde{\\boldsymbol{C}} =\n \\begin{pmatrix}\n \\lambda + 2\\mu & \\lambda & \\lambda & 0 \\\\\n \\lambda & \\lambda + 2\\mu & \\lambda & 0 \\\\\n \\lambda & \\lambda & \\lambda + 2\\mu & 0 \\\\\n 0 & 0 & 0 & \\mu\n \\end{pmatrix}\n\\]\nwhere $\\lambda = E \\nu / ((1+\\nu)(1-2\\nu))$ and $\\mu = E/(2(1+\nu))$. Here, $\\tilde{\\boldsymbol{C}}$ is a diagonal matrix representing the material properties in Voigt notation.\n\n### Displacement Methods\n#### Small Displacements (Linear)\nThe small displacements method assumes that deformations are small enough for linear approximations. The strain-displacement relationship is given by:\n\n\\[\n \\boldsymbol{\\varepsilon} = \\frac{1}{2}(\\boldsymbol{\\nabla u} + (\\boldsymbol{\\nabla u})^T)\n\\]\nwhere $\\boldsymbol{u}$ is the displacement vector and $\\boldsymbol{\\varepsilon}$ represents the strain tensor.\n\n#### Large Displacements (Corotational Methods)\nThe large displacements method can handle significant deformations by rotating between world space and material space. The rotation matrix $R$ aligns the deformed configuration with the initial one, and the strains are computed in this rotated frame:\n\n\\[\n \\boldsymbol{F} = R J \n\\]\nwhere $J$ is the deformation gradient in the corotational frame.\n\n### Strain-Displacement Matrix ($\\mathbf{B}$)\nThe strain-displacement matrix $B$ links nodal displacements to strains within each tetrahedron. For an element with four vertices, the displacement vector $\\boldsymbol{d} \\in \\mathbb{R}^{12}$ (with 3 components per vertex) and the strain vector $\\boldsymbol{\\varepsilon} \\in \\mathbb{R}^6$ are related by:\n\n\\[\n \\boldsymbol{\\varepsilon} = B \\cdot \\boldsymbol{d}\n\\]\nwhere $B \\in \\mathbb{R}^{6 \\times 12}$ is the strain-displacement matrix specific to each tetrahedral element.\n\n### Stiffness Matrix ($\\mathbf{K}$)\nThe stiffness matrix $K$ for an individual element in corotational methods can be expressed as:\n\n\\[\n K = R B^T \\tilde{C} B R^T \n\\]\nwhere $R$ is the rotation matrix, $B$ is the strain-displacement matrix, and $\\tilde{C}$ is the material stiffness matrix. For small displacements, the rotation matrix $R$ can be omitted.\n\n### Force Computation\nThe internal forces $\\boldsymbol{f}_{int}$ are computed using the stiffness matrices and nodal displacements:\n\n\\[\n \\boldsymbol{f}_{int} = K (\\boldsymbol{u}_d - \\boldsymbol{u}_0)\n\\]\nwhere $\\boldsymbol{u}_d$ is the current displacement vector, and $\\boldsymbol{u}_0$ represents the initial positions.\n\n### Plasticity Model\nThe component supports plasticity models to simulate irreversible deformation. For instance, a creep factor $\\eta$ can be defined as:\n\n\\[\n \\dot{p} = \\eta (|\\varepsilon_{\\text{eff}}| - \\sigma_y)\n\\]\nwhere $p$ is the accumulated plastic strain, $\\eta$ is the creep rate, and $\\sigma_y$ is the yield threshold.\n\n### Visualization (Von Mises Stress)\nThe component can compute Von Mises stress for visualization purposes. The von Mises equivalent stress $\\sigma_{VM}$ is given by:\n\n\\[\n \\sigma_{VM} = \\sqrt{\\frac{3}{2}\\boldsymbol{s}:\\boldsymbol{s}}\n\\]\nwhere $s$ is the deviatoric stress tensor.\n\n### Summary\nThe **TetrahedronFEMForceField** component provides a versatile framework for simulating linear elastic materials using tetrahedral elements. It supports both small and large deformation regimes, with corotational methods to handle rotations accurately. This makes it suitable for applications ranging from biomedical simulations to real-time virtual material handling.",
"abstract": "TetrahedronFEMForceField computes finite element forces using tetrahedral elements for deformable object simulation in SOFA, supporting small and large displacement formulations with corotational methods.",
"sheet": "# TetrahedronFEMForceField\n\n## Overview\nThe **TetrahedronFEMForceField** component calculates finite element forces on tetrahedral elements of deformable objects. It supports both small and large displacement formulations, including corotational methods that handle rotations between world space and material space.\n\n## Mathematical Model\n### Material Model\nFor an isotropic linear elastic material with Young's modulus $E$ and Poisson’s ratio $\nu$, the material stiffness matrix $K$ in terms of Lamé parameters is given by:\n\n\\[\n \\tilde{\\boldsymbol{C}} =\n \\begin{pmatrix}\n \\lambda + 2\\mu & \\lambda & \\lambda & 0 \\\\\n \\lambda & \\lambda + 2\\mu & \\lambda & 0 \\\\\n \\lambda & \\lambda & \\lambda + 2\\mu & 0 \\\\\n 0 & 0 & 0 & \\mu\n \\end{pmatrix}\n\\]\nwhere $\\lambda = E \\nu / ((1+\\nu)(1-2\\nu))$ and $\\mu = E/(2(1+\\nu))$. Here, $\\tilde{\\boldsymbol{C}}$ is a diagonal matrix representing the material properties in Voigt notation.\n\n### Displacement Methods\n#### Small Displacements (Linear)\nThe small displacements method assumes that deformations are small enough for linear approximations. The strain-displacement relationship is given by:\n\n\\[\n \\boldsymbol{\\varepsilon} = \\frac{1}{2}(\\boldsymbol{\\nabla u} + (\\boldsymbol{\\nabla u})^T)\n\\]\nwhere $\\boldsymbol{u}$ is the displacement vector and $\\boldsymbol{\\varepsilon}$ represents the strain tensor.\n\n#### Large Displacements (Corotational Methods)\nThe large displacements method can handle significant deformations by rotating between world space and material space. The rotation matrix $R$ aligns the deformed configuration with the initial one, and the strains are computed in this rotated frame:\n\n\\[\n \\boldsymbol{F} = R J \n\\]\nwhere $J$ is the deformation gradient in the corotational frame.\n\n### Strain-Displacement Matrix ($B$)\nThe strain-displacement matrix $B$ links nodal displacements to strains within each tetrahedron. For an element with four vertices, the displacement vector $d \\in \\mathbb{R}^{12}$ (with 3 components per vertex) and the strain vector $\\boldsymbol{\\varepsilon} \\in \\mathbb{R}^6$ are related by:\n\n\\[\n \\boldsymbol{\\varepsilon} = B \\cdot d\n\\]\nwhere $B \\in \\mathbb{R}^{6 \\times 12}$ is the strain-displacement matrix specific to each tetrahedral element.\n\n### Stiffness Matrix ($K$)\nThe stiffness matrix $K$ for an individual element in corotational methods can be expressed as:\n\n\\[\n K = R B^T \\tilde{C} B R^T \n\\]\nwhere $R$ is the rotation matrix, $B$ is the strain-displacement matrix, and $\\tilde{C}$ is the material stiffness matrix. For small displacements, the rotation matrix $R$ can be omitted.\n\n### Force Computation\nThe internal forces $f_{int}$ are computed using the stiffness matrices and nodal displacements:\n\n\\[\n f_{int} = K (u_d - u_0)\n\\]\nwhere $u_d$ is the current displacement vector, and $u_0$ represents the initial positions.\n\n### Visualization (Von Mises Stress)\nThe component can compute Von Mises stress for visualization purposes. The von Mises equivalent stress $\\sigma_{VM}$ is given by:\n\n\\[\n \\sigma_{VM} = \\sqrt{\\frac{3}{2}s:s}\n\\]\nwhere $s$ is the deviatoric stress tensor.\n\n## Parameters and Data\n- **updateStiffnessMatrix**: Boolean to update stiffness matrix (default: false).\n- **computeGlobalMatrix**: Boolean to compute global matrix (default: false).\n- **gatherPt**: Number of degrees of freedom accumulated per thread during gather operation (GPU version only).\n- **gatherBsize**: Number of degrees of freedom accumulated per thread during gather operation (GPU version only).\n- **drawHeterogeneousTetra**: Boolean to draw heterogeneous tetrahedra in different colors.\n- **computeVonMisesStress**: Integer to compute and display von Mises stress: 0 - no computations, 1 - using corotational strain, 2 - using full Green strain (default: 0).\n- **showStressAlpha**: Alpha for von Mises visualisation.\n- **showVonMisesStressPerNode**: Boolean to draw points showing von Mises stress interpolated in nodes.\n- **showVonMisesStressPerNodeColorMap**: Boolean to draw elements showing von Mises stress interpolated in nodes.\n- **showVonMisesStressPerElement**: Boolean to draw triangles showing von Mises stress interpolated in elements.\n- **updateStiffness**: Boolean to update structures using stiffness parameters (default: false)."
}