Spaces:
Sleeping
Sleeping
File size: 6,675 Bytes
315fce5 a744d63 315fce5 25ba998 315fce5 a744d63 25ba998 315fce5 a744d63 315fce5 a744d63 315fce5 a744d63 315fce5 a744d63 315fce5 25ba998 315fce5 25ba998 315fce5 a744d63 315fce5 a744d63 315fce5 a744d63 25ba998 a744d63 25ba998 a744d63 25ba998 a744d63 25ba998 a744d63 25ba998 a744d63 25ba998 a744d63 315fce5 a744d63 315fce5 a744d63 25ba998 315fce5 a744d63 315fce5 a744d63 25ba998 315fce5 a744d63 315fce5 a744d63 25ba998 a744d63 25ba998 315fce5 25ba998 315fce5 a744d63 315fce5 25ba998 315fce5 25ba998 315fce5 |
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 |
import math
import gradio
import pandas as pd
# ---------------- Settings ----------------
TITLE = "Simply-Supported I-Beam"
DESC = "Point load @ midspan or uniform load (UDL). SI units. Euler–Bernoulli."
# ---------------- Deterministic backend ----------------
def _compute(load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m,
P_kN, w_kNpm, sigma_allow_MPa, defl_ratio):
# --- Validation ---
if L_m <= 0: raise ValueError("Span L must be > 0.")
if E_GPa <= 0: raise ValueError("E must be > 0.")
if Ix_m4 <= 0: raise ValueError("Ix must be > 0.")
has_Sx = (mode == "I have Sx")
if has_Sx and Sx_m3 <= 0: raise ValueError("Sx must be > 0.")
if (not has_Sx) and depth_m <= 0: raise ValueError("Depth must be > 0 when Sx not provided.")
if load_type == "Point @ midspan" and P_kN <= 0: raise ValueError("P must be > 0 for point load.")
if load_type == "Uniform (UDL)" and w_kNpm <= 0: raise ValueError("w must be > 0 for UDL.")
# --- Units ---
E = E_GPa * 1e9
P = P_kN * 1e3
w = w_kNpm * 1e3
# --- Section properties ---
if has_Sx:
Sx = Sx_m3
c = Ix_m4 / Sx
h = 2 * c
else:
h = depth_m
c = h / 2
Sx = Ix_m4 / c
# --- Beam formulas ---
if load_type == "Point @ midspan":
Mmax = P * L_m / 4.0
dmax = P * (L_m**3) / (48.0 * E * Ix_m4)
else:
Mmax = w * (L_m**2) / 8.0
dmax = 5.0 * w * (L_m**4) / (384.0 * E * Ix_m4)
sigma = Mmax / Sx
# --- Checks ---
stress_ok, SF = None, None
if sigma_allow_MPa and sigma_allow_MPa > 0:
sigma_MPa = sigma / 1e6
SF = sigma_allow_MPa / max(sigma_MPa, 1e-12)
stress_ok = sigma_MPa <= sigma_allow_MPa
defl_ok, defl_lim = None, None
if defl_ratio and defl_ratio > 0:
defl_lim = (L_m * 1e3) / defl_ratio
defl_ok = (dmax * 1e3) <= defl_lim
# --- Context text ---
text = []
text.append(f"### 🔍 Contextual Explanation")
text.append(f"**Beam Type:** Simply supported ({load_type.lower()}) with span **L = {L_m:.2f} m**.")
text.append(f"**Material:** E = {E_GPa:.1f} GPa, **Section:** Ix = {Ix_m4:.2e} m⁴, Sx = {Sx:.2e} m³, depth = {h:.3f} m.")
text.append(f"\n#### Results Overview")
text.append(f"- Maximum bending moment **Mmax = {Mmax/1e3:.2f} kN·m**.")
text.append(f"- Maximum deflection **δmax = {dmax*1e3:.3f} mm**, ratio **δ/L = {dmax/L_m:.5f}**.")
text.append(f"- Bending stress **σmax = {sigma/1e6:.2f} MPa**.")
if sigma_allow_MPa > 0:
if stress_ok:
text.append(f"✅ Stress **({sigma/1e6:.2f} MPa)** ≤ allowable **({sigma_allow_MPa:.2f} MPa)**.")
else:
text.append(f"⚠️ Stress **({sigma/1e6:.2f} MPa)** exceeds allowable **({sigma_allow_MPa:.2f} MPa)**.")
if defl_ratio > 0:
if defl_ok:
text.append(f"✅ Deflection **({dmax*1e3:.3f} mm)** ≤ limit (L/{defl_ratio:.0f} = {defl_lim:.2f} mm).")
else:
text.append(f"⚠️ Deflection **({dmax*1e3:.3f} mm)** exceeds limit (L/{defl_ratio:.0f} = {defl_lim:.2f} mm).")
text.append("\n#### Engineering Meaning")
text.append("The bending moment represents internal torque; deflection is beam sag. "
"Safe design ensures both remain below limits to prevent failure or deformation.")
context_text = "\n".join(text)
# --- Return two outputs ---
data = {
"inputs": {
"load_type": load_type,
"L_m": L_m, "E_GPa": E_GPa, "Ix_m4": Ix_m4,
"Sx_m3": Sx, "depth_m": h,
"P_kN": P_kN if load_type.startswith("Point") else 0.0,
"w_kN_per_m": w_kNpm if load_type.startswith("Uniform") else 0.0,
"sigma_allow_MPa": sigma_allow_MPa or None,
"deflection_ratio": defl_ratio or None,
},
"solution": {
"M_max_kN_m": Mmax / 1e3,
"sigma_max_MPa": sigma / 1e6,
"delta_max_mm": dmax * 1e3,
"delta_over_L": dmax / L_m,
},
"checks": {
"stress_ok": stress_ok, "SF_stress": SF,
"deflection_ok": defl_ok,
"deflection_limit_mm": defl_lim, "deflection_ratio": defl_ratio or None,
},
}
return data, context_text
# ---------------- Gradio UI ----------------
with gradio.Blocks() as demo:
gradio.Markdown(f"# {TITLE}")
gradio.Markdown(DESC)
with gradio.Row():
load_type = gradio.Radio(choices=["Point @ midspan", "Uniform (UDL)"], value="Point @ midspan", label="Load case")
L_m = gradio.Number(value=3.0, label="Span L [m]", precision=4)
E_GPa = gradio.Number(value=200.0, label="Young's modulus E [GPa]", precision=3)
Ix_m4 = gradio.Number(value=8.0e-6, label="Second moment Ix [m^4]", precision=10)
with gradio.Row():
mode = gradio.Radio(choices=["I have Sx", "I have depth (h) only"], value="I have Sx", label="Section input")
Sx_m3 = gradio.Number(value=4.0e-4, label="Section modulus Sx [m^3]", precision=8, visible=True)
depth_m = gradio.Number(value=0.30, label="Depth h [m]", precision=4, visible=False)
def _toggle(v):
return gradio.update(visible=(v=="I have Sx")), gradio.update(visible=(v!="I have Sx"))
mode.change(_toggle, inputs=mode, outputs=[Sx_m3, depth_m])
with gradio.Row():
P_kN = gradio.Number(value=20.0, label="Point load P [kN]", precision=3)
w_kNpm = gradio.Number(value=5.0, label="UDL w [kN/m]", precision=4)
with gradio.Row():
sigma_allow = gradio.Number(value=250.0, label="Allowable stress [MPa] (0=skip)", precision=3)
defl_ratio = gradio.Number(value=360, label="Deflection limit L/ratio (0=skip)", precision=0)
# --- Two output sections ---
with gradio.Tab("Numerical Results"):
out = gradio.JSON(label="Results")
with gradio.Tab("Understanding the Results"):
context_out = gradio.Markdown()
inputs = [load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m,
P_kN, w_kNpm, sigma_allow, defl_ratio]
for comp in inputs:
comp.change(fn=_compute, inputs=inputs, outputs=[out, context_out])
gradio.Examples(
examples=[
["Point @ midspan", 3.0, 200.0, 8.0e-6, "I have Sx", 4.0e-4, 0.30, 20.0, 0.0, 250.0, 360],
["Uniform (UDL)", 4.5, 200.0, 1.2e-5, "I have Sx", 6.0e-4, 0.35, 0.0, 8.0, 200.0, 360],
["Uniform (UDL)", 2.5, 70.0, 3.5e-6, "I have depth (h) only", 0.0, 0.22, 0.0, 6.0, 160.0, 240],
],
inputs=inputs,
label="Examples",
cache_examples=False,
)
demo.launch()
|