Goodman’s mean-stress diagram (1899)#

Wöhler’s endurance tests reversed the stress fully, but most machine parts carry a steady stress with an alternating one on top. John Goodman’s Mechanics Applied to Engineering (1899) drew the line that design still uses: the alternating stress a part can carry falls linearly from the endurance limit \(S_e\) at zero mean to nothing at the ultimate strength \(S_{ut}\),

\[\frac{\sigma_a}{S_e} + \frac{\sigma_m}{S_{ut}} = \frac{1}{n}\]

(goodman_safety_factor()). The example compares it with Gerber’s parabola (1874) and Soderberg’s line (1930) and reads safety factors along a load line.

import matplotlib.pyplot as plt
import numpy as np

from engineeringkit.materials import goodman_safety_factor

A bolt with a preload#

A steel bolt (\(S_{ut} = 830\) MPa, \(S_e = 130\) MPa for a rolled thread) carries a mean stress of 400 MPa from its preload and an alternating 40 MPa from the external load. Scaling both stresses by \(n\) puts the point on the Goodman line.

Sut, Sy, Se = 830e6, 660e6, 130e6
sa, sm = 40e6, 400e6
n = goodman_safety_factor(sa, sm, Se, Sut)
print(f"Goodman safety factor {n:.3f}")
assert np.isclose(n * sa / Se + n * sm / Sut, 1)
Goodman safety factor 1.266

Three failure lines#

Gerber’s parabola \(\sigma_a/S_e + (\sigma_m/S_{ut})^2 = 1\) follows test data through the middle; Goodman’s line lies inside it, and Soderberg’s, drawn to the yield strength, is the most conservative.

mean = np.linspace(0, Sut, 200)
goodman = Se * (1 - mean / Sut)
gerber = Se * (1 - (mean / Sut) ** 2)
soderberg = Se * np.clip(1 - mean / Sy, 0, None)
assert np.all(soderberg <= goodman + 1e-6) and np.all(goodman <= gerber + 1e-6)
external = np.linspace(10e6, 80e6, 8)
n_external = goodman_safety_factor(external, sm, Se, Sut)
print("safety factor as the alternating stress grows:", np.round(n_external, 2).tolist())
assert np.all(np.diff(n_external) < 0)

fig, ax = plt.subplots(figsize=(6, 3.8))
ax.plot(mean / 1e6, gerber / 1e6, label="Gerber (1874)")
ax.plot(mean / 1e6, goodman / 1e6, label="Goodman (1899)")
ax.plot(mean / 1e6, soderberg / 1e6, label="Soderberg (1930)")
ax.plot([0, n * sm / 1e6], [0, n * sa / 1e6], "k:", lw=1, label="load line")
ax.plot(sm / 1e6, sa / 1e6, "ko", label=f"bolt, n = {n:.2f}")
ax.set(xlabel="mean stress [MPa]", ylabel="alternating stress [MPa]", title="Mean-stress diagram", ylim=(0, 1.2 * Se / 1e6))
ax.legend()
fig.tight_layout()

plt.show()
Mean-stress diagram
safety factor as the alternating stress grows: [1.79, 1.57, 1.4, 1.27, 1.15, 1.06, 0.98, 0.91]

Total running time of the script: (0 minutes 0.039 seconds)

Gallery generated by Sphinx-Gallery