|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def darcy_weisbach_calculation( |
|
|
rho, |
|
|
mu, |
|
|
D, |
|
|
L, |
|
|
Q, |
|
|
eps=1.5e-6 |
|
|
): |
|
|
""" |
|
|
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 |
|
|
""" |
|
|
|
|
|
A = pi*(D**2)/4.0 |
|
|
v = Q / A |
|
|
Re = rho * v * D / mu |
|
|
|
|
|
|
|
|
if Re < 2300: |
|
|
f = 64.0 / max(Re, 1e-9) |
|
|
regime = "laminar" |
|
|
else: |
|
|
|
|
|
|
|
|
term = (eps/(3.7*D)) + (5.74/(Re**0.9)) |
|
|
f = 0.25 / (log10(term)**2) |
|
|
regime = "turbulent" |
|
|
|
|
|
|
|
|
g = 9.80665 |
|
|
hf = f * (L/D) * (v**2/(2*g)) |
|
|
|
|
|
|
|
|
dP = rho * g * hf |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
model_id = "hf-internal-testing/tiny-random-LlamaForCausalLM" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_llm_pipeline(model_name=model_id, task="text2text-generation"): |
|
|
try: |
|
|
pipe = pipeline(task, model=model_name, device_map="auto") |
|
|
except Exception: |
|
|
|
|
|
pipe = pipeline(task, model="google/flan-t5-small") |
|
|
return pipe |
|
|
|
|
|
llm = load_llm_pipeline() |
|
|
|
|
|
def explain_results(structured_message): |
|
|
|
|
|
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" |
|
|
"- 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) |
|
|
|
|
|
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) |
|
|
|
|
|
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 = 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) |
|
|
|
|
|
|
|
|
explain = gr.Textbox(label="Explanation", lines=10) |
|
|
|
|
|
|
|
|
examples = gr.Examples( |
|
|
examples=[ |
|
|
[998.0, 0.0010, 0.05, 50.0, 0.005, 1.5e-6], |
|
|
[870.0, 0.0015, 0.10, 200.0, 0.03, 4.5e-5], |
|
|
[1000.0, 0.0008, 0.02, 10.0, 0.0002, 1.0e-6] |
|
|
], |
|
|
inputs=[rho, mu, D, L, Q, eps] |
|
|
) |
|
|
|
|
|
run_btn.click(run_calc, inputs=[rho, mu, D, L, Q, eps], outputs=[numeric, explain]) |
|
|
|
|
|
|
|
|
demo.launch(share=False, server_name="0.0.0.0") |
|
|
|
|
|
|