Add cavitation detection (NPSH-based) per pump #1
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Background
Cavitation occurs when the local pressure at the impeller eye drops below the liquid's vapour pressure: vapour bubbles form on the suction side, then collapse violently downstream — eroding the impeller, vibrating the shaft, and degrading flow. For wastewater pumping it's the dominant low-level failure mode (low water level → low static head → low NPSHa → cavitation → pump ruined).
This lives on
rotatingMachine(per-pump concern), NOT onpumpingStation, because:Engineering formula
NPSHa (Available) at the pump suction:
Where:
P_atmP_vapourcoolprop.PropsSI('P', 'T', T_K, 'Q', 0, 'Water')ρcoolprop.PropsSI('D', 'T', T_K, 'P', P_atm, 'Water')ggravity.js(9.80665 default; use Somigliana if lat known)h_swaterLevel − pumpSuctionElevation; positive when basin is above pump (flooded suction)h_frictionf × (L/D) × v²/(2g)for long suction linesNPSHr (Required) — pump-specific, from manufacturer curve. Typically rises with flow². For MVP a single conservative value per pump is fine; a flow-dependent curve is the v2 follow-up.
Cavitation criterion:
With
safetyMargintypically 0.5–1.0 m or 10–20% of NPSHr (config, default 0.5 m).Inputs needed
New
rotatingMachineconfig fieldscavitation.npshRequired(m) — manufacturer NPSHr at design flow. Required to enable detection.cavitation.suctionElevation(m, basin-floor reference) — height of pump suction inlet above basin floor. Often 0 for submersible. For dry-pit / suction-lift, this can equal the pump centerline elevation above the basin water surface (h_s becomes negative).cavitation.frictionHead(m) — default 0. Optional approximation of suction-line losses.cavitation.safetyMargin(m) — default 0.5.cavitation.enabled(bool) — default false (opt-in until calibrated).Inputs the pump pulls from its parent station
level.measured.atequipmentorlevel.predicted.atequipment— basin water level (m above basin floor).temperature.measured.atequipment— water temp (K). Default 15°C / 288.15 K if not present.atmosphericPressurePa— station-level config (default 101325).Implementation plan
Phase 1 — detection (this issue)
nodes/generalFunctions/src/helper/npsh.jswith one pure function:coolpropfor vapour pressure + density. Pure helper, no Node-RED.rotatingMachine/src/specificClass.js, on each tick (whencavitation.enabled):NPSHavia the helper.NPSHr + safetyMargin.npshAvailable.predicted.atequipment.default(m) andnpshMargin.predicted.atequipment.default(m) measurements for telemetry.this.cavitatingand a severity enumthis.cavitationState='normal' | 'margin-low' | 'cavitating'.getOutput():output.cavitating,output.cavitationState,output.npshAvailable,output.npshMargin.cavitating, amber whenmargin-low.Phase 2 — action (separate issue, do NOT do here)
Test scenarios
Must cover:
normal.margin-low.Acceptance criteria
npsh.jshelper with unit tests ingeneralFunctions/test/.rotatingMachineconfig schema updated; newcavitation.*block.getOutput()exposescavitating,cavitationState,npshAvailable,npshMargin.cavitation.enabled: falseso existing demos keep behaving identically until opted in.Why deferred (not done now)