File size: 4,826 Bytes
451dbc3
 
 
 
 
 
 
 
 
 
 
 
 
cc767c4
 
 
451dbc3
 
cc767c4
 
 
 
 
 
 
 
451dbc3
cc767c4
 
 
 
 
 
 
 
 
 
 
 
451dbc3
 
cc767c4
 
 
 
 
451dbc3
cc767c4
 
 
 
451dbc3
cc767c4
 
 
451dbc3
cc767c4
451dbc3
 
cc767c4
 
451dbc3
 
cc767c4
 
 
 
 
451dbc3
cc767c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451dbc3
cc767c4
 
451dbc3
 
 
cc767c4
 
 
 
 
451dbc3
 
cc767c4
 
 
451dbc3
 
 
 
cc767c4
 
451dbc3
 
cc767c4
 
 
451dbc3
 
 
cc767c4
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
# -*- coding: utf-8 -*-
"""Untitled3.ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/11sS74P6WlrbXCzSh9_b8ELPTtcfdsz8s
"""

# -*- coding: utf-8 -*-
# HW3: Deterministic calculator + LLM explanation (Gradio)
# Topic: Simply supported beam with center point load (max bending stress & midspan deflection)

# -*- coding: utf-8 -*-
# HW3: Deterministic calculator + Gradio + LLM explanation
# Simply Supported Beam with Center Load

import gradio as gr
import math
import json
from transformers import pipeline

# -------------------------------
# 1. Deterministic backend function
# -------------------------------
def beam_calculator(L, P, E, I, c, sigma_allow=250.0, fy=350.0, n=1.5):
    """
    Deterministic first-principles calculation for a simply supported beam
    under a central point load.
    
    Inputs:
        L  (m): span length
        P  (kN): central load
        E  (GPa): elastic modulus
        I  (cm^4): second moment of area
        c  (cm): extreme fiber distance
        sigma_allow (MPa): allowable stress
        fy (MPa): yield strength
        n (–): safety factor
    """

    # --- Unit conversions ---
    P_N = P * 1000        # kN -> N
    E_Pa = E * 1e9        # GPa -> Pa
    I_m4 = I * 1e-8       # cm^4 -> m^4
    c_m = c / 100.0       # cm -> m

    # --- Mechanics formulas ---
    M_max = P_N * L / 4.0                      # Max bending moment (N·m)
    delta_max = (P_N * L**3) / (48 * E_Pa * I_m4)  # Max deflection (m)
    sigma_max = M_max * c_m / I_m4 / 1e6       # Max stress (MPa)

    # --- Safety checks ---
    utilization_stress = sigma_max / sigma_allow
    utilization_yield = sigma_max / (fy / n)

    # Structured record
    record = {
        "inputs": {
            "L_m": L, "P_kN": P, "E_GPa": E, "I_cm4": I, "c_cm": c,
            "sigma_allow_MPa": sigma_allow, "fy_MPa": fy, "safety_factor": n
        },
        "results": {
            "M_max_Nm": M_max,
            "delta_max_m": delta_max,
            "sigma_max_MPa": sigma_max,
            "utilization_vs_allow": utilization_stress,
            "utilization_vs_yield": utilization_yield
        }
    }
    return record

# -------------------------------
# 2. LLM Explanation
# -------------------------------
explainer = pipeline("text-generation", model="distilgpt2")

def explain_results(record):
    """Use LLM to produce a clear explanation grounded in numbers."""
    text = json.dumps(record, indent=2)
    prompt = f"""
You are an engineering assistant. A beam calculation was performed.
Here are the structured results:

{text}

Explain the results to a civil engineering student in plain English:
- Report the maximum bending moment, stress, and deflection.
- Compare stress with allowable stress and yield strength.
- State clearly if the beam is safe or unsafe.
Avoid speculation. Base explanation only on the provided numbers.
"""
    explanation = explainer(prompt, max_new_tokens=200)[0]["generated_text"]
    return explanation

# -------------------------------
# 3. Wrapper for Gradio
# -------------------------------
def run_calculation(L, P, E, I, c, sigma_allow, fy, n):
    try:
        rec = beam_calculator(L, P, E, I, c, sigma_allow, fy, n)
        explanation = explain_results(rec)
        return json.dumps(rec["results"], indent=2), explanation
    except Exception as e:
        return {"error": str(e)}, "Error during calculation."

# -------------------------------
# 4. Gradio UI
# -------------------------------
with gr.Blocks() as demo:
    gr.Markdown("# Simply Supported Beam — Center Load")
    gr.Markdown("Deterministic calculator + LLM explanation (first principles).")

    with gr.Row():
        with gr.Column():
            L = gr.Slider(0.5, 30.0, value=2.0, label="Span L (m)")
            P = gr.Slider(0.1, 500.0, value=10.0, label="Center load P (kN)")
            E = gr.Slider(10, 300, value=200, label="Elastic modulus E (GPa)")
            I = gr.Number(value=8000, label="Second moment of area I (cm^4)")
            c = gr.Number(value=15, label="Extreme fiber distance c (cm)")

            with gr.Accordion("Optional: Allowables", open=False):
                sigma_allow = gr.Number(value=250, label="Allowable stress σ_allow (MPa)")
                fy = gr.Number(value=350, label="Yield strength fy (MPa)")
                n = gr.Number(value=1.5, label="Safety factor n")

            run_btn = gr.Button("Compute")

        with gr.Column():
            results_out = gr.Textbox(label="Numerical Results")
            explain_out = gr.Textbox(label="LLM Explanation")

    run_btn.click(
        fn=run_calculation,
        inputs=[L, P, E, I, c, sigma_allow, fy, n],
        outputs=[results_out, explain_out],
    )

if __name__ == "__main__":
    demo.launch()