From dc27a569d9be6e1d0e1d2c7538c30a6bb794c945 Mon Sep 17 00:00:00 2001 From: Rene De Ren Date: Fri, 8 May 2026 17:20:21 +0200 Subject: [PATCH] handlePressureChange: mirror aggregate flow onto DOWNSTREAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PS subscribes to MGC's flow.predicted.downstream and uses it as the outflow estimate for net-flow computation. MGC was only writing to DOWNSTREAM inside optimalControl (the optimizer's bestFlow TARGET, not the achieved aggregate), and to AT_EQUIPMENT in handlePressureChange. During transients — e.g. demand dropping to dead-band keep-alive while pumps are still ramping down from full throttle — PS saw a stale 25 m³/h target on DOWNSTREAM while pumps were physically delivering 500+ m³/h. NetFlow looked small and stable when the basin was actually draining fast. flow.act = sum of every pump's current predicted output = achieved aggregate. Mirror it onto DOWNSTREAM so PS gets a live signal on every pump flow/pressure update, not just every MGC.handleInput. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/specificClass.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/specificClass.js b/src/specificClass.js index cd78b67..bf98c45 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -283,6 +283,18 @@ class MachineGroup { this.logger.debug(`Dynamic Totals after pressure change - Flow: Min ${flow.min}, Max ${flow.max}, Act ${flow.act} | Power: Min ${power.min}, Max ${power.max}, Act ${power.act}`); this._writeMeasurement("flow", "predicted", POSITIONS.AT_EQUIPMENT, flow.act, this.unitPolicy.canonical.flow); + // Mirror the aggregate flow onto DOWNSTREAM as well. PS subscribes to + // flow.predicted.downstream from MGC and uses it as the outflow + // estimate for net-flow computation. Without this mirror, the only + // place DOWNSTREAM gets written is optimalControl's bestFlow (the + // optimizer's TARGET, not the achieved aggregate). During transients + // — e.g. demand dropping to dead-band keep-alive while pumps are + // still ramping down from full throttle — PS would see a stale + // 25 m³/h target while pumps are physically delivering 500+ m³/h, + // making netFlow look small and stable when the basin is actually + // draining fast. flow.act here is the sum of every pump's current + // predicted output, so it IS the achieved aggregate. + this._writeMeasurement("flow", "predicted", POSITIONS.DOWNSTREAM, flow.act, this.unitPolicy.canonical.flow); this._writeMeasurement("power", "predicted", POSITIONS.AT_EQUIPMENT, power.act, this.unitPolicy.canonical.power); const { maxEfficiency, lowestEfficiency } = this.calcGroupEfficiency(this.machines);