JointSpringForceField
Springs for Rigids. JointSpringForceField simulates 6D springs between Rigid DOFS Use kst vector to specify the directionnal stiffnesses (on each local axe) Use ksr vector to specify the rotational stiffnesses (on each local axe)
`JointSpringForceField` simulates 6D springs between rigid bodies in SOFA, providing both translational and rotational stiffnesses.
- module
- Sofa.Component.SolidMechanics.Spring
- namespace
- sofa::component::solidmechanics::spring
- include
- sofa/component/solidmechanics/spring/JointSpringForceField.h
- inherits
-
- PairInteractionForceField
- templates
-
- sofa::defaulttype::Rigid3Types
- description
Governing Equations and Operators
The JointSpringForceField in the SOFA framework simulates 6D springs between rigid bodies, providing both translational and rotational stiffnesses. This component contributes to the following key operators:
- Internal Force $\mathbf{f}_{int}$
- Residual $R(x)$
- Tangent Stiffness Matrix $K(x)$
Internal Forces and Torques
The internal force and torque contributions are computed based on the displacement and rotation differences between connected rigid bodies. The equations for translational and rotational forces/torques can be summarized as follows:
- *Translational Force:
where:
- $K_T$: Translational stiffness matrix
- $(\mathbf{x}_2 - \mathbf{x}_1)$: Displacement vector between the rigid bodies
- $\Delta_x$: Initial rest position displacement
- $\mathbf{k_d}$: Damping coefficient
- *Rotational Torque:
where:
- $K_R$: Rotational stiffness matrix
- $(\mathbf{q}_2 \cdot \mathbf{q}_1^{-1})$: Rotation difference between the rigid bodies
- $\Delta_q$: Initial rest rotation difference
- $\mathbf{k_d}$: Damping coefficient
The total force and torque contributions are then added to the global internal forces vector:
$$\mathbf{f}_{int} = \begin{pmatrix} \mathbf{f}_T \\ \mathbf{f}_R \end{pmatrix}$$Residual Calculation
The residual for the system, which is used in nonlinear solution methods such as Newton-Raphson, is defined by:
$$R(x) = M \frac{x_{n+1} - x_n}{\Delta t} + f_{int}(x_{n+1}) - f_{ext}$$where:
- $M$: Mass matrix (for rigid bodies, often the identity matrix)
- $f_{int}$: Internal forces and torques
- $f_{ext}$: External forces and torques applied to the system
Tangent Stiffness Matrix
The tangent stiffness matrix $K(x)$, which is used in Newton-Raphson iterations, linearizes the internal force contributions with respect to displacements:
$$K(x) = \frac{1}{\Delta t} M - K_{int}(x)$$where $K_{int}(x)$ represents the tangent stiffness of the spring system.
Constitutive and Kinematic Laws
The JointSpringForceField component implements a nonlinear kinematic law for rigid body interactions. The following aspects are notable:
- Stiffness Matrices $K_T$ and $K_R$:
- These matrices encode the stiffness coefficients along each local axis, both translational ($kst$) and rotational ($ksr$).
-
The spring behavior can be characterized as soft or hard depending on the specified stiffness values.
-
Limit Angles:
- Angular limits are defined for rotational degrees of freedom to restrict movement beyond predefined angles. This is achieved by projecting torsions to lawful parts based on limit angles.
Role in FEM Pipeline
The JointSpringForceField fits into the global FEM pipeline as follows:
- Assembly Phase:
- The internal forces $f_{int}$ and torques are computed for each spring connecting rigid bodies during assembly.
-
These contributions are aggregated to form the global residual vector $R(x)$.
-
Time Integration:
-
Implicit time integration schemes such as Backward Euler can be employed, where the internal forces contribute to the nonlinear system of equations.
-
Nonlinear Solution:
-
The tangent stiffness matrix is computed and used in Newton-Raphson iterations to solve for displacements at each timestep.
-
Linear Solve:
- Linear systems are solved iteratively or directly based on the stiffness contributions from this component.
Numerical Methods and Discretization Choices
-
Pairwise Interaction Force Calculation: The
addSpringForcemethod computes force contributions for each spring using specified stiffnesses, damping, and displacement differences. This is performed in a pairwise fashion for rigid bodies. -
Stiffness Contribution: The
addSpringDForcemethod calculates the incremental forces due to changes in displacements ($dx$), which form part of the tangent stiffness matrix.
Variational/Lagrangian Mechanics Framework Fit
The component fits into a variational framework by:
-
Variational Principle: The internal forces are derived from potential energy differences, consistent with the Lagrangian formulation where the Euler-Lagrange equations govern the motion of rigid bodies connected by springs.
-
Weak Formulation: Although explicit in this case due to the simplicity of rigid body interactions, the internal force contributions implicitly stem from a weak form discretization principle.
Data Fields
| Name | Type | Default | Help |
|---|---|---|---|
data |
DataTypes | |
|
d_period |
Real | |
period between outputs |
d_reinit |
bool | |
flag enabling reinitialization of the output file at each timestep |
d_showLawfulTorsion |
bool | |
display the lawful part of the joint rotation |
d_showExtraTorsion |
bool | |
display the illicit part of the joint rotation |
d_showFactorSize |
Real | |
modify the size of the debug information of a given factor |
Methods
void
addSpringForce
(SReal & potentialEnergy, VecDeriv & f1, const VecCoord & p1, const VecDeriv & v1, VecDeriv & f2, const VecCoord & p2, const VecDeriv & v2, int i, Spring & spring)
void
addSpringDForce
(VecDeriv & df1, const VecDeriv & dx1, VecDeriv & df2, const VecDeriv & dx2, int i, Spring & spring, Real kFactor)
void
projectTorsion
(Spring & spring)
void
init
()
void
bwdInit
()
void
draw
(const core::visual::VisualParams * vparams)
void
computeBBox
(const core::ExecParams * params, bool )
void
addForce
(const core::MechanicalParams * mparams, DataVecDeriv & data_f1, DataVecDeriv & data_f2, const DataVecCoord & data_x1, const DataVecCoord & data_x2, const DataVecDeriv & data_v1, const DataVecDeriv & data_v2)
void
addDForce
(const core::MechanicalParams * mparams, DataVecDeriv & data_df1, DataVecDeriv & data_df2, const DataVecDeriv & data_dx1, const DataVecDeriv & data_dx2)
void
buildDampingMatrix
(core::behavior::DampingMatrix * )
SReal
getPotentialEnergy
(const core::MechanicalParams * , const DataVecCoord & , const DataVecCoord & )
core::behavior::MechanicalState<DataTypes> *
getObject1
()
core::behavior::MechanicalState<DataTypes> *
getObject2
()
int *
getSprings
()
void
clear
(int reserve)
void
addSpring
(const Spring & s)
void
addSpring
(int m1, int m2, Real softKst, Real hardKst, Real softKsr, Real hardKsr, Real blocKsr, Real axmin, Real axmax, Real aymin, Real aymax, Real azmin, Real azmax, Real kd)
{
"name": "JointSpringForceField",
"namespace": "sofa::component::solidmechanics::spring",
"module": "Sofa.Component.SolidMechanics.Spring",
"include": "sofa/component/solidmechanics/spring/JointSpringForceField.h",
"doc": "Springs for Rigids.\n\nJointSpringForceField simulates 6D springs between Rigid DOFS\n Use kst vector to specify the directionnal stiffnesses (on each local axe)\n Use ksr vector to specify the rotational stiffnesses (on each local axe)",
"inherits": [
"PairInteractionForceField"
],
"templates": [
"sofa::defaulttype::Rigid3Types"
],
"data_fields": [
{
"name": "data",
"type": "DataTypes"
},
{
"name": "d_period",
"type": "Real",
"xmlname": "period",
"help": "period between outputs"
},
{
"name": "d_reinit",
"type": "bool",
"xmlname": "reinit",
"help": "flag enabling reinitialization of the output file at each timestep"
},
{
"name": "d_showLawfulTorsion",
"type": "bool",
"xmlname": "showLawfulTorsion",
"help": "display the lawful part of the joint rotation"
},
{
"name": "d_showExtraTorsion",
"type": "bool",
"xmlname": "showExtraTorsion",
"help": "display the illicit part of the joint rotation"
},
{
"name": "d_showFactorSize",
"type": "Real",
"xmlname": "showFactorSize",
"help": "modify the size of the debug information of a given factor"
}
],
"links": [],
"methods": [
{
"name": "addSpringForce",
"return_type": "void",
"params": [
{
"name": "potentialEnergy",
"type": "SReal &"
},
{
"name": "f1",
"type": "VecDeriv &"
},
{
"name": "p1",
"type": "const VecCoord &"
},
{
"name": "v1",
"type": "const VecDeriv &"
},
{
"name": "f2",
"type": "VecDeriv &"
},
{
"name": "p2",
"type": "const VecCoord &"
},
{
"name": "v2",
"type": "const VecDeriv &"
},
{
"name": "i",
"type": "int"
},
{
"name": "spring",
"type": "Spring &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "addSpringDForce",
"return_type": "void",
"params": [
{
"name": "df1",
"type": "VecDeriv &"
},
{
"name": "dx1",
"type": "const VecDeriv &"
},
{
"name": "df2",
"type": "VecDeriv &"
},
{
"name": "dx2",
"type": "const VecDeriv &"
},
{
"name": "i",
"type": "int"
},
{
"name": "spring",
"type": "Spring &"
},
{
"name": "kFactor",
"type": "Real"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "projectTorsion",
"return_type": "void",
"params": [
{
"name": "spring",
"type": "Spring &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "protected"
},
{
"name": "init",
"return_type": "void",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "bwdInit",
"return_type": "void",
"params": [],
"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": "",
"type": "bool"
}
],
"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": "data_f1",
"type": "DataVecDeriv &"
},
{
"name": "data_f2",
"type": "DataVecDeriv &"
},
{
"name": "data_x1",
"type": "const DataVecCoord &"
},
{
"name": "data_x2",
"type": "const DataVecCoord &"
},
{
"name": "data_v1",
"type": "const DataVecDeriv &"
},
{
"name": "data_v2",
"type": "const DataVecDeriv &"
}
],
"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": "data_df1",
"type": "DataVecDeriv &"
},
{
"name": "data_df2",
"type": "DataVecDeriv &"
},
{
"name": "data_dx1",
"type": "const DataVecDeriv &"
},
{
"name": "data_dx2",
"type": "const DataVecDeriv &"
}
],
"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": "getPotentialEnergy",
"return_type": "SReal",
"params": [
{
"name": "",
"type": "const core::MechanicalParams *"
},
{
"name": "",
"type": "const DataVecCoord &"
},
{
"name": "",
"type": "const DataVecCoord &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getObject1",
"return_type": "core::behavior::MechanicalState<DataTypes> *",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getObject2",
"return_type": "core::behavior::MechanicalState<DataTypes> *",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "getSprings",
"return_type": "int *",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "clear",
"return_type": "void",
"params": [
{
"name": "reserve",
"type": "int"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "addSpring",
"return_type": "void",
"params": [
{
"name": "s",
"type": "const Spring &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "addSpring",
"return_type": "void",
"params": [
{
"name": "m1",
"type": "int"
},
{
"name": "m2",
"type": "int"
},
{
"name": "softKst",
"type": "Real"
},
{
"name": "hardKst",
"type": "Real"
},
{
"name": "softKsr",
"type": "Real"
},
{
"name": "hardKsr",
"type": "Real"
},
{
"name": "blocKsr",
"type": "Real"
},
{
"name": "axmin",
"type": "Real"
},
{
"name": "axmax",
"type": "Real"
},
{
"name": "aymin",
"type": "Real"
},
{
"name": "aymax",
"type": "Real"
},
{
"name": "azmin",
"type": "Real"
},
{
"name": "azmax",
"type": "Real"
},
{
"name": "kd",
"type": "Real"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
}
],
"description": "The `JointSpringForceField` is a SOFA component that simulates 6D springs between rigid degrees-of-freedom (DOFs). It inherits from the `PairInteractionForceField` and supports both directional and rotational stiffnesses defined on each local axis. This component allows for the specification of soft and hard stiffness values, as well as damping coefficients and limits on joint rotations.\n\nIt interacts with other components through methods like `addSpringForce`, `addSpringDForce`, which handle force and torque calculations based on specified spring properties and displacements between connected rigid bodies. The `draw` method enables visual debugging of the springs by drawing lines and arrows representing lawful and illicit torsions. \n\nUsage involves defining directional stiffnesses (`kst`) and rotational stiffnesses (`ksr`). Additional data fields like `d_period`, `d_reinit`, `d_showLawfulTorsion`, `d_showExtraTorsion`, and `d_showFactorSize` allow for customization of output file periods, reinitialization flags, and visualization settings.",
"maths": "### Governing Equations and Operators\n\nThe `JointSpringForceField` in the SOFA framework simulates 6D springs between rigid bodies, providing both translational and rotational stiffnesses. This component contributes to the following key operators:\n\n- **Internal Force** \\(\\mathbf{f}_{int}\\)\n- **Residual** \\(R(x)\\)\n- **Tangent Stiffness Matrix** \\(K(x)\\)\n\n#### Internal Forces and Torques\n\nThe internal force and torque contributions are computed based on the displacement and rotation differences between connected rigid bodies. The equations for translational and rotational forces/torques can be summarized as follows:\n\n1. **Translational Force:*\n \n \\[\\mathbf{f}_{T} = -K_{T}(\\mathbf{x}_2 - \\mathbf{x}_1 - \\Delta_x) + \\mathbf{k_d} (\\dot{\\mathbf{x}}_2 - \\dot{\\mathbf{x}}_1)\\]\n \n where:\n - \\(K_T\\): Translational stiffness matrix\n - \\((\\mathbf{x}_2 - \\mathbf{x}_1)\\): Displacement vector between the rigid bodies\n - \\(\\Delta_x\\): Initial rest position displacement\n - \\(\\mathbf{k_d}\\): Damping coefficient\n\n2. **Rotational Torque:*\n \n \\[\\mathbf{f}_{R} = -K_{R}(\\mathbf{q}_2 \\cdot \\mathbf{q}_1^{-1} - \\Delta_q) + \\mathbf{k_d} (\\dot{\\mathbf{q}}_2 - \\dot{\\mathbf{q}}_1)\\]\n \n where:\n - \\(K_R\\): Rotational stiffness matrix\n - \\((\\mathbf{q}_2 \\cdot \\mathbf{q}_1^{-1})\\): Rotation difference between the rigid bodies\n - \\(\\Delta_q\\): Initial rest rotation difference\n - \\(\\mathbf{k_d}\\): Damping coefficient\n\nThe total force and torque contributions are then added to the global internal forces vector:\n\n\\[\\mathbf{f}_{int} = \\begin{pmatrix}\n\\mathbf{f}_T \\\\ \n\\mathbf{f}_R\n\\end{pmatrix}\\]\n\n#### Residual Calculation\n\nThe residual for the system, which is used in nonlinear solution methods such as Newton-Raphson, is defined by:\n\n\\[R(x) = M \\frac{x_{n+1} - x_n}{\\Delta t} + f_{int}(x_{n+1}) - f_{ext}\\]\n\nwhere:\n- \\(M\\): Mass matrix (for rigid bodies, often the identity matrix)\n- \\(f_{int}\\): Internal forces and torques\n- \\(f_{ext}\\): External forces and torques applied to the system\n\n#### Tangent Stiffness Matrix\n\nThe tangent stiffness matrix \\(K(x)\\), which is used in Newton-Raphson iterations, linearizes the internal force contributions with respect to displacements:\n\n\\[K(x) = \\frac{1}{\\Delta t} M - K_{int}(x)\\]\n\nwhere \\(K_{int}(x)\\) represents the tangent stiffness of the spring system.\n\n### Constitutive and Kinematic Laws\n\nThe `JointSpringForceField` component implements a nonlinear kinematic law for rigid body interactions. The following aspects are notable:\n\n- **Stiffness Matrices** \\(K_T\\) and \\(K_R\\):\n - These matrices encode the stiffness coefficients along each local axis, both translational (\\(kst\\)) and rotational (\\(ksr\\)).\n - The spring behavior can be characterized as soft or hard depending on the specified stiffness values.\n\n- **Limit Angles**:\n - Angular limits are defined for rotational degrees of freedom to restrict movement beyond predefined angles. This is achieved by projecting torsions to lawful parts based on limit angles.\n\n### Role in FEM Pipeline\n\nThe `JointSpringForceField` fits into the global FEM pipeline as follows:\n\n1. **Assembly Phase**:\n - The internal forces \\(f_{int}\\) and torques are computed for each spring connecting rigid bodies during assembly.\n - These contributions are aggregated to form the global residual vector \\(R(x)\\).\n\n2. **Time Integration**:\n - Implicit time integration schemes such as Backward Euler can be employed, where the internal forces contribute to the nonlinear system of equations.\n\n3. **Nonlinear Solution**:\n - The tangent stiffness matrix is computed and used in Newton-Raphson iterations to solve for displacements at each timestep.\n\n4. **Linear Solve**:\n - Linear systems are solved iteratively or directly based on the stiffness contributions from this component.\n\n### Numerical Methods and Discretization Choices\n\n- **Pairwise Interaction Force Calculation**: The `addSpringForce` method computes force contributions for each spring using specified stiffnesses, damping, and displacement differences. This is performed in a pairwise fashion for rigid bodies.\n\n- **Stiffness Contribution**: The `addSpringDForce` method calculates the incremental forces due to changes in displacements (\\(dx\\)), which form part of the tangent stiffness matrix.\n\n### Variational/Lagrangian Mechanics Framework Fit\n\nThe component fits into a variational framework by:\n\n- **Variational Principle**: The internal forces are derived from potential energy differences, consistent with the Lagrangian formulation where the Euler-Lagrange equations govern the motion of rigid bodies connected by springs.\n\n- **Weak Formulation**: Although explicit in this case due to the simplicity of rigid body interactions, the internal force contributions implicitly stem from a weak form discretization principle.",
"abstract": "`JointSpringForceField` simulates 6D springs between rigid bodies in SOFA, providing both translational and rotational stiffnesses.",
"sheet": "# JointSpringForceField\n\n## Overview\n\nThe `JointSpringForceField` component simulates 6D springs between rigid bodies in the SOFA framework. It inherits from `PairInteractionForceField` and supports directional and rotational stiffnesses defined on each local axis.\n\n## Mathematical Model\n\n### Internal Forces and Torques\n\nThe internal force and torque contributions are computed based on the displacement and rotation differences between connected rigid bodies:\n\n1. **Translational Force**\n \n \\[\\mathbf{f}_{T} = -K_{T}(\\mathbf{x}_2 - \\mathbf{x}_1 - \\Delta_x) + \\mathbf{k_d} (\\dot{\\mathbf{x}}_2 - \\dot{\\mathbf{x}}_1)\\]\n \n where:\n - \\(K_T\\): Translational stiffness matrix\n - \\((\\mathbf{x}_2 - \\mathbf{x}_1)\\): Displacement vector between the rigid bodies\n - \\(\\Delta_x\\): Initial rest position displacement\n - \\(\\mathbf{k_d}\\): Damping coefficient\n\n2. **Rotational Torque**\n \n \\[\\mathbf{f}_{R} = -K_{R}(\\mathbf{q}_2 \\cdot \\mathbf{q}_1^{-1} - \\Delta_q) + \\mathbf{k_d} (\\dot{\\mathbf{q}}_2 - \\dot{\\mathbf{q}}_1)\\]\n \n where:\n - \\(K_R\\): Rotational stiffness matrix\n - \\((\\mathbf{q}_2 \\cdot \\mathbf{q}_1^{-1})\\): Rotation difference between the rigid bodies\n - \\(\\Delta_q\\): Initial rest rotation difference\n - \\(\\mathbf{k_d}\\): Damping coefficient\n\nThe total force and torque contributions are then added to the global internal forces vector:\n\n\\[\\mathbf{f}_{int} = \\begin{pmatrix}\n\\mathbf{f}_T \\\\ \n\\mathbf{f}_R\n\\end{pmatrix}\\]\n\n### Residual Calculation\n\nThe residual for the system is defined by:\n\n\\[R(x) = M \\frac{x_{n+1} - x_n}{\\Delta t} + f_{int}(x_{n+1}) - f_{ext}\\]\n\nwhere:\n- \\(M\\): Mass matrix (often the identity matrix for rigid bodies)\n- \\(f_{int}\\): Internal forces and torques\n- \\(f_{ext}\\): External forces and torques applied to the system\n\n### Tangent Stiffness Matrix\n\nThe tangent stiffness matrix is defined as:\n\n\\[K(x) = \\frac{1}{\\Delta t} M - K_{int}(x)\\]\n\nwhere \\(K_{int}(x)\\) represents the tangent stiffness of the spring system.\n\n## Parameters and Data\n\nThe significant data fields exposed by this component include:\n- `d_period`: Period between outputs (Real)\n- `d_reinit`: Flag enabling reinitialization of the output file at each timestep (bool)\n- `d_showLawfulTorsion`: Display the lawful part of the joint rotation (bool)\n- `d_showExtraTorsion`: Display the illicit part of the joint rotation (bool)\n- `d_showFactorSize`: Modify the size of the debug information for a given factor (Real)"
}