Cantilever plate¶

Open In Colab Binder

A plate of dimensions 100mm x 50mm x 0.5mm clamped at one end. It is subjected to concentrated forces of 5N at each corner at the tip.

A reference solution is computed with ABAQUS for the following shell elements:

Type u_max S_max PEEQ_max
STRI65 46.33 304.9 0.4846%
In [1]:
import torch

from torchfem import Shell
from torchfem.materials import IsotropicPlasticityPlaneStress
from torchfem.mesh import rect_tri

torch.set_default_dtype(torch.float64)

Material model¶

In [2]:
# Material properties
E = 200000.0
nu = 0.3
sigma_y = 250.0
k = 10000.0


# Hardening function
def sigma_f(q):
    return sigma_y + k * q


# Derivative of the hardening function
def sigma_f_prime(q):
    return k


material = IsotropicPlasticityPlaneStress(E, nu, sigma_f, sigma_f_prime)

Model setup¶

In [3]:
# Define nodes and element of the plate
nodes, elements = rect_tri(10, 5, Lx=100.0, Ly=50.0, variant="zigzag")
nodes = torch.hstack([nodes, torch.zeros((nodes.size(0), 1))])

# Define Shell model
cantilever = Shell(nodes, elements, material, thickness=0.5, n_simpson=5)

# Define masks for boundaries
left = nodes[:, 0] < 0.01
right = nodes[:, 0] > 99.9
front = nodes[:, 1] < 0.01
back = nodes[:, 1] > 49.99
corner_1 = right & front
corner_2 = right & back

# Apply load boundary conditions
cantilever.forces[corner_1, 2] = -5
cantilever.forces[corner_2, 2] = -5

# Apply displacement boundary conditions
cantilever.constraints[left] = True


cantilever.plot(bcs=True)

Solve and extract maxima¶

In [4]:
# Solve
increments = torch.linspace(0, 1.0, 21)
u, f, σ, F, ɑ = cantilever.solve(
    increments=increments,
    return_intermediate=True,
    aggregate_integration_points=False,
)
In [5]:
# Extract final plastic strains along thickness integration points
ɑ_top = ɑ[-1, 0, :, 0]
ɑ_middle = ɑ[-1, 2, :, 0]
ɑ_bottom = ɑ[-1, 4, :, 0]

# Extract final stresses along thickness integration points
σ_top = σ[-1, 0, :, :]
σ_middle = σ[-1, 2, :, :]
σ_bottom = σ[-1, 4, :, :]

mises_top = torch.sqrt(
    σ_top[:, 0, 0] ** 2
    - σ_top[:, 0, 0] * σ_top[:, 1, 1]
    + σ_top[:, 1, 1] ** 2
    + 3 * σ_top[:, 0, 1] ** 2
)

mises_middle = torch.sqrt(
    σ_middle[:, 0, 0] ** 2
    - σ_middle[:, 0, 0] * σ_middle[:, 1, 1]
    + σ_middle[:, 1, 1] ** 2
    + 3 * σ_middle[:, 0, 1] ** 2
)

mises_bottom = torch.sqrt(
    σ_bottom[:, 0, 0] ** 2
    - σ_bottom[:, 0, 0] * σ_bottom[:, 1, 1]
    + σ_bottom[:, 1, 1] ** 2
    + 3 * σ_bottom[:, 0, 1] ** 2
)

print(f"Maximum displacement: {torch.linalg.norm(u[-1, :, 0:3], dim=1).max():.4f}")
print(f"Maximum plastic strain at top: {ɑ_top.max():.4f}")
print(f"Maximum plastic strain at middle: {ɑ_middle.max():.4f}")
print(f"Maximum plastic strain at bottom: {ɑ_bottom.max():.4f}")
print(f"Maximum von Mises stress at top: {mises_top.max():.4f}")
print(f"Maximum von Mises stress at middle: {mises_middle.max():.4f}")
print(f"Maximum von Mises stress at bottom: {mises_bottom.max():.4f}")
Maximum displacement: 45.6149
Maximum plastic strain at top: 0.0038
Maximum plastic strain at middle: 0.0000
Maximum plastic strain at bottom: 0.0038
Maximum von Mises stress at top: 288.1621
Maximum von Mises stress at middle: 0.0000
Maximum von Mises stress at bottom: 288.1621

Visualize results on deformed geometry¶

In [6]:
# Displacement on deformed configuration
cantilever.plot(
    u[-1, :, 0:3],
    element_property={"von Mises Stress (top)": mises_top},
    cmap="inferno",
)
In [7]:
# Displacement on deformed configuration
cantilever.plot(
    u[-1, :, 0:3], element_property={"PEEQ (top) in % ": ɑ_top * 100}, cmap="Blues"
)