Stabilisation Models
This directory contains runtime-selectable stabilisation models used by solids4foam to add artificial dissipation for suppressing grid-scale oscillations in scalar and vector fields.
Design Overview
The common base class is stabilisationModel.
Each concrete stabilisation model is responsible for:
- reading its configuration from a dictionary,
- computing a face-based stabilisation contribution,
- optionally providing an approximate Jacobian for implicit use.
The classes are intentionally lightweight. The current interface is based on an explicit update step followed by read access to cached results. This lets a solid model control when the stabilisation is recalculated and re-use the result more than once without repeating the work.
Runtime Selection
Models are selected from dictionary input using the standard OpenFOAM runtime selection mechanism:
stabilisation
{
momentum
{
type diffStencilLaplacian;
scaleFactor 0.1;
}
pressure
{
type diffStencilLaplacian;
scaleFactor 0.1;
}
}
The currently available model types in this directory are:
alphadiffStencilLaplaciangeneralisedEvenOrderLaplaciangradDivJamesonSchmidtTurkellaplacianmultiple— composite model combining two or more models (see below)volStrainRate— temporal stabilisation based on the rate of change of volumetric strain (see below)
RhieChow is implemented as a helper under diffStencilLaplacianStab/RhieChowStab.
Usage Pattern
The intended solver-side usage is:
- Construct the model through
stabilisationModel::New(...). - Call
updateScalar(...)orupdateVector(...)when the stabilisation needs to be refreshed. - Read the cached result using
faceScalar()orfaceVector(). - Optionally derive a cached cell field using
cellScalar(...)orcellVector(...). - If supported by the model, use
scalarJacobian(...)orvectorJacobian(...)to obtain an approximate implicit contribution.
For example, in linGeomTotalDispSolid.C, the momentum stabilisation is updated before its face contribution is added to the traction.
If faceScalar() or faceVector() is accessed before the corresponding update...() call, the code intentionally aborts with a clear fatal error. This is by design and is used to keep the interface simple.
The cellScalar(...) and cellVector(...) accessors follow the same pattern. They build and cache a cell-centred divergence of the current face stabilisation. If the corresponding face field has not been initialised yet, they also abort with a clear fatal error.
The cell-field interface accepts:
cellScalar(gammaPtr, rebuild)
cellVector(gammaPtr, rebuild)
The optional gammaPtr lets a solver include a face diffusivity inside the divergence, for example div(gamma*faceScalar*magSf). The optional rebuild flag defaults to false and forces the cached cell field to be recalculated from the current cached face field when set to true.
Gradient Arguments
The updateScalar(...) and updateVector(...) functions optionally accept a pointer to the gradient of the primary field.
This is intentionally a minimal interface. Some models need the gradient to build the stabilisation efficiently or accurately, while others can reconstruct what they need internally and therefore ignore the pointer.
Current expectation:
- gradient-based stencil/jump models may require
gradPtr, - Laplacian-like models may ignore
gradPtr, - callers should pass the available gradient when they already have it.
This avoids forcing more specialised interfaces for each stabilisation family.
Jacobian Caching
Some models provide an approximate Jacobian through scalarJacobian(...) or vectorJacobian(...). These matrices are cached internally after first construction.
The Jacobian interface also accepts an optional rebuild flag:
scalarJacobian(field, gammaPtr, rebuild)
vectorJacobian(field, gammaPtr, rebuild)
The optional scaleFactorJacobian entry defaults to 1.0, not to the explicit stabilisation scaleFactor. This lets the approximate Jacobian act as an independently tuned implicit contribution when needed.
The default is false, which preserves the existing behaviour and reuses the cached matrix. If a solver needs the approximate Jacobian to be reconstructed because the relevant coefficients or matrix structure have changed, it can pass true.
For the current development work, the solid-model call sites are left on the default behaviour, so no existing solver logic changes.
Combining Multiple Models
The multiple type combines two or more stabilisation models at run time. Their face contributions are summed and an optional outer scaleFactor (defaults to 1.0) is applied to the total. The Jacobian is delegated to a single user-nominated sub-model.
stabilisation
{
momentum
{
type multiple;
// scaleFactor 1.0; // optional outer scale; defaults to 1.0
models ( stab1 stab2 );
jacobianModel stab1;
stab1
{
type laplacian;
scaleFactor 0.1;
}
stab2
{
type gradDiv;
scaleFactor 0.05;
}
}
}
Each entry in models must correspond to a named sub-dictionary in the same dictionary. The jacobianModel entry names whichever sub-model provides the Jacobian (it must be one of the entries in models).
The highOrderResidual option is allowed with multiple only if every sub-model returns true from supportsHighOrderResidual(). Currently only the alpha model satisfies this requirement.
Volumetric Strain Rate Stabilisation
The volStrainRate type targets temporal oscillations in the volumetric strain tr(gradD) rather than spatial oscillations. The face stabilisation vector is:
faceVector_f =
scaleFactor * C(mode)
* [tr(gradD_f_future) - tr(gradD_f_old)] * n_f
Five modes are available, selected via the mode entry:
| mode | C(mode) | Vanishes as |
|---|---|---|
physicalDamping | tau/deltaT | never — permanent physical damping |
firstOrderTemporal | 1 | O(deltaT) |
secondOrderTemporal | deltaT | O(deltaT^2) |
spatioTemporal | h^2/m^2 | O(h^2 * deltaT) |
h2PhysicalDamping | h^2/(m^2*deltaT) | O(h^2) as h→0; O(1) as deltaT→0 |
The gradient pointer (gradPtr) passed to updateVector must be non-null and must carry an old-time level (i.e. gradPtr->oldTime() must be valid). In nonLinGeomTotalLagVelocitySolid this is satisfied by passing &gradD().
stabilisation
{
momentum
{
type volStrainRate;
scaleFactor 0.1;
mode firstOrderTemporal;
}
}
For physicalDamping mode, an additional tau entry (in seconds) sets the damping time scale:
type volStrainRate;
scaleFactor 0.1;
mode physicalDamping;
tau 1e-4;
The h2PhysicalDamping mode combines the O(h²) spatial scaling of spatioTemporal with the Δt-persistence of physicalDamping. It is the recommended mode when the instability is a temporal pressure pulsation (whole-domain oscillation) that worsens as Δt decreases, and when spatial consistency under mesh refinement is also required. No tau parameter is needed; the time scale is folded into scaleFactor.
type volStrainRate;
scaleFactor 0.1;
mode h2PhysicalDamping;
An approximate Laplacian Jacobian is provided via vectorJacobian. For modes whose coefficient depends on deltaT (physicalDamping, secondOrderTemporal, and h2PhysicalDamping), the Jacobian should be rebuilt each time step by calling vectorJacobian(field, gammaPtr, true).
Notes For Extension
When adding a new stabilisation model:
- derive from
stabilisationModel, - add
TypeName("...")in the header, - register with
addToRunTimeSelectionTable(...)in the source, - add the source to the relevant build lists,
- keep the interface consistent with the existing
update...()and cached accessor pattern unless there is a strong reason to change the framework, - if the new model is compatible with
highOrderResidualcalculation, overridesupportsHighOrderResidual()to returntrue.
The current framework is being validated first with linGeomTotalDispSolid. Wider adoption across the other solid models can follow once the design settles.