electroMechanicalLaw
This law adds fibre-directed active stress to the stress calculated by a run-time selectable passive nonlinear mechanical law. The runtime type is:
electroMechanicalLaw
User Guide
What it computes
The cell-centred overload first asks the passive law to calculate the Cauchy stress, then adds an active contribution:
A0 = f0 (x) f0
J = det(F)
sigma = sigma_passive + symm(F & (Ta_current*A0) & F^T)/J
When a cell-centred Ta field exists in the mesh object registry at the first call to correct, Ta_current is that field. Otherwise the dictionary value is ramped according to:
Ta_current = (t/rampTime)*activeTension for t < rampTime
Ta_current = activeTension otherwise
The field-based choice is made once and retained. For the face-centred overload, Ta is interpolated from cells to faces. The implemented face relation differs from the cell relation by multiplying by J:
A0f = f0f (x) f0f
Jf = det(Ff)
sigmaf = sigmaf_passive
+ Jf*symm(Ff & (Taf_current*A0f) & Ff^T)
The volSymmTensorField and surfaceSymmTensorField overloads are implemented. The inherited pointSymmTensorField overload aborts with notImplemented. On OpenFOAM.com and OpenFOAM.org, the inherited CompactListList overload also aborts with notImplemented; that overload is not compiled for foam-extend.
Model options
| Entry | Required | Description |
|---|---|---|
rho | yes | Density, [1 -3 0 0 0 0 0] |
activeTension | yes | Constant active tension, [1 -1 -2 0 0 0 0] |
rampTime | yes | Ramp duration in simulation-time units |
passiveMechanicalLaw | yes | Passive nonlinear-law sub-dictionary |
passiveMechanicalLaw.type | yes | Runtime type of the passive law |
solvePressureEqn | no | Base-class switch; default false |
pressureSmoothingScaleFactor | no | Base-class scalar; default 100 |
regionName | no | Base mesh region used to find the solid model |
activeTension and rampTime remain required when a Ta field will be used, because the constructor reads both before checking the registry. A negative rampTime is rejected. A zero value applies the full constant tension without division by zero because the ramp branch is then not entered for non-negative simulation time.
The top-level base-class pressure options are constructed, but this wrapper does not call updateSigmaHyd(). Options needed by the selected passive law belong inside passiveMechanicalLaw. If regionName is absent, the base class selects solid, then region0; construction fails if neither region exists.
The law also requires volVectorField f0 and surfaceVectorField f0f in the initial time directory. They are read independently and are not normalised by this class.
Recommended dictionary setup
This setup follows the idealisedVentricle tutorial and uses a Guccione law for passive heart tissue:
planeStress no;
mechanical
(
heartTissue
{
type electroMechanicalLaw;
rho rho [1 -3 0 0 0 0 0] 3000;
activeTension activeTension [1 -1 -2 0 0 0 0] 0;
rampTime 0;
passiveMechanicalLaw
{
type GuccioneElastic;
k k [1 -1 -2 0 0 0 0] 10e3;
cf 1;
ct 1;
cfs 1;
uniformFibreField yes;
f0 (0 0 1);
bulkModulus bulkModulus [1 -1 -2 0 0 0 0] 1e6;
}
// Optional base-class entries
// regionName solid;
// solvePressureEqn no;
// pressureSmoothingScaleFactor 100;
}
);
The outer law still requires separate f0 and f0f field files even when the passive law uses its own uniform fibre setting. Set activeTension to the fallback value required when no coupling model registers Ta.
Field glossary
f0: reference fibre direction at cell centres, read withMUST_READand written automatically.f0f: reference fibre direction at faces, read separately withMUST_READand written automatically.f0f0,f0f0f: cell- and face-centred structural tensors formed bysqr(f0)andsqr(f0f).Ta: optional cell-centred active-tension field supplied through the object registry; this law does not create it.F_,Ff_: deformation gradients accessed through the base class for the cell- and face-centred active-stress transformations.- Fields belonging to the passive law are maintained by that nested law.
Developer Notes
Class role
electroMechanicalLaw derives directly from mechanicalLaw and is registered in the nonLinGeomMechLaw selection table. It owns an autoPtr<mechanicalLaw> for the passive law, the f0, f0f, f0f0 and f0f0f fields, the constant Ta_, the scalar rampTime_, and two mutable flags that cache the registry check for field-based active tension.
There are no fork-specific guards in this class. Its source is listed in both Make/files.openfoam and Make/files.foamextend. The base-class CompactListList interface is guarded by #ifndef FOAMEXTEND.
Construction
Construction proceeds in this order:
- The
mechanicalLawbase readssolvePressureEqnwith defaultfalseandpressureSmoothingScaleFactorwith default100, then resolvesregionName. - The
passiveMechanicalLawsub-dictionary and its requiredtypeentry are used to construct a nonlinear mechanical law through the runtime table. f0is read andf0f0is formed assqr(f0).f0fis read independently andf0f0fis formed assqr(f0f).- The required
activeTensiondimensioned scalar andrampTimescalar are read, and the registry-check flags are initialised tofalse. - A negative
rampTimetriggersFatalErrorwith the message that it should be greater than or equal to zero.
The base class also emits a fatal error if it cannot identify solid or region0 and no regionName is supplied. It prints an informational message when solvePressureEqn is enabled. On the first stress correction, this law prints whether it selected field-based or constant active tension.
Key methods
impK()delegates to the passive law. It is the diffusivity used for the solid model's implicit Laplacian term and affects the outer-iteration convergence rate rather than the converged answer.correct(volSymmTensorField&)obtains passive stress, accessesF, and adds either registry-field or ramped constant active stress divided bydet(F).correct(surfaceSymmTensorField&)follows the same sequence withFf, interpolates a registryTato faces, and multiplies the active term bydet(Ff)as implemented.materialTangentField()delegates the complete face list to the passive law. The singular inheritedmaterialTangent()is not overridden and aborts withnotImplemented.bulkModulus()andshearModulus()delegate to the passive law.
Extension points
A related active-passive wrapper can be made by copying this class, retaining the nonlinear runtime construction of the passive law, and replacing the active tensor assembled in the two correct overloads. New implementations should decide explicitly which registry fields are detected, whether that choice may change after the first correction, and which cell, face, point and quadrature interfaces they support. A consistent Newton implementation also needs the active contribution in its material tangent rather than only the passive-law tangent.
The source is at electroMechanicalLaw.C.
Tutorials
solids/hyperelasticity/idealisedVentricle/caseOptions/petsc