Large stretch¶

Open In Colab Binder

We compare different material models for uni-axial strain with a large stretch to twenty times its original length.

In [1]:
import matplotlib.pyplot as plt
import numpy as np
import torch
from scipy.optimize import fsolve

from torchfem import Solid
from torchfem.materials import Hyperelastic3D, IsotropicElasticity3D
from torchfem.mesh import cube_hexa

torch.set_default_dtype(torch.float64)
In [2]:
# Material
E = 1000.0
nu = 0.3
lbd = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))
mu = E / (2.0 * (1.0 + nu))


# Generate cube
nodes, elements = cube_hexa(5, 5, 5)

# Boundary sets
left = nodes[:, 0] == 0.0
right = nodes[:, 0] == 1.0
center1 = nodes[:, 1] == 0.5
center2 = nodes[:, 2] == 0.5

# Load
U = 19.0
N = 21
displacements = torch.zeros_like(nodes)
displacements[right, 0] = U
increments = torch.linspace(0.0, 1.0, N)

# Boundary conditions
constraints = torch.zeros_like(nodes, dtype=torch.bool)
constraints[left, 0] = True
constraints[right, 0] = True
constraints[center1, 1] = True
constraints[center2, 2] = True

# Analytical stretch solution
λ = torch.linspace(1.0, 1.0 + U, N)

Linear elasticity with small strains¶

In [3]:
# Reference solution
σl_ref = torch.linspace(0.0, E * U, N)
In [4]:
# Create model
material = IsotropicElasticity3D(E=E, nu=nu)
box = Solid(nodes, elements, material)
box.constraints = constraints
box.displacements = displacements

# Solve
_, _, σl, _, _ = box.solve(increments=increments, return_intermediate=True)

# Plot
plt.plot(λ, σl_ref / E, ".-", color="gray", label="Reference")
plt.plot(λ, σl[..., 0, 0].mean(dim=1) / E, ".--", color="deeppink", label="torch-fem")
plt.xlabel("Stretch λ")
plt.ylabel("Dimensionless Cauchy stress σ/E")
plt.grid()
plt.legend()
plt.show()
No description has been provided for this image

Neo-Hookean hyperelasticity¶

The strain energy function for this Neo-Hookean material is chosen as

$$ \psi(C) = \frac{\mu}{2} \left( \textrm{tr}(C) - 3\right) - \mu \log(J) + \frac{\lambda}{2} \log(J)^2 $$

with the right Cauchy-Green tensor $$ C = F^\top F $$

and the Jacobian $$ J = \det(F). $$

In [5]:
# Analytical reference solution
J = fsolve(
    lambda J: mu * (J / λ.numpy() - 1) + lbd * np.log(J),
    x0=np.ones(λ.shape),
    xtol=1e-10,
)

# Convert J to a numpy array (just to make the linters happy)
J = np.asarray(J)

σn_ref = 1 / J * (lbd * np.log(J) + mu * (λ.numpy() ** 2 - 1))
In [6]:
def psi(F, params):
    """Neo-Hookean strain energy density function."""
    # Extract material parameters
    MU = params[0]
    LBD = params[1]
    # Compute the right Cauchy-Green deformation tensor
    C = F.transpose(-1, -2) @ F
    # Stable computation of the logarithm of the determinant
    logJ = 0.5 * torch.logdet(C)
    return MU / 2 * (torch.trace(C) - 3.0) - MU * logJ + LBD / 2 * logJ**2


# Create model
material = Hyperelastic3D(psi, params=[mu, lbd])

box = Solid(nodes, elements, material)
box.constraints = constraints
box.displacements = displacements

# Solve
_, _, σn, _, _ = box.solve(increments=increments, return_intermediate=True, nlgeom=True)


with torch.no_grad():
    plt.plot(λ, σn_ref / E, ".-", color="gray", label="Reference")
    plt.plot(
        λ,
        σn[..., 0, 0].mean(dim=1) / E,
        ".--",
        color="deeppink",
        label="torch-fem",
    )
    plt.xlabel("Stretch λ")
    plt.ylabel("Dimensionless Cauchy stress σ/E")
    plt.grid()
    plt.legend()
    plt.show()
No description has been provided for this image

Comparison¶

In [7]:
with torch.no_grad():
    plt.plot(λ, σl[..., 0, 0].mean(dim=1) / E, ".-", label="Linear Elasticity")
    plt.plot(λ, σn[..., 0, 0].mean(dim=1) / E, ".-", label="Neo-Hookean")
    plt.xlabel("Stretch λ")
    plt.ylabel("Dimensionless Cauchy stress σ/E")
    plt.grid()
    plt.legend()
    plt.show()
No description has been provided for this image