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,18 +173,20 @@ The basin is modelled as a rectangular prism with constant cross-section. Everyt
|
||||
┌─────────────────┐ ◄─ heightBasin (rim)
|
||||
│ │
|
||||
│ freeboard │
|
||||
├─ ─ ─ ─ ─ ─ ─ ─ ─┤ ◄─ heightOverflow ═══► overfill trip
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ (upstream stops)
|
||||
├─ ─ ─ ─ ─ ─ ─ ─ ─┤ ◄─ heightOverflow ═══► spill over weir
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ (measure & log —
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ see Safety note)
|
||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ maxFlowLevel
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||
│≈≈≈ SCALING ≈≈≈≈≈│ (levelbased: demand
|
||||
│≈≈≈ RANGE ≈≈≈≈≈│ ramps 0 → 100 %
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ across this band)
|
||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ startLevel
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||
│≈≈≈ DEAD ZONE ≈≈≈│ (hysteresis —
|
||||
│≈≈ (keep cmd) ≈≈│ keep last command)
|
||||
INFLOW ═══════►╣≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ◄─ heightInlet
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ maxFlowLevel ═══► 100 % demand
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ▲
|
||||
│≈≈≈≈≈ RUN ≈≈≈≈≈≈≈│ │ ramp
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ │ linearly
|
||||
INFLOW ═══════►╣≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ ◄─ heightInlet │
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│ │
|
||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ startLevel ═══► 0 % demand
|
||||
│≈≈ DEAD ZONE ≈≈≈≈│ ─── hysteresis
|
||||
│≈≈ (keep cmd) ≈≈≈│
|
||||
├╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌ ╌┤ ◄─ stopLevel ═══► unconditional STOP
|
||||
│≈≈≈≈≈ BUFFER ≈≈≈≈│
|
||||
│≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈│
|
||||
@@ -193,7 +195,9 @@ The basin is modelled as a rectangular prism with constant cross-section. Everyt
|
||||
└─────────────────┘ ◄─ 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:
|
||||
|
||||
@@ -246,7 +250,7 @@ flowPositions = { inflow: ['in', 'upstream'], outflow: ['out', 'downstream'] }
|
||||
level
|
||||
▲
|
||||
│
|
||||
┼── heightOverflow ═══ overfill trip ─► upstream STOP
|
||||
┼── heightOverflow ─── weir crest (spill → measure)
|
||||
│
|
||||
│ ┐
|
||||
│ │ RUN
|
||||
@@ -254,17 +258,17 @@ flowPositions = { inflow: ['in', 'upstream'], outflow: ['out', 'downstream'] }
|
||||
│ │
|
||||
┼── maxFlowLevel ═══ ┴ 100 % demand
|
||||
│
|
||||
┼── heightInlet ─── inflow pipe
|
||||
│
|
||||
┼── startLevel ═══ 0 % demand (ramp starts)
|
||||
│ ┐
|
||||
│ │ (scaling range)
|
||||
│ │
|
||||
┼── startLevel ═══ 0 % demand ── ramp starts
|
||||
│ ┐
|
||||
│ │ DEAD ZONE
|
||||
│ │ hysteresis — keep last cmd
|
||||
┼── heightInlet ─── │ hysteresis — keep last cmd
|
||||
│ │
|
||||
┼── stopLevel ═══ ┴ unconditional STOP
|
||||
│
|
||||
┼── heightOutlet ─── outflow pipe
|
||||
│ ═══ dry-run trip ─► downstream STOP
|
||||
┼── heightOutlet ─── outflow pipe (dry-run trip here)
|
||||
│
|
||||
┴── 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`.
|
||||
|
||||
> ⚠️ **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.
|
||||
|
||||
## Registration — which children count as flow?
|
||||
|
||||
Reference in New Issue
Block a user