Tabular Regression
ONNX
LiteRT
Keras
PyTorch
LiteRT
industrial
pump
digital-twin
edge-ai
onnxruntime
tensorflow
anomaly-detection
Instructions to use sankalpsthakur/forge-pump-surrogate-multiruntime with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use sankalpsthakur/forge-pump-surrogate-multiruntime with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
| """Clean-room synthetic pump physics for a public edge-inference baseline. | |
| All constants are illustrative engineering proxies. They are not copied from | |
| vendor curves, CAD, BOMs, plant telemetry, or the private pump repository. | |
| """ | |
| from __future__ import annotations | |
| import numpy as np | |
| FEATURE_NAMES = ( | |
| "speed_fraction", | |
| "static_head_m", | |
| "system_k", | |
| "voltage_fraction", | |
| "ambient_temp_c", | |
| "inlet_pressure_bar", | |
| ) | |
| TARGET_NAMES = ( | |
| "flow_m3h", | |
| "total_head_m", | |
| "input_power_kw", | |
| "winding_temp_c", | |
| "npsh_margin_m", | |
| "efficiency_fraction", | |
| ) | |
| # Public, illustrative baseline constants—not equipment specifications. | |
| SHUTOFF_HEAD_M = 132.0 | |
| PUMP_CURVE_COEFF = 0.58 | |
| BEP_FLOW_M3H = 11.5 | |
| DEMO_THERMAL_REVIEW_C = 70.0 | |
| DEMO_OVERLOAD_REVIEW_KW = 3.2 | |
| def evaluate(features: np.ndarray) -> np.ndarray: | |
| """Evaluate a generic pump/system intersection and thermal proxy. | |
| Args: | |
| features: float array shaped ``(..., 6)`` in FEATURE_NAMES order. | |
| Returns: | |
| Float array shaped ``(..., 6)`` in TARGET_NAMES order. | |
| """ | |
| x = np.asarray(features, dtype=np.float64) | |
| if x.shape[-1] != len(FEATURE_NAMES): | |
| raise ValueError(f"expected {len(FEATURE_NAMES)} features, got {x.shape[-1]}") | |
| speed, static_head, system_k, voltage, ambient, inlet_pressure = np.moveaxis(x, -1, 0) | |
| available_head = np.maximum(SHUTOFF_HEAD_M * speed**2 - static_head, 0.0) | |
| flow = np.sqrt(available_head / np.maximum(PUMP_CURVE_COEFF + system_k, 1e-6)) | |
| total_head = static_head + system_k * flow**2 | |
| bep_flow = np.maximum(BEP_FLOW_M3H * speed, 0.1) | |
| relative_offset = (flow - bep_flow) / bep_flow | |
| pump_efficiency = np.clip( | |
| 0.74 - 0.34 * relative_offset**2 - 0.05 * (1.0 - speed), | |
| 0.18, | |
| 0.76, | |
| ) | |
| motor_efficiency = np.clip( | |
| 0.90 - 0.12 * (1.0 - voltage) ** 2 - 0.05 * (1.0 - speed) ** 2, | |
| 0.65, | |
| 0.92, | |
| ) | |
| efficiency = pump_efficiency * motor_efficiency | |
| hydraulic_power_kw = 9.80665 * (flow / 3600.0) * total_head | |
| input_power_kw = hydraulic_power_kw / np.maximum(efficiency, 0.1) + 0.10 * speed | |
| low_flow_penalty = 12.0 * np.clip(1.0 - flow / np.maximum(0.55 * bep_flow, 0.1), 0.0, 1.0) | |
| undervoltage_penalty = 60.0 * np.clip(0.90 - voltage, 0.0, 0.20) | |
| winding_temp_c = ambient + 7.2 * input_power_kw + low_flow_penalty + undervoltage_penalty | |
| npsh_required_m = 1.4 + 0.018 * flow**2 | |
| npsh_available_m = 10.197 * inlet_pressure + 2.0 | |
| npsh_margin_m = npsh_available_m - npsh_required_m | |
| return np.stack( | |
| (flow, total_head, input_power_kw, winding_temp_c, npsh_margin_m, efficiency), | |
| axis=-1, | |
| ) | |
| def anomaly_flags(features: np.ndarray, outputs: np.ndarray) -> list[str]: | |
| """Return deterministic advisory flags for each row. | |
| These thresholds are test/demo policy, not a certified protection layer. | |
| """ | |
| x = np.asarray(features, dtype=np.float64) | |
| y = np.asarray(outputs, dtype=np.float64) | |
| rows: list[str] = [] | |
| for feature, target in zip(x.reshape(-1, 6), y.reshape(-1, 6), strict=True): | |
| speed, _, _, voltage, _, _ = feature | |
| flow, _, power, winding, npsh_margin, _ = target | |
| flags: list[str] = [] | |
| if speed > 0.35 and flow < 0.20: | |
| flags.append("no_flow_risk") | |
| if npsh_margin < 1.0: | |
| flags.append("cavitation_risk") | |
| if winding > DEMO_THERMAL_REVIEW_C: | |
| flags.append("thermal_risk") | |
| if voltage < 0.90: | |
| flags.append("undervoltage") | |
| if power > DEMO_OVERLOAD_REVIEW_KW: | |
| flags.append("overload_risk") | |
| rows.append("|".join(flags) if flags else "normal") | |
| return rows | |
| def sample_features(count: int, seed: int = 20260802) -> np.ndarray: | |
| """Sample the frozen synthetic operating envelope.""" | |
| rng = np.random.default_rng(seed) | |
| columns = ( | |
| rng.uniform(0.35, 1.05, count), | |
| rng.uniform(5.0, 120.0, count), | |
| rng.uniform(0.03, 0.80, count), | |
| rng.uniform(0.82, 1.08, count), | |
| rng.uniform(5.0, 50.0, count), | |
| rng.uniform(0.15, 2.50, count), | |
| ) | |
| return np.stack(columns, axis=-1).astype(np.float32) | |