Note
Go to the end to download the full example code or to run this example in your browser via JupyterLite.
Tresca’s maximum-shear yield criterion (1864)#
Henri Tresca (1864) punched and extruded lead, copper and iron through dies
at the Conservatoire des Arts et Métiers and found that metals flow like a
viscous fluid once the largest shear stress reaches a constant. With
principal stresses \(\sigma_1 \ge \sigma_2 \ge \sigma_3\) the criterion
is \(\sigma_1 - \sigma_3 = \sigma_y\)
(tresca_equivalent()). It is the first
criterion for yielding under combined stresses, and in the plane-stress
principal plane it draws a hexagon. The example applies it to a shaft in
bending and torsion and to biaxial stress states.
import matplotlib.pyplot as plt
import numpy as np
from engineeringkit.materials import factor_of_safety, tresca_equivalent
from engineeringkit.materials.visualizers import plot_yield_surfaces
A shaft in bending and torsion#
At the surface of a shaft the bending stress \(\sigma\) and the torsional shear \(\tau\) give principal stresses \(\sigma/2 \pm \sqrt{(\sigma/2)^2 + \tau^2}\) and zero. Tresca’s equivalent stress is their spread, \(\sqrt{\sigma^2 + 4\tau^2}\).
sy = 350e6
sigma, tau = 120e6, 90e6
center, radius = sigma / 2, np.hypot(sigma / 2, tau)
principal = [center + radius, center - radius, 0.0]
equivalent = tresca_equivalent(principal)
print(f"principal stresses {np.round(np.array(principal) / 1e6, 1)} MPa")
print(f"Tresca equivalent {equivalent / 1e6:.1f} MPa, safety factor {factor_of_safety(sy, equivalent):.2f}")
assert np.isclose(equivalent, np.sqrt(sigma**2 + 4 * tau**2))
principal stresses [168.2 -48.2 0. ] MPa
Tresca equivalent 216.3 MPa, safety factor 1.62
Where the zero stress matters#
When both in-plane principal stresses have the same sign, the largest shear acts out of the plane and the zero third stress sets the spread. Equal biaxial tension yields at \(\sigma_y\), not at infinity.
states = np.array([[1.0, 1.0, 0.0], [1.0, 0.5, 0.0], [1.0, -1.0, 0.0], [0.5, -0.5, 0.0]]) * sy
for state, eq in zip(states, tresca_equivalent(states)):
print(f"sigma_1, sigma_2 = {state[0] / sy:+.1f}, {state[1] / sy:+.1f} sigma_y -> Tresca {eq / sy:.2f} sigma_y")
np.testing.assert_allclose(tresca_equivalent(states) / sy, [1, 1, 2, 1])
ax = plot_yield_surfaces(sy)
ax.plot(states[:, 0] / sy, states[:, 1] / sy, "ko")
ax.set_title("Tresca's hexagon")
ax.figure.tight_layout()
plt.show()

sigma_1, sigma_2 = +1.0, +1.0 sigma_y -> Tresca 1.00 sigma_y
sigma_1, sigma_2 = +1.0, +0.5 sigma_y -> Tresca 1.00 sigma_y
sigma_1, sigma_2 = +1.0, -1.0 sigma_y -> Tresca 2.00 sigma_y
sigma_1, sigma_2 = +0.5, -0.5 sigma_y -> Tresca 1.00 sigma_y
Total running time of the script: (0 minutes 0.027 seconds)