Note
Go to the end to download the full example code or to run this example in your browser via JupyterLite.
Johnson’s parabola (1893)#
Euler’s hyperbola overestimates the strength of stocky columns, which
yield or buckle inelastically, and tests scattered below it. J. B. Johnson
and his co-authors, in The Theory and Practice of Modern Framed
Structures (1893), fitted a parabola that starts at the yield stress and
meets Euler’s curve tangentially at half of it
(johnson_critical_stress()),
at the transition slenderness \(C_c = \sqrt{2\pi^2E/\sigma_y}\). The
AISC column formula used the same parabola for decades. End conditions
enter through the effective length \(KL\)
(effective_length_factor()).
The example draws the design curve and checks that the two branches meet
with the same slope.
import matplotlib.pyplot as plt
import numpy as np
from engineeringkit.structural_engineering import effective_length_factor, johnson_critical_stress
The design curve#
E, sy = 200e9, 250e6
Cc = np.sqrt(2 * np.pi**2 * E / sy)
slenderness = np.linspace(1, 250, 500)
sigma = johnson_critical_stress(sy, E, slenderness)
print(f"transition slenderness Cc = {Cc:.1f}, where the critical stress is {johnson_critical_stress(sy, E, Cc) / 1e6:.0f} MPa")
h = 1e-4
left = (johnson_critical_stress(sy, E, Cc - h) - johnson_critical_stress(sy, E, Cc - 2 * h)) / h
right = (johnson_critical_stress(sy, E, Cc + 2 * h) - johnson_critical_stress(sy, E, Cc + h)) / h
assert np.isclose(left, right, rtol=1e-4)
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(slenderness, sigma / 1e6, label="Johnson + Euler")
ax.plot(slenderness, np.pi**2 * E / slenderness**2 / 1e6, "--", label="Euler alone")
ax.axvline(Cc, color="gray", lw=0.5)
ax.set(xlabel="slenderness KL/r", ylabel="critical stress [MPa]", ylim=(0, 300))
ax.legend()
fig.tight_layout()

transition slenderness Cc = 125.7, where the critical stress is 125 MPa
The same strut with four end conditions#
L, r = 3.0, 0.03
for ends in ("fixed-fixed", "fixed-pinned", "pinned-pinned", "fixed-free"):
K = effective_length_factor(ends)
print(f"{ends:14s} K = {K:.3f} KL/r = {K * L / r:6.1f} sigma_cr = {johnson_critical_stress(sy, E, K * L / r) / 1e6:6.1f} MPa")
assert np.isclose(np.tan(np.pi / effective_length_factor("fixed-pinned")), np.pi / effective_length_factor("fixed-pinned"))
plt.show()
fixed-fixed K = 0.500 KL/r = 50.0 sigma_cr = 230.2 MPa
fixed-pinned K = 0.699 KL/r = 69.9 sigma_cr = 211.3 MPa
pinned-pinned K = 1.000 KL/r = 100.0 sigma_cr = 170.8 MPa
fixed-free K = 2.000 KL/r = 200.0 sigma_cr = 49.3 MPa
Total running time of the script: (0 minutes 0.084 seconds)