Fix basin + control-zone diagram accuracy
Three corrections after review: 1. Overfill behaviour — replaced "overfill trip (upstream stops)" with "spill over weir (measure & log)" and added a Known Limitation box in the Safety section. The code's execSequence:shutdown on upstream children only makes sense in a cascaded-station layout; for the gravity-sewer case the inflow can't be stopped (toilets back up). Correct response is spill measurement + alarm. 2. Demand-ramp annotations — removed "100% / 0% demand" and the RUN arrow from the basin cross-section. Those are levelbased-mode specifics; the basin model should describe physical geometry only. Demand annotations remain in the Control logic thermometer. 3. heightInlet placement — moved below startLevel in both diagrams. Matches physical reality: pumps start before water rises to the gravity-inlet pipe. Flags a contradictory comment in specificClass.js for cleanup next time that file is touched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@@ -173,27 +173,31 @@ The basin is modelled as a rectangular prism with constant cross-section. Everyt
|
|||||||
┌─────────────────┐ ◄─ heightBasin (rim)
|
┌─────────────────┐ ◄─ heightBasin (rim)
|
||||||
│ │
|
│ │
|
||||||
│ freeboard │
|
│ freeboard │
|
||||||
├─ ─ ─ ─ ─ ─ ─ ─ ─┤ ◄─ heightOverflow ═══► overfill trip
|
├─ ─ ─ ─ ─ ─ ─ ─ ─┤ ◄─ heightOverflow ═══► spill over weir
|
||||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ (upstream stops)
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ (measure & log —
|
||||||
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ see Safety note)
|
||||||
|
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ maxFlowLevel
|
||||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ maxFlowLevel ═══► 100 % demand
|
│≈≈≈ SCALING ≈≈≈≈≈│ (levelbased: demand
|
||||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ▲
|
│≈≈≈ RANGE ≈≈≈≈≈│ ramps 0 → 100 %
|
||||||
│≈≈≈≈≈ RUN ≈≈≈≈≈≈≈│ │ ramp
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ across this band)
|
||||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ │ linearly
|
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ startLevel
|
||||||
INFLOW ═══════►╣≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ◄─ heightInlet │
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ │
|
│≈≈≈ DEAD ZONE ≈≈≈│ (hysteresis —
|
||||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ startLevel ═══► 0 % demand
|
│≈≈ (keep cmd) ≈≈│ keep last command)
|
||||||
│≈≈ DEAD ZONE ≈≈≈≈│ ─── hysteresis
|
INFLOW ═══════►╣≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ◄─ heightInlet
|
||||||
│≈≈ (keep cmd) ≈≈≈│
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ stopLevel ═══► unconditional STOP
|
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ stopLevel ═══► unconditional STOP
|
||||||
│≈≈≈≈≈ BUFFER ≈≈≈≈│
|
│≈≈≈≈≈ BUFFER ≈≈≈≈│
|
||||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||||
OUTFLOW ◄══════╣≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ◄─ heightOutlet ═══► dry-run trip
|
OUTFLOW ◄══════╣≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ◄─ heightOutlet ═══► dry-run trip
|
||||||
│░░░ DEAD VOLUME ░│ (downstream stops)
|
│░░░ DEAD VOLUME ░│ (downstream stops)
|
||||||
└─────────────────┘ ◄─ 0 (floor)
|
└─────────────────┘ ◄─ 0 (floor)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Typical ordering** (bottom → top): `stopLevel < startLevel = minFlowLevel ≤ heightInlet < maxFlowLevel ≈ heightOverflow`.
|
**Typical ordering** (bottom → top): `stopLevel < heightInlet < startLevel = minFlowLevel < maxFlowLevel ≤ heightOverflow`.
|
||||||
|
|
||||||
|
> ⚠️ The comment block in `specificClass.js` currently says `startLevel ≤ heightInlet` (inlet above startLevel). The physical convention is the opposite: pumps start *before* the water reaches the gravity inlet, so `heightInlet < startLevel`. Worth fixing in the code comment next time that file is touched.
|
||||||
|
|
||||||
**minHeightBasedOn** — which pipe defines `minVol`, the operational floor used for the initial seed, the dry-run trigger, and the 0 % point of the fill percentage:
|
**minHeightBasedOn** — which pipe defines `minVol`, the operational floor used for the initial seed, the dry-run trigger, and the 0 % point of the fill percentage:
|
||||||
|
|
||||||
@@ -246,7 +250,7 @@ flowPositions = { inflow: ['in', 'upstream'], outflow: ['out', 'downstream'] }
|
|||||||
level
|
level
|
||||||
▲
|
▲
|
||||||
│
|
│
|
||||||
┼── heightOverflow ═══ overfill trip ─► upstream STOP
|
┼── heightOverflow ─── weir crest (spill → measure)
|
||||||
│
|
│
|
||||||
│ ┐
|
│ ┐
|
||||||
│ │ RUN
|
│ │ RUN
|
||||||
@@ -254,17 +258,17 @@ flowPositions = { inflow: ['in', 'upstream'], outflow: ['out', 'downstream'] }
|
|||||||
│ │
|
│ │
|
||||||
┼── maxFlowLevel ═══ ┴ 100 % demand
|
┼── maxFlowLevel ═══ ┴ 100 % demand
|
||||||
│
|
│
|
||||||
┼── heightInlet ─── inflow pipe
|
│ ┐
|
||||||
│
|
│ │ (scaling range)
|
||||||
┼── startLevel ═══ 0 % demand (ramp starts)
|
│ │
|
||||||
|
┼── startLevel ═══ 0 % demand ── ramp starts
|
||||||
│ ┐
|
│ ┐
|
||||||
│ │ DEAD ZONE
|
│ │ DEAD ZONE
|
||||||
│ │ hysteresis — keep last cmd
|
┼── heightInlet ─── │ hysteresis — keep last cmd
|
||||||
│ │
|
│ │
|
||||||
┼── stopLevel ═══ ┴ unconditional STOP
|
┼── stopLevel ═══ ┴ unconditional STOP
|
||||||
│
|
│
|
||||||
┼── heightOutlet ─── outflow pipe
|
┼── heightOutlet ─── outflow pipe (dry-run trip here)
|
||||||
│ ═══ dry-run trip ─► downstream STOP
|
|
||||||
│
|
│
|
||||||
┴── 0 (floor)
|
┴── 0 (floor)
|
||||||
```
|
```
|
||||||
@@ -310,6 +314,8 @@ flowPositions = { inflow: ['in', 'upstream'], outflow: ['out', 'downstream'] }
|
|||||||
|
|
||||||
During overfill, level-based control naturally commands ≥100 % on the downstream MGC because the level is above `maxFlowLevel`.
|
During overfill, level-based control naturally commands ≥100 % on the downstream MGC because the level is above `maxFlowLevel`.
|
||||||
|
|
||||||
|
> ⚠️ **Known limitation — gravity-sewer context.** The "upstream STOP" action only makes sense in a **cascaded** station layout where the upstream equipment is an EVOLV-controllable pump or station. In a conventional wastewater wet-well the inflow is gravity-fed from the municipal sewer and **cannot be stopped** — attempting to would back up toilets. For that case the correct response to an overfill event is to **measure and log the spill over the weir** (for compliance reporting) and raise an alarm, while keeping downstream pumps at maximum demand. The current code fires `execSequence: shutdown` on upstream children regardless of what they are; that should be gated on "is the upstream actually controllable?" and supplemented with overflow-rate tracking. Tracked as follow-up work.
|
||||||
|
|
||||||
A missing volume reading is treated as a hard fault: every direct machine is sent `execSequence: shutdown` and `safetyControllerActive` latches. Calibrate predicted volume (`calibratePredictedVolume`) or wire a level measurement to recover.
|
A missing volume reading is treated as a hard fault: every direct machine is sent `execSequence: shutdown` and `safetyControllerActive` latches. Calibrate predicted volume (`calibratePredictedVolume`) or wire a level measurement to recover.
|
||||||
|
|
||||||
## Registration — which children count as flow?
|
## Registration — which children count as flow?
|
||||||
|
|||||||
Reference in New Issue
Block a user