Compare commits

...

1 Commits

Author SHA1 Message Date
znetsixe
26e253d030 fix: clamp flow/power predictions to 0 when controller position ≤ 0
At ctrl=0% with high backpressure, the curve prediction extrapolates to
large negative values (backflow through a stopped pump). This produced
confusing chart readings (-200+ m³/h for an idle pump) and polluted
downstream consumers like MGC efficiency calculations.

Fix: in both calcFlow and calcPower, if the controller position x ≤ 0
the prediction is clamped to 0 regardless of what the spline returns.
For x > 0, predictions are also clamped to ≥ 0 (negative flow/power
from a running pump is physically implausible for a centrifugal machine).

91/91 tests still green — no existing test asserted on negative
flow/power values at ctrl=0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:07:02 +02:00

View File

@@ -967,10 +967,14 @@ _callMeasurementHandler(measurementType, value, position, context) {
return 0;
}
const cFlow = this.predictFlow.y(x);
// Clamp: at position ≤ 0 the pump isn't rotating — physical flow is 0.
// Without this, curve extrapolation at ctrl=0 + high backpressure
// produces large negative values (backflow through a stopped pump)
// that confuse dashboards and downstream consumers.
const rawFlow = this.predictFlow.y(x);
const cFlow = (x <= 0) ? 0 : Math.max(0, rawFlow);
this.measurements.type("flow").variant("predicted").position("downstream").value(cFlow,Date.now(),this.unitPolicy.canonical.flow);
this.measurements.type("flow").variant("predicted").position("atEquipment").value(cFlow,Date.now(),this.unitPolicy.canonical.flow);
//this.logger.debug(`Calculated flow: ${cFlow} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
return cFlow;
}
@@ -991,10 +995,9 @@ _callMeasurementHandler(measurementType, value, position, context) {
return 0;
}
//this.predictPower.currentX = x; Decrepated
const cPower = this.predictPower.y(x);
const rawPower = this.predictPower.y(x);
const cPower = (x <= 0) ? 0 : Math.max(0, rawPower);
this.measurements.type("power").variant("predicted").position('atEquipment').value(cPower, Date.now(), this.unitPolicy.canonical.power);
//this.logger.debug(`Calculated power: ${cPower} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
return cPower;
}
// If no curve data is available, log a warning and return 0