Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse files
app.py
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import math as m
|
| 3 |
+
import gradio as gr
|
| 4 |
+
import pandas as pd
|
| 5 |
+
import numpy as np
|
| 6 |
+
from math import log10, pi
|
| 7 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
|
| 8 |
+
|
| 9 |
+
# Assuming darcy_weisbach_calculation and explain_results functions are defined elsewhere or in this string
|
| 10 |
+
# For this example, I'll include them for completeness. In a real scenario,
|
| 11 |
+
# you might have these in separate files or ensure they are defined before this string.
|
| 12 |
+
|
| 13 |
+
def darcy_weisbach_calculation(
|
| 14 |
+
rho, # kg/m^3
|
| 15 |
+
mu, # Pa路s
|
| 16 |
+
D, # m
|
| 17 |
+
L, # m
|
| 18 |
+
Q, # m^3/s
|
| 19 |
+
eps=1.5e-6 # m, absolute roughness (default ~ smooth steel)
|
| 20 |
+
):
|
| 21 |
+
"""
|
| 22 |
+
Assumptions:
|
| 23 |
+
- Steady, incompressible, Newtonian fluid
|
| 24 |
+
- Fully developed internal flow in a straight, horizontal, circular pipe
|
| 25 |
+
- Single-phase, isothermal
|
| 26 |
+
- Darcy friction factor: laminar f=64/Re; turbulent via Swamee鈥揓ain explicit fit
|
| 27 |
+
Valid ranges (typical sanity):
|
| 28 |
+
- 500 <= rho <= 2000 kg/m^3
|
| 29 |
+
- 0.2e-3 <= mu <= 5e-3 Pa路s
|
| 30 |
+
- 0.005 <= D <= 1.0 m
|
| 31 |
+
- 0.5 <= L <= 1000 m
|
| 32 |
+
- 1e-5 <= Q <= 2.0 m^3/s
|
| 33 |
+
- 0 <= eps <= 5e-3 m
|
| 34 |
+
"""
|
| 35 |
+
# Derived quantities
|
| 36 |
+
A = pi*(D**2)/4.0
|
| 37 |
+
v = Q / A
|
| 38 |
+
Re = rho * v * D / mu
|
| 39 |
+
|
| 40 |
+
# Friction factor
|
| 41 |
+
if Re < 2300:
|
| 42 |
+
f = 64.0 / max(Re, 1e-9) # protect division
|
| 43 |
+
regime = "laminar"
|
| 44 |
+
else:
|
| 45 |
+
# Swamee鈥揓ain explicit approximation for turbulent flow
|
| 46 |
+
# f = 0.25 / [log10( (eps/(3.7D)) + (5.74/Re^0.9) )]^2
|
| 47 |
+
term = (eps/(3.7*D)) + (5.74/(Re**0.9))
|
| 48 |
+
f = 0.25 / (log10(term)**2)
|
| 49 |
+
regime = "turbulent"
|
| 50 |
+
|
| 51 |
+
# Darcy鈥揥eisbach head loss: h_f = f*(L/D)*(v^2/(2g))
|
| 52 |
+
g = 9.80665 # m/s^2
|
| 53 |
+
hf = f * (L/D) * (v**2/(2*g))
|
| 54 |
+
|
| 55 |
+
# Pressure drop: 螖P = rho*g*h_f
|
| 56 |
+
dP = rho * g * hf
|
| 57 |
+
|
| 58 |
+
# Structured, human-readable message
|
| 59 |
+
message = {
|
| 60 |
+
"title": "Darcy鈥揥eisbach Head Loss Calculator",
|
| 61 |
+
"scope": [
|
| 62 |
+
"Steady, incompressible, fully developed flow in a straight circular pipe",
|
| 63 |
+
"Single-phase, isothermal, horizontal run"
|
| 64 |
+
],
|
| 65 |
+
"assumptions": [
|
| 66 |
+
"Newtonian fluid",
|
| 67 |
+
"Darcy friction factor: laminar f=64/Re; turbulent via Swamee鈥揓ain explicit formula",
|
| 68 |
+
"No fittings/minor losses included"
|
| 69 |
+
],
|
| 70 |
+
"inputs": {
|
| 71 |
+
"density_rho_kg_per_m3": rho,
|
| 72 |
+
"viscosity_mu_Pa_s": mu,
|
| 73 |
+
"diameter_D_m": D,
|
| 74 |
+
"length_L_m": L,
|
| 75 |
+
"flow_rate_Q_m3_per_s": Q,
|
| 76 |
+
"roughness_eps_m": eps
|
| 77 |
+
},
|
| 78 |
+
"derived": {
|
| 79 |
+
"area_A_m2": A,
|
| 80 |
+
"avg_velocity_v_m_per_s": v,
|
| 81 |
+
"Reynolds_Re": Re,
|
| 82 |
+
"friction_factor_f": f,
|
| 83 |
+
"flow_regime": regime
|
| 84 |
+
},
|
| 85 |
+
"outputs": {
|
| 86 |
+
"head_loss_hf_m": hf,
|
| 87 |
+
"pressure_drop_dP_Pa": dP
|
| 88 |
+
},
|
| 89 |
+
"formulas": [
|
| 90 |
+
"A = 蟺 D^2 / 4",
|
| 91 |
+
"v = Q / A",
|
| 92 |
+
"Re = 蟻 v D / 渭",
|
| 93 |
+
"Laminar: f = 64 / Re",
|
| 94 |
+
"Turbulent: f = 0.25 / [log10(蔚/(3.7D) + 5.74/Re^0.9)]^2",
|
| 95 |
+
"h_f = f (L/D) (v^2 / (2g))",
|
| 96 |
+
"螖P = 蟻 g h_f"
|
| 97 |
+
],
|
| 98 |
+
"constants": {
|
| 99 |
+
"g_m_per_s2": g
|
| 100 |
+
},
|
| 101 |
+
"notes": [
|
| 102 |
+
"For turbulent flow with significant fittings, include minor losses separately.",
|
| 103 |
+
"Check cavitation or NPSH if near pumps; this tool reports line loss only."
|
| 104 |
+
],
|
| 105 |
+
"valid_ranges": {
|
| 106 |
+
"rho_kg_per_m3": [500, 2000],
|
| 107 |
+
"mu_Pa_s": [0.0002, 0.005],
|
| 108 |
+
"D_m": [0.005, 1.0],
|
| 109 |
+
"L_m": [0.5, 1000],
|
| 110 |
+
"Q_m3_per_s": [1e-5, 2.0],
|
| 111 |
+
"eps_m": [0.0, 0.005]
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
return message
|
| 115 |
+
|
| 116 |
+
# Small instruction-tuned model for concise, low-latency explanations.
|
| 117 |
+
# Change model if desired; keep it tiny for Spaces CPU.
|
| 118 |
+
model_id = "hf-internal-testing/tiny-random-LlamaForCausalLM" # placeholder tiny model
|
| 119 |
+
# For practical explanations, replace with a small instruct model like:
|
| 120 |
+
# model_id = "HuggingFaceH4/zephyr-7b-alpha" # requires more resources
|
| 121 |
+
# or a tiny flan-t5: "google/flan-t5-small"
|
| 122 |
+
|
| 123 |
+
def load_llm_pipeline(model_name=model_id, task="text-generation"):
|
| 124 |
+
try:
|
| 125 |
+
pipe = pipeline(task, model=model_name, device_map="auto")
|
| 126 |
+
except Exception:
|
| 127 |
+
# Fallback small model available in most environments
|
| 128 |
+
pipe = pipeline(task, model="google/flan-t5-small")
|
| 129 |
+
return pipe
|
| 130 |
+
|
| 131 |
+
llm = load_llm_pipeline()
|
| 132 |
+
|
| 133 |
+
def explain_results(structured_message):
|
| 134 |
+
# Convert the structured dict into a readable block and prompt the LLM
|
| 135 |
+
import json
|
| 136 |
+
context = json.dumps(structured_message, indent=2)
|
| 137 |
+
|
| 138 |
+
prompt = (
|
| 139 |
+
"You are an engineering tutor. Read the structured calculation JSON and produce a clear, concise explanation for a non-expert.
|
| 140 |
+
"
|
| 141 |
+
"Goals:
|
| 142 |
+
"
|
| 143 |
+
"- Briefly restate the problem and assumptions.
|
| 144 |
+
"
|
| 145 |
+
"- Highlight the formulas and what they mean physically.
|
| 146 |
+
"
|
| 147 |
+
"- Interpret the Reynolds number and friction factor.
|
| 148 |
+
"
|
| 149 |
+
"- Explain head loss and pressure drop magnitudes and practical implications.
|
| 150 |
+
"
|
| 151 |
+
"- If inputs look out of typical ranges, gently flag them.
|
| 152 |
+
"
|
| 153 |
+
"Stay under 180 words. Avoid equations in LaTeX; use plain words.
|
| 154 |
+
|
| 155 |
+
"
|
| 156 |
+
f"JSON:
|
| 157 |
+
{context}
|
| 158 |
+
|
| 159 |
+
"
|
| 160 |
+
"Explanation:"
|
| 161 |
+
)
|
| 162 |
+
out = llm(prompt, max_new_tokens=220)
|
| 163 |
+
text = out[0]["generated_text"] if isinstance(out, list) else str(out)
|
| 164 |
+
# In case the model echoes the prompt, try to extract the tail
|
| 165 |
+
if "Explanation:" in text:
|
| 166 |
+
text = text.split("Explanation:", 1)[-1].strip()
|
| 167 |
+
return text
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def run_calc(rho, mu, D, L, Q, eps):
|
| 171 |
+
msg = darcy_weisbach_calculation(rho, mu, D, L, Q, eps)
|
| 172 |
+
# Numeric panel summary
|
| 173 |
+
out_lines = []
|
| 174 |
+
out = msg["outputs"]
|
| 175 |
+
der = msg["derived"]
|
| 176 |
+
out_lines.append(f"Reynolds number: {der['Reynolds_Re']:.0f}")
|
| 177 |
+
out_lines.append(f"Friction factor: {der['friction_factor_f']:.5f} ({der['flow_regime']})")
|
| 178 |
+
out_lines.append(f"Head loss h_f: {out['head_loss_hf_m']:.4f} m")
|
| 179 |
+
out_lines.append(f"Pressure drop 螖P: {out['pressure_drop_dP_Pa']:.1f} Pa")
|
| 180 |
+
numeric_panel = "
|
| 181 |
+
".join(out_lines)
|
| 182 |
+
|
| 183 |
+
# Explanation via LLM
|
| 184 |
+
explanation = explain_results(msg)
|
| 185 |
+
return numeric_panel, explanation
|
| 186 |
+
|
| 187 |
+
with gr.Blocks() as demo:
|
| 188 |
+
gr.Markdown("# Darcy鈥揥eisbach Pipe Loss (Deterministic)")
|
| 189 |
+
|
| 190 |
+
with gr.Row():
|
| 191 |
+
with gr.Column():
|
| 192 |
+
rho = gr.Slider(500, 2000, value=998.0, step=1.0, label="Density 蟻 (kg/m鲁)")
|
| 193 |
+
mu = gr.Slider(0.0002, 0.005, value=0.0010, step=0.0001, label="Viscosity 渭 (Pa路s)")
|
| 194 |
+
D = gr.Slider(0.005, 1.0, value=0.05, step=0.001, label="Diameter D (m)")
|
| 195 |
+
L = gr.Slider(0.5, 1000.0, value=50.0, step=0.5, label="Length L (m)")
|
| 196 |
+
Q = gr.Slider(1e-5, 2.0, value=0.005, step=1e-4, label="Flow rate Q (m鲁/s)")
|
| 197 |
+
eps= gr.Slider(0.0, 0.005, value=1.5e-6, step=1e-6, label="Roughness 蔚 (m)")
|
| 198 |
+
|
| 199 |
+
run_btn = gr.Button("Compute")
|
| 200 |
+
|
| 201 |
+
with gr.Column():
|
| 202 |
+
numeric = gr.Textbox(label="Numerical results", lines=6)
|
| 203 |
+
# Assuming 'explain' is defined elsewhere, e.g., as a gr.Textbox
|
| 204 |
+
# If not, you might need to define it here:
|
| 205 |
+
explain = gr.Textbox(label="Explanation", lines=10)
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
examples = gr.Examples(
|
| 209 |
+
examples=[
|
| 210 |
+
[998.0, 0.0010, 0.05, 50.0, 0.005, 1.5e-6], # Water, smooth steel
|
| 211 |
+
[870.0, 0.0015, 0.10, 200.0, 0.03, 4.5e-5], # Light oil, commercial steel
|
| 212 |
+
[1000.0, 0.0008, 0.02, 10.0, 0.0002, 1.0e-6] # Small tube, low flow
|
| 213 |
+
],
|
| 214 |
+
inputs=[rho, mu, D, L, Q, eps]
|
| 215 |
+
)
|
| 216 |
+
|
| 217 |
+
run_btn.click(run_calc, inputs=[rho, mu, D, L, Q, eps], outputs=[numeric, explain])
|
| 218 |
+
|
| 219 |
+
# Comment out the demo.launch() call as it will be handled by the Hugging Face Space
|
| 220 |
+
# demo.launch(share=True)
|