Docs + simulations refresh; align spill-flow keys with new position
- wiki/functional-description.md: rename Overfill Protection → High-volume
Safety; tighten basin-ordering chain; relocate level-based mode
diagrams under wiki/diagrams/modes/level-based/; document the new
flow.predicted.overflow.default position (replaces the previous
child='overflow' under position 'out'); add underflowVolume +
predictedUnderflowVolume entries.
- wiki/modes/{levelbased,powerbased}.md: paragraph cleanups.
- wiki/diagrams: move level-linear basin diagram under modes/level-based/
alongside a new level-log variant.
- simulations/run.js: add max_demand_gt expectation.
- simulations/scenarios/*: minor fixture updates.
- test/basic/nodeClass-config.test.js: new config-shape coverage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ updated: 2026-04-22
|
||||
|
||||
# Level-based mode
|
||||
|
||||
The simplest and most widely deployed control strategy. Demand is a direct, *static* piecewise-linear function of basin level — no feedback loop, no predictions beyond the level measurement itself. This page uses the [shared basin model](../functional-description.md#basin-model); see [`modes/README.md`](README.md) for the template other mode pages follow.
|
||||
The simplest and most widely deployed control strategy. Demand is a direct, static function of basin level — no feedback loop, no predictions beyond the level measurement itself. This page uses the [shared basin model](../functional-description.md#basin-model); see [`modes/README.md`](README.md) for the template other mode pages follow.
|
||||
|
||||
## At a glance
|
||||
|
||||
@@ -20,9 +20,9 @@ The simplest and most widely deployed control strategy. Demand is a direct, *sta
|
||||
|
||||
## Diagram
|
||||
|
||||

|
||||

|
||||
|
||||
*Editable source: [`../diagrams/modes/basin-mode-level-linear.drawio.svg`](../diagrams/modes/basin-mode-level-linear.drawio.svg) (drag into [draw.io](https://app.diagrams.net/) — it round-trips).*
|
||||
*Editable sources: [`../diagrams/modes/level-based/basin-mode-level-linear.drawio.svg`](../diagrams/modes/level-based/basin-mode-level-linear.drawio.svg) and [`../diagrams/modes/level-based/basin-mode-level-log.drawio.svg`](../diagrams/modes/level-based/basin-mode-level-log.drawio.svg) (drag into [draw.io](https://app.diagrams.net/) — they round-trip).*
|
||||
|
||||
## Inputs
|
||||
|
||||
@@ -30,10 +30,11 @@ The simplest and most widely deployed control strategy. Demand is a direct, *sta
|
||||
|---|---|---|
|
||||
| current level | `measurement` child (`measured`) → predicted from volume integrator (fallback) | X-axis of the transfer function |
|
||||
| `config.control.levelbased.minLevel` | editor, static | below → pumps hard OFF |
|
||||
| `config.control.levelbased.startLevel` | editor, static | where demand-ramp starts |
|
||||
| `config.control.levelbased.startLevel` | editor, static | falling ramp reaches 0 % here; rising demand holds 0 % until the inlet level |
|
||||
| `config.control.levelbased.maxLevel` | editor, static | where demand saturates at 100 % |
|
||||
| `config.control.levelbased.curveType` | editor, static | `linear` or `log`; log is fast early response |
|
||||
|
||||
The three control thresholds are the **only** mode-specific configuration. Nothing here is recomputed at runtime.
|
||||
The three control thresholds plus curve type are the mode-specific configuration. Nothing here is recomputed at runtime.
|
||||
|
||||
## Threshold policy
|
||||
|
||||
@@ -42,6 +43,7 @@ The three control thresholds are the **only** mode-specific configuration. Nothi
|
||||
| `minLevel` | `config.control.levelbased.minLevel` | No |
|
||||
| `startLevel` | `config.control.levelbased.startLevel` | No |
|
||||
| `maxLevel` | `config.control.levelbased.maxLevel` | No |
|
||||
| `curveType` | `config.control.levelbased.curveType` | No |
|
||||
|
||||
That this policy is trivial (all static) is **the defining simplicity of this mode**. Modes like `powerBased` or future `weather-aware` variants will recompute these thresholds on the fly.
|
||||
|
||||
@@ -51,15 +53,15 @@ That this policy is trivial (all static) is **the defining simplicity of this mo
|
||||
if level < minLevel:
|
||||
demand = 0
|
||||
MGC → turnOffAllMachines() # explicit shutdown, not just "0 %"
|
||||
elif level < startLevel:
|
||||
demand = <previous demand> # dead zone — hold last command (hysteresis)
|
||||
elif level <= maxLevel:
|
||||
demand = lerp(level, [startLevel, maxLevel], [0 %, 100 %])
|
||||
elif direction == filling:
|
||||
demand = curve(level, [inflowLevel, maxLevel], [0 %, 100 %])
|
||||
elif direction == draining:
|
||||
demand = curve(level, [startLevel, maxLevel], [0 %, 100 %])
|
||||
else:
|
||||
demand = 100 % # saturated; MGC clamps internally if overshoot
|
||||
demand = previous demand
|
||||
```
|
||||
|
||||
Where `lerp` is linear interpolation. The MGC is free to distribute the demand across its pumps however its own policy dictates (equal split, lead-lag, staging — that's the MGC's business).
|
||||
Below the active lower ramp point, demand is 0 %. Above `maxLevel`, demand is 100 %. `curve` is either linear or logarithmic; the log variant rises faster early in the ramp. The MGC is free to distribute the demand across its pumps however its own policy dictates (equal split, lead-lag, staging — that's the MGC's business).
|
||||
|
||||
## Edge cases
|
||||
|
||||
|
||||
Reference in New Issue
Block a user