HW3_NLE / app.py
mohitk24's picture
Upload folder using huggingface_hub
0ad8067 verified
import math as m
import gradio as gr
import pandas as pd
import numpy as np
from math import log10, pi
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
# Assuming darcy_weisbach_calculation and explain_results functions are defined elsewhere or in this string
# For this example, I'll include them for completeness. In a real scenario,
# you might have these in separate files or ensure they are defined before this string.
def darcy_weisbach_calculation(
rho, # kg/m^3
mu, # Pa·s
D, # m
L, # m
Q, # m^3/s
eps=1.5e-6 # m, absolute roughness (default ~ smooth steel)
):
"""
Assumptions:
- Steady, incompressible, Newtonian fluid
- Fully developed internal flow in a straight, horizontal, circular pipe
- Single-phase, isothermal
- Darcy friction factor: laminar f=64/Re; turbulent via Swamee–Jain explicit fit
Valid ranges (typical sanity):
- 500 <= rho <= 2000 kg/m^3
- 0.2e-3 <= mu <= 5e-3 Pa·s
- 0.005 <= D <= 1.0 m
- 0.5 <= L <= 1000 m
- 1e-5 <= Q <= 2.0 m^3/s
- 0 <= eps <= 5e-3 m
"""
# Derived quantities
A = pi*(D**2)/4.0
v = Q / A
Re = rho * v * D / mu
# Friction factor
if Re < 2300:
f = 64.0 / max(Re, 1e-9) # protect division
regime = "laminar"
else:
# Swamee–Jain explicit approximation for turbulent flow
# f = 0.25 / [log10( (eps/(3.7D)) + (5.74/Re^0.9) )]^2
term = (eps/(3.7*D)) + (5.74/(Re**0.9))
f = 0.25 / (log10(term)**2)
regime = "turbulent"
# Darcy–Weisbach head loss: h_f = f*(L/D)*(v^2/(2g))
g = 9.80665 # m/s^2
hf = f * (L/D) * (v**2/(2*g))
# Pressure drop: ΔP = rho*g*h_f
dP = rho * g * hf
# Structured, human-readable message
message = {
"title": "Darcy–Weisbach Head Loss Calculator",
"scope": [
"Steady, incompressible, fully developed flow in a straight circular pipe",
"Single-phase, isothermal, horizontal run"
],
"assumptions": [
"Newtonian fluid",
"Darcy friction factor: laminar f=64/Re; turbulent via Swamee–Jain explicit formula",
"No fittings/minor losses included"
],
"inputs": {
"density_rho_kg_per_m3": rho,
"viscosity_mu_Pa_s": mu,
"diameter_D_m": D,
"length_L_m": L,
"flow_rate_Q_m3_per_s": Q,
"roughness_eps_m": eps
},
"derived": {
"area_A_m2": A,
"avg_velocity_v_m_per_s": v,
"Reynolds_Re": Re,
"friction_factor_f": f,
"flow_regime": regime
},
"outputs": {
"head_loss_hf_m": hf,
"pressure_drop_dP_Pa": dP
},
"formulas": [
"A = π D^2 / 4",
"v = Q / A",
"Re = ρ v D / μ",
"Laminar: f = 64 / Re",
"Turbulent: f = 0.25 / [log10(ε/(3.7D) + 5.74/Re^0.9)]^2",
"h_f = f (L/D) (v^2 / (2g))",
"ΔP = ρ g h_f"
],
"constants": {
"g_m_per_s2": g
},
"notes": [
"For turbulent flow with significant fittings, include minor losses separately.",
"Check cavitation or NPSH if near pumps; this tool reports line loss only."
],
"valid_ranges": {
"rho_kg_per_m3": [500, 2000],
"mu_Pa_s": [0.0002, 0.005],
"D_m": [0.005, 1.0],
"L_m": [0.5, 1000],
"Q_m3_per_s": [1e-5, 2.0],
"eps_m": [0.0, 0.005]
}
}
return message
# Small instruction-tuned model for concise, low-latency explanations.
# Change model if desired; keep it tiny for Spaces CPU.
model_id = "hf-internal-testing/tiny-random-LlamaForCausalLM" # placeholder tiny model
# For practical explanations, replace with a small instruct model like:
# model_id = "HuggingFaceH4/zephyr-7b-alpha" # requires more resources
# or a tiny flan-t5: "google/flan-t5-small"
def load_llm_pipeline(model_name=model_id, task="text2text-generation"): # Changed task to text2text-generation
try:
pipe = pipeline(task, model=model_name, device_map="auto")
except Exception:
# Fallback small model available in most environments
pipe = pipeline(task, model="google/flan-t5-small")
return pipe
llm = load_llm_pipeline()
def explain_results(structured_message):
# Convert the structured dict into a readable block and prompt the LLM
import json
context = json.dumps(structured_message, indent=2)
prompt = (
"You are an engineering tutor. Read the structured calculation JSON and produce a clear, concise explanation for a non-expert.\n"
"Goals:\n"
"- This tool calculates pressure loss in a straight pipe using the Darcy-Weisbach equation. It assumes steady, incompressible, Newtonian fluid flow in a horizontal pipe and calculates friction based on flow regime (laminar or turbulent).\n\n" # Fixed escaping
"- Highlight the formulas and what they mean physically.\n"
"- Interpret the Reynolds number and friction factor.\n"
"- Explain head loss and pressure drop magnitudes and practical implications.\n"
"- If inputs look out of typical ranges, gently flag them.\n"
"Stay under 180 words. Avoid equations in LaTeX; use plain words.\n\n"
f"JSON:\n{{context}}\n\n"
"Explanation:"
)
out = llm(prompt, max_new_tokens=220)
text = out[0]["generated_text"] if isinstance(out, list) else str(out)
# In case the model echoes the prompt, try to extract the tail
if "Explanation:" in text:
text = text.split("Explanation:", 1)[-1].strip()
return text
def run_calc(rho, mu, D, L, Q, eps):
msg = darcy_weisbach_calculation(rho, mu, D, L, Q, eps)
# Numeric panel summary
out_lines = []
out = msg["outputs"]
der = msg["derived"]
out_lines.append(f"Reynolds number: {der['Reynolds_Re']:.0f}")
out_lines.append(f"Friction factor: {der['friction_factor_f']:.5f} ({der['flow_regime']})")
out_lines.append(f"Head loss h_f: {out['head_loss_hf_m']:.4f} m")
out_lines.append(f"Pressure drop ΔP: {out['pressure_drop_dP_Pa']:.1f} Pa")
numeric_panel = "\n".join(out_lines)
# Explanation via LLM
explanation = explain_results(msg)
return numeric_panel, explanation
with gr.Blocks() as demo:
gr.Markdown("# Darcy–Weisbach Pipe Loss (Deterministic)")
with gr.Row():
with gr.Column():
rho = gr.Slider(500, 2000, value=998.0, step=1.0, label="Density ρ (kg/m³)")
mu = gr.Slider(0.0002, 0.005, value=0.0010, step=0.0001, label="Viscosity μ (Pa·s)")
D = gr.Slider(0.005, 1.0, value=0.05, step=0.001, label="Diameter D (m)")
L = gr.Slider(0.5, 1000.0, value=50.0, step=0.5, label="Length L (m)")
Q = gr.Slider(1e-5, 2.0, value=0.005, step=1e-4, label="Flow rate Q (m³/s)")
eps= gr.Slider(0.0, 0.005, value=1.5e-6, step=1e-6, label="Roughness ε (m)")
run_btn = gr.Button("Compute")
with gr.Column():
numeric = gr.Textbox(label="Numerical results", lines=6)
# Assuming 'explain' is defined elsewhere, e.g., as a gr.Textbox
# If not, you might need to define it here:
explain = gr.Textbox(label="Explanation", lines=10)
examples = gr.Examples(
examples=[
[998.0, 0.0010, 0.05, 50.0, 0.005, 1.5e-6], # Water, smooth steel
[870.0, 0.0015, 0.10, 200.0, 0.03, 4.5e-5], # Light oil, commercial steel
[1000.0, 0.0008, 0.02, 10.0, 0.0002, 1.0e-6] # Small tube, low flow
],
inputs=[rho, mu, D, L, Q, eps]
)
run_btn.click(run_calc, inputs=[rho, mu, D, L, Q, eps], outputs=[numeric, explain])
# Comment out the demo.launch() call as it will be handled by the Hugio Face Space
demo.launch(share=False, server_name="0.0.0.0") # Uncomment and add arguments for Space