apsora commited on
Commit
a744d63
·
verified ·
1 Parent(s): 25ba998

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -27
app.py CHANGED
@@ -7,7 +7,10 @@ TITLE = "Simply-Supported I-Beam"
7
  DESC = "Point load @ midspan or uniform load (UDL). SI units. Euler–Bernoulli."
8
 
9
  # ---------------- Deterministic backend ----------------
10
- def _compute(load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m, P_kN, w_kNpm, sigma_allow_MPa, defl_ratio):
 
 
 
11
  if L_m <= 0: raise ValueError("Span L must be > 0.")
12
  if E_GPa <= 0: raise ValueError("E must be > 0.")
13
  if Ix_m4 <= 0: raise ValueError("Ix must be > 0.")
@@ -17,19 +20,22 @@ def _compute(load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m, P_kN, w_kNpm, s
17
  if load_type == "Point @ midspan" and P_kN <= 0: raise ValueError("P must be > 0 for point load.")
18
  if load_type == "Uniform (UDL)" and w_kNpm <= 0: raise ValueError("w must be > 0 for UDL.")
19
 
 
20
  E = E_GPa * 1e9
21
  P = P_kN * 1e3
22
  w = w_kNpm * 1e3
23
 
 
24
  if has_Sx:
25
  Sx = Sx_m3
26
- c = Ix_m4 / Sx
27
- h = 2 * c
28
  else:
29
- h = depth_m
30
- c = h / 2
31
  Sx = Ix_m4 / c
32
 
 
33
  if load_type == "Point @ midspan":
34
  Mmax = P * L_m / 4.0
35
  dmax = P * (L_m**3) / (48.0 * E * Ix_m4)
@@ -39,46 +45,44 @@ def _compute(load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m, P_kN, w_kNpm, s
39
 
40
  sigma = Mmax / Sx
41
 
 
42
  stress_ok, SF = None, None
43
  if sigma_allow_MPa and sigma_allow_MPa > 0:
44
  sigma_MPa = sigma / 1e6
45
  SF = sigma_allow_MPa / max(sigma_MPa, 1e-12)
46
  stress_ok = sigma_MPa <= sigma_allow_MPa
 
47
  defl_ok, defl_lim = None, None
48
  if defl_ratio and defl_ratio > 0:
49
  defl_lim = (L_m * 1e3) / defl_ratio
50
  defl_ok = (dmax * 1e3) <= defl_lim
51
 
52
- # Build explanation
53
  text = []
54
  text.append(f"### 🔍 Contextual Explanation")
55
  text.append(f"**Beam Type:** Simply supported ({load_type.lower()}) with span **L = {L_m:.2f} m**.")
56
  text.append(f"**Material:** E = {E_GPa:.1f} GPa, **Section:** Ix = {Ix_m4:.2e} m⁴, Sx = {Sx:.2e} m³, depth = {h:.3f} m.")
57
-
58
  text.append(f"\n#### Results Overview")
59
  text.append(f"- Maximum bending moment **Mmax = {Mmax/1e3:.2f} kN·m**.")
60
  text.append(f"- Maximum deflection **δmax = {dmax*1e3:.3f} mm**, ratio **δ/L = {dmax/L_m:.5f}**.")
61
  text.append(f"- Bending stress **σmax = {sigma/1e6:.2f} MPa**.")
62
-
63
  if sigma_allow_MPa > 0:
64
  if stress_ok:
65
- text.append(f"✅ The beam’s stress **({sigma/1e6:.2f} MPa)** is below the allowable limit **({sigma_allow_MPa:.2f} MPa)**.")
66
  else:
67
- text.append(f"⚠️ The stress **({sigma/1e6:.2f} MPa)** exceeds the allowable limit **({sigma_allow_MPa:.2f} MPa)**.")
68
  if defl_ratio > 0:
69
  if defl_ok:
70
- text.append(f"✅ Deflection **({dmax*1e3:.3f} mm)** is within the limit (L/{defl_ratio:.0f} = {defl_lim:.2f} mm).")
71
  else:
72
- text.append(f"⚠️ Deflection **({dmax*1e3:.3f} mm)** exceeds the limit (L/{defl_ratio:.0f} = {defl_lim:.2f} mm).")
73
-
74
  text.append("\n#### Engineering Meaning")
75
- text.append("The bending moment represents how much internal torque the beam experiences due to the applied load. "
76
- "The deflection quantifies how much the beam bends under that load. "
77
- "A safe design keeps both the stress and deflection below their respective limits to avoid failure or excessive sagging.")
78
-
79
  context_text = "\n".join(text)
80
 
81
- return {
 
82
  "inputs": {
83
  "load_type": load_type,
84
  "L_m": L_m, "E_GPa": E_GPa, "Ix_m4": Ix_m4,
@@ -96,12 +100,14 @@ def _compute(load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m, P_kN, w_kNpm, s
96
  },
97
  "checks": {
98
  "stress_ok": stress_ok, "SF_stress": SF,
99
- "deflection_ok": defl_ok, "deflection_limit_mm": defl_lim,
100
- "deflection_ratio": defl_ratio or None,
101
  },
102
- "context": context_text
103
  }
104
 
 
 
 
105
  # ---------------- Gradio UI ----------------
106
  with gradio.Blocks() as demo:
107
  gradio.Markdown(f"# {TITLE}")
@@ -109,13 +115,13 @@ with gradio.Blocks() as demo:
109
 
110
  with gradio.Row():
111
  load_type = gradio.Radio(choices=["Point @ midspan", "Uniform (UDL)"], value="Point @ midspan", label="Load case")
112
- L_m = gradio.Number(value=3.0, label="Span L [m]", precision=4)
113
  E_GPa = gradio.Number(value=200.0, label="Young's modulus E [GPa]", precision=3)
114
  Ix_m4 = gradio.Number(value=8.0e-6, label="Second moment Ix [m^4]", precision=10)
115
 
116
  with gradio.Row():
117
  mode = gradio.Radio(choices=["I have Sx", "I have depth (h) only"], value="I have Sx", label="Section input")
118
- Sx_m3 = gradio.Number(value=4.0e-4, label="Section modulus Sx [m^3]", precision=8, visible=True)
119
  depth_m = gradio.Number(value=0.30, label="Depth h [m]", precision=4, visible=False)
120
 
121
  def _toggle(v):
@@ -123,20 +129,23 @@ with gradio.Blocks() as demo:
123
  mode.change(_toggle, inputs=mode, outputs=[Sx_m3, depth_m])
124
 
125
  with gradio.Row():
126
- P_kN = gradio.Number(value=20.0, label="Point load P [kN]", precision=3)
127
- w_kNpm = gradio.Number(value=5.0, label="UDL w [kN/m]", precision=4)
128
 
129
  with gradio.Row():
130
  sigma_allow = gradio.Number(value=250.0, label="Allowable stress [MPa] (0=skip)", precision=3)
131
- defl_ratio = gradio.Number(value=360, label="Deflection limit L/ratio (0=skip)", precision=0)
132
 
 
133
  with gradio.Tab("Numerical Results"):
134
  out = gradio.JSON(label="Results")
135
 
136
  with gradio.Tab("Understanding the Results"):
137
  context_out = gradio.Markdown()
138
 
139
- inputs = [load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m, P_kN, w_kNpm, sigma_allow, defl_ratio]
 
 
140
  for comp in inputs:
141
  comp.change(fn=_compute, inputs=inputs, outputs=[out, context_out])
142
 
 
7
  DESC = "Point load @ midspan or uniform load (UDL). SI units. Euler–Bernoulli."
8
 
9
  # ---------------- Deterministic backend ----------------
10
+ def _compute(load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m,
11
+ P_kN, w_kNpm, sigma_allow_MPa, defl_ratio):
12
+
13
+ # --- Validation ---
14
  if L_m <= 0: raise ValueError("Span L must be > 0.")
15
  if E_GPa <= 0: raise ValueError("E must be > 0.")
16
  if Ix_m4 <= 0: raise ValueError("Ix must be > 0.")
 
20
  if load_type == "Point @ midspan" and P_kN <= 0: raise ValueError("P must be > 0 for point load.")
21
  if load_type == "Uniform (UDL)" and w_kNpm <= 0: raise ValueError("w must be > 0 for UDL.")
22
 
23
+ # --- Units ---
24
  E = E_GPa * 1e9
25
  P = P_kN * 1e3
26
  w = w_kNpm * 1e3
27
 
28
+ # --- Section properties ---
29
  if has_Sx:
30
  Sx = Sx_m3
31
+ c = Ix_m4 / Sx
32
+ h = 2 * c
33
  else:
34
+ h = depth_m
35
+ c = h / 2
36
  Sx = Ix_m4 / c
37
 
38
+ # --- Beam formulas ---
39
  if load_type == "Point @ midspan":
40
  Mmax = P * L_m / 4.0
41
  dmax = P * (L_m**3) / (48.0 * E * Ix_m4)
 
45
 
46
  sigma = Mmax / Sx
47
 
48
+ # --- Checks ---
49
  stress_ok, SF = None, None
50
  if sigma_allow_MPa and sigma_allow_MPa > 0:
51
  sigma_MPa = sigma / 1e6
52
  SF = sigma_allow_MPa / max(sigma_MPa, 1e-12)
53
  stress_ok = sigma_MPa <= sigma_allow_MPa
54
+
55
  defl_ok, defl_lim = None, None
56
  if defl_ratio and defl_ratio > 0:
57
  defl_lim = (L_m * 1e3) / defl_ratio
58
  defl_ok = (dmax * 1e3) <= defl_lim
59
 
60
+ # --- Context text ---
61
  text = []
62
  text.append(f"### 🔍 Contextual Explanation")
63
  text.append(f"**Beam Type:** Simply supported ({load_type.lower()}) with span **L = {L_m:.2f} m**.")
64
  text.append(f"**Material:** E = {E_GPa:.1f} GPa, **Section:** Ix = {Ix_m4:.2e} m⁴, Sx = {Sx:.2e} m³, depth = {h:.3f} m.")
 
65
  text.append(f"\n#### Results Overview")
66
  text.append(f"- Maximum bending moment **Mmax = {Mmax/1e3:.2f} kN·m**.")
67
  text.append(f"- Maximum deflection **δmax = {dmax*1e3:.3f} mm**, ratio **δ/L = {dmax/L_m:.5f}**.")
68
  text.append(f"- Bending stress **σmax = {sigma/1e6:.2f} MPa**.")
 
69
  if sigma_allow_MPa > 0:
70
  if stress_ok:
71
+ text.append(f"✅ Stress **({sigma/1e6:.2f} MPa)** allowable **({sigma_allow_MPa:.2f} MPa)**.")
72
  else:
73
+ text.append(f"⚠️ Stress **({sigma/1e6:.2f} MPa)** exceeds allowable **({sigma_allow_MPa:.2f} MPa)**.")
74
  if defl_ratio > 0:
75
  if defl_ok:
76
+ text.append(f"✅ Deflection **({dmax*1e3:.3f} mm)** limit (L/{defl_ratio:.0f} = {defl_lim:.2f} mm).")
77
  else:
78
+ text.append(f"⚠️ Deflection **({dmax*1e3:.3f} mm)** exceeds limit (L/{defl_ratio:.0f} = {defl_lim:.2f} mm).")
 
79
  text.append("\n#### Engineering Meaning")
80
+ text.append("The bending moment represents internal torque; deflection is beam sag. "
81
+ "Safe design ensures both remain below limits to prevent failure or deformation.")
 
 
82
  context_text = "\n".join(text)
83
 
84
+ # --- Return two outputs ---
85
+ data = {
86
  "inputs": {
87
  "load_type": load_type,
88
  "L_m": L_m, "E_GPa": E_GPa, "Ix_m4": Ix_m4,
 
100
  },
101
  "checks": {
102
  "stress_ok": stress_ok, "SF_stress": SF,
103
+ "deflection_ok": defl_ok,
104
+ "deflection_limit_mm": defl_lim, "deflection_ratio": defl_ratio or None,
105
  },
 
106
  }
107
 
108
+ return data, context_text
109
+
110
+
111
  # ---------------- Gradio UI ----------------
112
  with gradio.Blocks() as demo:
113
  gradio.Markdown(f"# {TITLE}")
 
115
 
116
  with gradio.Row():
117
  load_type = gradio.Radio(choices=["Point @ midspan", "Uniform (UDL)"], value="Point @ midspan", label="Load case")
118
+ L_m = gradio.Number(value=3.0, label="Span L [m]", precision=4)
119
  E_GPa = gradio.Number(value=200.0, label="Young's modulus E [GPa]", precision=3)
120
  Ix_m4 = gradio.Number(value=8.0e-6, label="Second moment Ix [m^4]", precision=10)
121
 
122
  with gradio.Row():
123
  mode = gradio.Radio(choices=["I have Sx", "I have depth (h) only"], value="I have Sx", label="Section input")
124
+ Sx_m3 = gradio.Number(value=4.0e-4, label="Section modulus Sx [m^3]", precision=8, visible=True)
125
  depth_m = gradio.Number(value=0.30, label="Depth h [m]", precision=4, visible=False)
126
 
127
  def _toggle(v):
 
129
  mode.change(_toggle, inputs=mode, outputs=[Sx_m3, depth_m])
130
 
131
  with gradio.Row():
132
+ P_kN = gradio.Number(value=20.0, label="Point load P [kN]", precision=3)
133
+ w_kNpm = gradio.Number(value=5.0, label="UDL w [kN/m]", precision=4)
134
 
135
  with gradio.Row():
136
  sigma_allow = gradio.Number(value=250.0, label="Allowable stress [MPa] (0=skip)", precision=3)
137
+ defl_ratio = gradio.Number(value=360, label="Deflection limit L/ratio (0=skip)", precision=0)
138
 
139
+ # --- Two output sections ---
140
  with gradio.Tab("Numerical Results"):
141
  out = gradio.JSON(label="Results")
142
 
143
  with gradio.Tab("Understanding the Results"):
144
  context_out = gradio.Markdown()
145
 
146
+ inputs = [load_type, L_m, E_GPa, Ix_m4, mode, Sx_m3, depth_m,
147
+ P_kN, w_kNpm, sigma_allow, defl_ratio]
148
+
149
  for comp in inputs:
150
  comp.change(fn=_compute, inputs=inputs, outputs=[out, context_out])
151