File size: 7,985 Bytes
7324519 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# =========================
# Column Buckling Calculator — Euler Elastic (Rectangular Section)
# =========================
import math
import gradio as gr
import pandas as pd
SCOPE_MD = """
### Scope & Assumptions
- **Problem:** Axially compressed **prismatic column** (rectangular cross-section), **Euler elastic buckling**.
- **Outputs:** Governing critical load \(P_{cr}\), governing axis, slenderness \(λ\), factor of safety vs. applied load \(P\), verdict.
- **Method:** Euler buckling (linear-elastic, small deflection), **no inelastic (Johnson)**, **no eccentricity**, **no imperfections**.
- **Section:** Rectangle (width \(b\), height \(h\)); checks both axes and picks the **weaker axis** (smaller \(P_{cr}\)).
- **End conditions:** Choose \(K\): Fixed–Fixed (0.5), Fixed–Pinned (0.7), Pinned–Pinned (1.0), Fixed–Free (2.0).
- **Units:** SI (m, N, GPa, MPa). Input \(P\) in kN. Results show \(P_{cr}\) in **kN**.
### Valid Ranges (hard checks)
- 0.1 < L ≤ 20 m
- 0 < P ≤ 5*10^6 N
- 1 ≤ E ≤ 400 GPa
- 10 ≤ Sy ≤ 3000 MPa (for context only; not used in Euler (P_{cr}\)
- 0.005 < b ≤ 2 m
- 0.005 < h ≤ 2 m
"""
# ----- Validation -----
def _validate_inputs(L_m, P_kN, E_GPa, Sy_MPa, b_m, h_m):
errs = []
def in_range(name, val, lo, hi):
if not (lo < val <= hi):
errs.append(f"{name} must be in ({lo}, {hi}] (got {val}).")
in_range("Length L [m]", L_m, 0.1, 20.0)
in_range("Load P [kN]", P_kN, 0.0, 5000.0) # 5e6 N
in_range("Elastic modulus E [GPa]", E_GPa, 1.0, 400.0)
in_range("Yield strength Sy [MPa]", Sy_MPa, 10.0, 3000.0)
in_range("Width b [m]", b_m, 0.005, 2.0)
in_range("Height h [m]", h_m, 0.005, 2.0)
if errs:
raise ValueError("\n".join(errs))
# ----- Core Math -----
def euler_buckling_rect(L_m, P_kN, E_GPa, Sy_MPa, b_m, h_m, K):
"""
Euler elastic buckling for a rectangular column.
Checks both principal axes and selects the governing (smaller Pcr).
"""
_validate_inputs(L_m, P_kN, E_GPa, Sy_MPa, b_m, h_m)
# SI conversions
P_applied_N = float(P_kN) * 1e3
E_Pa = float(E_GPa) * 1e9
# Section properties
A = b_m * h_m
Ix = b_m * (h_m**3) / 12.0
Iy = h_m * (b_m**3) / 12.0
rx = (Ix / A) ** 0.5
ry = (Iy / A) ** 0.5
KL = K * L_m
Pcr_x = (math.pi**2) * E_Pa * Ix / (KL**2)
Pcr_y = (math.pi**2) * E_Pa * Iy / (KL**2)
# Governing axis (smaller Pcr)
if Pcr_x <= Pcr_y:
axis = "x (buckles about the weak direction of Ix → bending about h)"
Pcr = Pcr_x
r_govern = rx
I_govern = Ix
else:
axis = "y (buckles about the weak direction of Iy → bending about b)"
Pcr = Pcr_y
r_govern = ry
I_govern = Iy
slenderness = KL / r_govern if r_govern > 0 else math.inf
fos = Pcr / P_applied_N if P_applied_N > 0 else math.inf
ok = P_applied_N <= Pcr
# Pretty print helpers
def _fmt(x, d=6):
try:
return f"{x:.{d}g}"
except Exception:
return str(x)
steps_md = "\n".join([
"## Show the math (Euler elastic buckling)",
f"L = {_fmt(L_m)} m, K = {_fmt(K)}, KL = {K} * {L_m} = {KL:.6g} m",
f"E = {_fmt(E_GPa)} GPa, P = {_fmt(P_kN)} kN (= {P_applied_N:.6g} N)",
f"b = {_fmt(b_m)} m, h = {_fmt(h_m)} m",
"",
"Area and moments of inertia:",
f"A = b * h = {b_m} * {h_m} = {A:.6e} m^2",
f"Ix = b * h^3 / 12 = {b_m} * {h_m}^3 / 12 = {Ix:.6e} m^4",
f"Iy = h * b^3 / 12 = {h_m} * {b_m}^3 / 12 = {Iy:.6e} m^4",
f"rx = sqrt(Ix / A) = sqrt({Ix:.6e} / {A:.6e}) = {rx:.6e} m",
f"ry = sqrt(Iy / A) = sqrt({Iy:.6e} / {A:.6e}) = {ry:.6e} m",
"",
"Euler critical loads:",
"Pcr = π^2 * E * I / (K*L)^2",
f"Pcr_x = (π^2) * ({E_GPa} * 10^9) * ({Ix:.6e}) / ({K} * {L_m})^2 = {Pcr_x:.6e} N",
f"Pcr_y = (π^2) * ({E_GPa} * 10^9) * ({Iy:.6e}) / ({K} * {L_m})^2 = {Pcr_y:.6e} N",
f"Governing axis: {axis}",
f"Pcr(governing) = {Pcr:.6e} N = {Pcr/1e3:.3f} kN",
"",
"Slenderness (governing axis):",
f"λ = (K*L) / r_governing = {KL:.6g} / {r_govern:.6e} = {slenderness:.2f}",
"",
"Check vs applied load:",
f"FoS_buckling = Pcr / P = {Pcr:.6e} / {P_applied_N:.6e} = {fos:.3f}",
f"Verdict: {'OK (no buckling at P)' if ok else 'NOT OK (buckles at P)'}"
])
results = {
"A_m2": A,
"Ix_m4": Ix,
"Iy_m4": Iy,
"rx_m": rx,
"ry_m": ry,
"Pcr_x_N": Pcr_x,
"Pcr_y_N": Pcr_y,
"Pcr_governing_N": Pcr,
"P_applied_N": P_applied_N,
"FoS_buckling": fos,
"governing_axis": axis,
"slenderness_governing": slenderness,
"ok": bool(ok),
}
verdict = {
"message": "OK: no Euler buckling at the applied load" if ok else "NOT OK: Euler buckling likely at the applied load",
"governing_axis": axis
}
return results, verdict, steps_md
# ----- Gradio glue -----
END_CONDITIONS = {
"Fixed–Fixed (K=0.5)": 0.5,
"Fixed–Pinned (K=0.7)": 0.7,
"Pinned–Pinned (K=1.0)": 1.0,
"Fixed–Free / Cantilever (K=2.0)": 2.0,
}
def run_once(L_m, P_kN, E_GPa, Sy_MPa, b_m, h_m, end_condition):
try:
K = END_CONDITIONS[end_condition]
res, ver, steps = euler_buckling_rect(
float(L_m), float(P_kN), float(E_GPa), float(Sy_MPa),
float(b_m), float(h_m), float(K)
)
df = pd.DataFrame([{
"Pcr_x [kN]": round(res["Pcr_x_N"]/1e3, 3),
"Pcr_y [kN]": round(res["Pcr_y_N"]/1e3, 3),
"Pcr (governing) [kN]": round(res["Pcr_governing_N"]/1e3, 3),
"Applied P [kN]": round(res["P_applied_N"]/1e3, 3),
"FoS_buckling [-]": round(res["FoS_buckling"], 3),
"Slenderness (λ)": round(res["slenderness_governing"], 2),
"Governing axis": res["governing_axis"],
"Verdict": ver["message"],
}])
explain = (
f"Column buckles about {res['governing_axis']}: "
f"Pcr={res['Pcr_governing_N']/1e3:.2f} kN vs P={res['P_applied_N']/1e3:.2f} kN "
f"(FoS={res['FoS_buckling']:.2f}) → {ver['message']}."
)
return df, explain, steps, ""
except Exception as e:
return pd.DataFrame(), "", "", f"Input error:\n{e}"
with gr.Blocks(title="Column Buckling — Euler Elastic") as demo:
gr.Markdown("# Column Buckling Calculator — Euler Elastic (Rectangular Section)")
gr.Markdown(SCOPE_MD)
with gr.Row():
with gr.Column():
gr.Markdown("### Geometry & Material")
L_m = gr.Number(value=3.0, label="Length L [m]")
b_m = gr.Number(value=0.06, label="Width b [m]")
h_m = gr.Number(value=0.10, label="Height h [m]")
E_GPa = gr.Number(value=200., label="Elastic modulus E [GPa]")
Sy_MPa= gr.Number(value=250., label="Yield strength Sy [MPa] (context)")
with gr.Column():
gr.Markdown("### Load & End Condition")
P_kN = gr.Number(value=200.0, label="Applied load P [kN]")
end_condition = gr.Radio(
list(END_CONDITIONS.keys()),
value="Pinned–Pinned (K=1.0)",
label="End conditions (effective-length factor K)"
)
run_btn = gr.Button("Compute")
gr.Markdown("### Results")
results_df = gr.Dataframe(label="Numerical results", interactive=False)
gr.Markdown("### Explain the result")
explain_md = gr.Markdown()
gr.Markdown("### Show the math")
steps_md = gr.Markdown()
err_box = gr.Textbox(label="Errors", interactive=False)
run_btn.click(
fn=run_once,
inputs=[L_m, P_kN, E_GPa, Sy_MPa, b_m, h_m, end_condition],
outputs=[results_df, explain_md, steps_md, err_box]
)
if __name__ == "__main__":
demo.launch(debug=False)
|