GuccioneElastic
This page documents the Guccione transversely isotropic exponential hyperelastic law, intended for passive myocardium. The runtime type is:
GuccioneElastic
The law is anisotropic about a local fibre direction f0, which is either a single uniform vector read from mechanicalProperties or a full volVectorField read from a time directory. The implementation follows the formulation used in E. Garcia-Blanco, R. Ortigosa, A. J. Gil, C. H. Lee and J. Bonet, A new computational framework for electro-activation in cardiac mechanics, Computer Methods in Applied Mechanics and Engineering, 348 (2019) 796-845. The underlying constitutive model is due to J. M. Guccione, A. D. McCulloch and L. K. Waldman (1991).
User Guide
Constitutive relation
The strain energy density is exponential in a quadratic form Q of the Green-Lagrange strain E:
W = 0.5*k*(exp(Q) - 1)
S = dW/dE = 0.5*k*exp(Q)*dQ/dE
where S is the deviatoric part of the 2nd Piola-Kirchhoff stress and k has units of pressure. Two equivalent expressions for Q are implemented, selected by calculateStressInLocalCoordinateSystem.
With calculateStressInLocalCoordinateSystem no (the default), Q is written in terms of invariants of E and the structural tensor f0*f0:
I1 = tr(E)
I2 = 0.5*(sqr(tr(E)) - tr(E & E))
I4 = E && (f0*f0)
I5 = (E & E) && (f0*f0)
Q = ct*sqr(I1) - 2*ct*I2
+ (cf - 2*cfs + ct)*sqr(I4)
+ 2*(cfs - ct)*I5
With calculateStressInLocalCoordinateSystem yes, E is first rotated into the orthonormal fibre frame (f0, s0, n0) to give EStar, and Q takes the classical component form:
Q = cf*sqr(E11)
+ ct*(sqr(E22) + sqr(E33) + 2*sqr(E23))
+ cfs*(2*sqr(E12) + 2*sqr(E13))
The Cauchy stress is then assembled differently in the two solver modes. In the standard (displacement-only) mode a penalty bulk term enforces near incompressibility:
sigma = dev(symm(F & S & F.T))/J + sigmaHyd*I
sigmaHyd = 0.5*bulkModulus*(sqr(J) - 1)/J
In pressure-displacement mode the hydrostatic part comes from the solved pressure field p instead:
sigma = dev(symm(F & S & F.T)) - p*I
Fibre, sheet and sheet-normal directions
Only f0 is user input. The constructor normalises it, then constructs the sheet direction s0 by removing the f0 component from the global x direction (falling back to y where that degenerates), normalises it, and sets n0 = f0 ^ s0. The rotation tensor R has f0, s0 and n0 as its columns and is used for the local-coordinate-system branch. Because s0 and n0 are generated automatically rather than supplied, the transverse response is isotropic in the plane normal to f0 unless ct and cfs are chosen to differ.
Model options
Required entries in the material sub-dictionary:
| Entry | Type | Description |
|---|---|---|
k | dimensionedScalar | Exponential stress scale, [1 -1 -2 0 0 0 0] |
cf | scalar | Fibre-direction stiffness coefficient |
ct | scalar | Transverse stiffness coefficient |
cfs | scalar | Fibre-transverse shear coefficient |
rho | dimensionedScalar | Density, read by the base mechanicalLaw |
bulkModulus is also read with lookup() and is therefore required, unless pressureDisplacement is yes, in which case it is silently set to GREAT and never read.
Optional entries:
| Entry | Default | Description |
|---|---|---|
pressureDisplacement | false | Pressure-displacement formulation |
uniformFibreField | false | Read f0 as a single vector |
f0 | none | Fibre vector; required if uniformFibreField |
calculateStressInLocalCoordinateSystem | false | Use EStar form of Q |
impKcoeff | 1.0 | Scales impK, pressure-displacement only |
writeS0N0R | false | Write s0, n0 and R at construction |
tangentEps is read with lookup() inside materialTangentField(). It is only needed by solid models that request a material tangent, but it is a hard requirement for those.
When uniformFibreField is false, a volVectorField named f0 must exist in the start time directory or in 0; the code tries the current time directory first and falls back to 0, and aborts if neither has it.
Compatibility
correct(volSymmTensorField&) is implemented for both modes, so the law works with the cell-centred nonlinear-geometry solid models, both total and updated Lagrangian (updateF() handles both).
correct(surfaceSymmTensorField&) is implemented only when pressureDisplacement is enabled; otherwise it hits notImplemented. The face-based path is what coupledPressureDisplacementSolid uses, and that model also supplies the p and pf fields that the pressure-displacement branch looks up from the registry. Selecting pressureDisplacement yes with a solid model that does not create p will fail at the first correct() call.
Recommended dictionary setup
Standard penalty-bulk-modulus form, for example with nonLinearGeometryTotalLagrangianTotalDisplacement:
mechanical
(
myocardium
{
type GuccioneElastic;
rho rho [1 -3 0 0 0 0 0] 1000;
k k [1 -1 -2 0 0 0 0] 2000;
cf 8;
ct 2;
cfs 4;
// Penalty bulk modulus; aim for ~100 x the shear modulus
bulkModulus bulkModulus [1 -1 -2 0 0 0 0] 1e6;
uniformFibreField yes;
f0 (0 0 1);
calculateStressInLocalCoordinateSystem no;
}
);
Pressure-displacement form, for coupledPressureDisplacementSolid:
mechanical
(
myocardium
{
type GuccioneElastic;
rho rho [1 -3 0 0 0 0 0] 1000;
nu nu [0 0 0 0 0 0 0] 0.5;
pressureDisplacement yes;
impKcoeff 2;
k k [1 -1 -2 0 0 0 0] 2000;
cf 8;
ct 2;
cfs 4;
calculateStressInLocalCoordinateSystem true;
}
);
Note that nu is not read by this law; it appears in the tutorials because other parts of the case setup expect it.
Field glossary
f0: reference fibre direction, unit length after construction.s0,n0: generated sheet and sheet-normal directions; written only ifwriteS0N0Ris enabled.R,Rf: rotation from the local fibre frame to global Cartesian axes.f0f0,f0f0f: structural tensorsqr(f0)at cells and faces.S2PK,S2PKf: the deviatoric 2nd Piola-Kirchhoff stressS.muEff: effective shear modulus used forimpKin pressure-displacement mode; recomputed at the end of every time step.expQf: face field holdingexp(Q), under-relaxed between outer iterations in the pressure-displacement face path.
Developer Notes
Class role
GuccioneElastic derives from mechanicalLaw. It carries two parallel sets of fields, cell-centred and face-centred, so the same law can serve both the standard cell-centred solid models and coupledPressureDisplacementSolid.
Construction
The constructor:
- Reads
bulkModulusvia the file-local helperreadBulkModulus(), which short-circuits toGREATwhenpressureDisplacementis set. - Reads
k,cf,ct,cfsand forms the linearised shear modulusmu = 0.5*k*(cf + cfs + ct)/3. - Builds
f0andf0fthroughmakeF0()/makeF0f(), either from a uniform vector or from a field on disk. - Stores old-time copies of
FandFf. - Normalises
f0, constructss0andn0, and assemblesRandRf. - If
pressureDisplacement, callscalcInitialShearModulus()andcalcEffectiveShearModulus().
correct() walkthrough
correct(volSymmTensorField&) first calls updateF(). If that returns true the solver has enforced linearised elasticity for stability and the function returns immediately. Otherwise:
C = symm(F.T() & F)andE = 0.5*(C - I);QanddQ/dEare formed by one of the two branches above;S_ = dQdE*0.5*k*exp(Q)(rotated back to global axes in the local branch);- the deviatoric Cauchy stress is
dev(symm(F & S & F.T))/J; updateSigmaHyd()supplies the hydrostatic term, with implicit stiffness(4/3)*mu + bulkModulus.
In the pressure-displacement branch the /J division is omitted and the hydrostatic term is -p*I, taken from the registry field p.
correct(surfaceSymmTensorField&) mirrors this for faces, but only in pressure-displacement mode. It additionally stores and under-relaxes expQf_ between outer iterations, which damps the strong exponential nonlinearity.
Implicit stiffness impK()
pressureDisplacement: impK = impKcoeff*muEff
otherwise: impK = (4/3)*mu + bulkModulus
muEff is not a material constant. calcEffectiveShearModulus() perturbs the displacement gradient by 0.001 in each of the three shear planes of the principal stress frame, evaluates the deviatoric Cauchy stress through calcDevCauchy(), and takes the largest resulting secant shear stiffness. It does this for both the old-time and current deformation gradients and keeps the maximum. updateTotalFields() refreshes it once per time step, so impK stiffens automatically as the exponential response steepens.
calcInitialShearModulus() runs the same perturbation procedure once at construction to replace the analytic small-strain mu.
Material tangent
materialTangentField() builds a mat66 per face by finite-differencing the face stress with respect to each component of grad(D)f, using the step size tangentEps. It calls the private calculateStress() helper, which is currently notImplemented, so the tangent path is not usable as it stands.
Extension points
- Supply
s0explicitly rather than generating it, if genuine orthotropy (cf,ct,cfsall distinct with a meaningful sheet plane) is wanted. - Implement
calculateStress(surfaceSymmTensorField&, const surfaceTensorField&)to enable the material tangent and the non-pressure-displacement face path. - Replace the penalty
bulkModuluswith a different volumetric energy in theupdateSigmaHyd()call.
Tutorials
Cases that select GuccioneElastic:
solids/hyperelasticity/heartTissueBeam(pressure-displacement)solids/hyperelasticity/idealisedVentricle/caseOptions/pressureDisplacementsolids/hyperelasticity/idealisedVentricle/caseOptions/petsc, where it is the passive law nested insideelectroMechanicalLaw