Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of finite Strain Viscoelastic Model with Mooney-Rivlin Hyperelasticity #140

Merged
merged 5 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ Included [pseudo-elastic material models](https://github.com/adtzlr/matadi/blob/

Included [viscoelastic material models](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_viscoelasticity.py):
- [Finite-Strain-Viscoelastic](https://doi.org/10.1016/j.cma.2013.07.004) ([code](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_viscoelasticity.py#L4-L18))
- [Finite-Strain-Viscoelastic (Mooney-Rivlin)](https://doi.org/10.1002/nme.5724) ([code](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_viscoelasticity.py#L21-L51))

Included [other material models](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_misc.py):
- [MORPH](https://doi.org/10.1016/S0749-6419(02)00091-8) ([code](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_misc.py#L19-L75))
Expand Down Expand Up @@ -259,8 +260,9 @@ d2WdFdF, d2WdFdp, d2Wdpdp = NH.hessian([defgrad, pressure, statevars])
The Neo-Hooke, the MORPH and the Finite-Strain-Viscoelastic [[4](https://doi.org/10.1016/j.cma.2013.07.004)] material model formulations are available as ready-to-go materials in `matadi.models` as:

* [`NeoHookeOgdenRoxburgh()`](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_templates.py),
* [`Morph()`](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_templates.py) and
* [`Viscoelastic()`](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_templates.py).
* [`Morph()`](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_templates.py),
* [`Viscoelastic()`](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_templates.py) and
* [`ViscoelasticMooneyRivlin()`](https://github.com/adtzlr/matadi/blob/main/src/matadi/models/_templates.py).

**Hint**: *The state variable concept is also implemented for the `Material` class.*

Expand Down
10 changes: 6 additions & 4 deletions src/matadi/_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,9 @@ def _fun_wrapper(self, x, **kwargs):


class MaterialComposite:
"Composite Material as a sum of a list of hyperelastic materials."

def __init__(self, materials):
"Composite Material as a sum of a list of hyperelastic materials."
self.materials = materials
self.fun = self.composite

Expand All @@ -231,10 +232,11 @@ def hessian(self, x, **kwargs):


class MaterialTensorGeneral(MaterialTensor):
def __init__(self, fun, statevars_shape=(1, 1), x=None, triu=True, **kwargs):
"""A (first Piola-Kirchhoff stress) tensor-based material definition with
state variables of a given shape."""
"""A (first Piola-Kirchhoff stress) tensor-based material definition with
state variables of a given shape.
"""

def __init__(self, fun, statevars_shape=(1, 1), x=None, triu=True, **kwargs):
if x is None:
x = [Variable("F", 3, 3)]

Expand Down
26 changes: 26 additions & 0 deletions src/matadi/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,29 @@ def astensor(A, scale=1):

else:
raise ValueError("Unknown shape of input.")


def unimodular(T):
"""
Compute the unimodular part of a tensor.

The unimodular part of a tensor is a modified version of the tensor where
the determinant is raised to the power of (-1/3) and multiplied to the tensor.
This operation preserves the isochoric (volume-preserving) part of the tensor
while removing the volumetric part.
"""
return (det(T) ** (-1 / 3)) * T


def sqrtm(C, eps=8e-5):
"""
Compute the matrix square root of a tensor C using eigendecomposition.
"""
w = eigvals(C, eps=eps)
eye = SX.eye(3)

M1 = (C - w[1] * eye) * (C - w[2] * eye) / (w[0] - w[1]) / (w[0] - w[2])
M2 = (C - w[2] * eye) * (C - w[0] * eye) / (w[1] - w[2]) / (w[1] - w[0])
M3 = (C - w[0] * eye) * (C - w[1] * eye) / (w[2] - w[0]) / (w[2] - w[1])

return sqrt(w[0]) * M1 + sqrt(w[1]) * M2 + sqrt(w[2]) * M3
10 changes: 8 additions & 2 deletions src/matadi/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@
)
from ._misc import morph
from ._pseudo_elasticity import ogden_roxburgh
from ._templates import Morph, NeoHookeOgdenRoxburgh, Viscoelastic
from ._viscoelasticity import finite_strain_viscoelastic
from ._templates import (
Morph,
NeoHookeOgdenRoxburgh,
Viscoelastic,
ViscoelasticMooneyRivlin,
)
from ._viscoelasticity import finite_strain_viscoelastic, finite_strain_viscoelastic_mr
from .microsphere.nonaffine import miehe_goektepe_lulei

__all__ = [
Expand All @@ -47,5 +52,6 @@
"NeoHookeOgdenRoxburgh",
"Viscoelastic",
"finite_strain_viscoelastic",
"finite_strain_viscoelastic_mr",
"miehe_goektepe_lulei",
]
26 changes: 25 additions & 1 deletion src/matadi/models/_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from ._hyperelasticity_isotropic import neo_hooke
from ._misc import morph
from ._pseudo_elasticity import ogden_roxburgh
from ._viscoelasticity import finite_strain_viscoelastic
from ._viscoelasticity import finite_strain_viscoelastic, finite_strain_viscoelastic_mr


class NeoHookeOgdenRoxburgh(MaterialTensorGeneral):
Expand Down Expand Up @@ -81,3 +81,27 @@ def fun(x, mu, eta, dtime):
eta=eta,
dtime=dtime,
)


class ViscoelasticMooneyRivlin(MaterialTensorGeneral):
"Finite strain viscoelastic material formulation with Mooney-Rivlin hyperelasticity."

def __init__(
self,
c10=1,
c01=1,
eta=1,
dtime=1,
):
def fun(x, c10, c01, eta, dtime):
P, statevars = finite_strain_viscoelastic_mr(x, c10, c01, eta, dtime)
return P, statevars

super().__init__(
fun=fun,
statevars_shape=(6, 1),
c10=c10,
c01=c01,
eta=eta,
dtime=dtime,
)
35 changes: 34 additions & 1 deletion src/matadi/models/_viscoelasticity.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ..math import astensor, asvoigt, det, gradient, inv, trace
from ..math import astensor, asvoigt, det, eye, gradient, inv, sqrtm, trace, unimodular


def finite_strain_viscoelastic(x, mu, eta, dtime):
Expand All @@ -16,3 +16,36 @@ def finite_strain_viscoelastic(x, mu, eta, dtime):

# first Piola-Kirchhoff stress tensor and state variable
return gradient(mu / 2 * (I1 - 3), F), asvoigt(Ci)


def finite_strain_viscoelastic_mr(x, c10, c01, eta, dtime):
"""
Finite strain viscoelastic material formulation with Mooney-Rivlin hyperelasticity
(Shutov 2018) https://doi.org/10.1002/nme.5724
"""

# Split input into the deformation gradient and the vector of state variables
F, Cin = x[0], x[-1]

# Right cauchy-green deformation tensor
C = F.T @ F

# Based on
# <<TABLE 1: Iteration-free Euler backward method on the reference configuration>>
A = (
unimodular(sqrtm(inv(C)))
@ (astensor(Cin) + (dtime / eta) * c10 * unimodular(C))
@ unimodular(sqrtm(inv(C)))
)
eps = c01 * (dtime / eta)
phi0 = det(A) ** (1 / 3)
phi = phi0 - (trace(A) / (3 * phi0)) * eps
X = 2 * A @ inv(sqrtm(phi * phi * eye(3) + 4 * eps * A) + phi * eye(3))

Ci = unimodular(sqrtm(C) @ X @ sqrtm(C))

I1 = trace(unimodular(C @ inv(Ci)))
I2 = trace(unimodular(Ci @ inv(C)))

# First Piola-Kirchhoff stress tensor and state variable
return gradient(c10 / 2 * (I1 - 3) + c01 / 2 * (I2 - 3), F), asvoigt(Ci)
8 changes: 7 additions & 1 deletion tests/test_template-materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Morph,
NeoHookeOgdenRoxburgh,
Viscoelastic,
ViscoelasticMooneyRivlin,
neo_hooke,
volumetric,
)
Expand Down Expand Up @@ -47,7 +48,12 @@ def test_templates():
def test_templates_models():
# Material as a function of `F`
# with additional state variables `z`
for M in [NeoHookeOgdenRoxburgh(), Morph(), Viscoelastic()]:
for M in [
NeoHookeOgdenRoxburgh(),
Morph(),
Viscoelastic(),
ViscoelasticMooneyRivlin(),
]:
FF = (np.random.rand(3, 3, 8, 100) - 0.5) / 2
zz = np.random.rand(*M.x[-1].shape, 8, 100)

Expand Down
Loading