|
|
| 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") |
|
|
|
|