### eval/ (scenario-based evaluation)
Complements the unit tests under test/basic. Scenarios fluctuate inputs
over simulated time, record every tick to JSONL, print a summary
table + event log, and check expectations. Complementary to unit
tests — these answer "how does the system respond to this input
profile" rather than "is this function correct".
- eval/run.js — driver; monkey-patches Date.now so the
volume integrator ticks at 1 s/iter
regardless of wall-clock
- eval/scenarios/ — one file per scenario
- levelbased-steady.js — constant inflow, demand converges
- levelbased-storm.js — inflow surge, demand saturates
- safety-dry-run-trip.js — manual mode, empty basin, safety trips
- eval/formatters/table.js — ASCII summary of sampled ticks
- eval/logs/ — per-scenario JSONL output (one line per tick)
- eval/README.md — usage + scenario file shape + how to pipe
into InfluxDB/Grafana
All three starter scenarios PASS with their expectations.
### wiki/modes/ (tier template pages)
The levelbased page templated Tier-1 modes (static transfer function).
Added worked examples for the other two tiers so all mode pages share
a common skeleton and new modes have something concrete to imitate:
- flowbased.md — Tier 2 (PID on measured outflow)
- powerbased.md — Tier 2 (levelbased curve clipped by grid power budget)
- mpc.md — Tier 3 (optimisation + forecast; block diagram +
scenario time-series instead of a fixed curve)
- modes/README.md — updated with the three-tier classification table
and diagram-type-per-tier guidance
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
2.2 KiB
Markdown
39 lines
2.2 KiB
Markdown
# Control modes
|
|
|
|
Each page describes one `pumpingStation` control mode and how it uses the shared [basin model](../functional-description.md#basin-model) — specifically, how it uses the three control thresholds (`minLevel`, `startLevel`, `maxLevel`) and computes the demand it sends to the MGC.
|
|
|
|
The two **safety** thresholds (`dryRunLevel` and `overflowLevel`) are mode-independent and are enforced by the safety layer outside any mode. They never appear in a mode's policy.
|
|
|
|
## Template
|
|
|
|
Every mode page follows the same structure:
|
|
|
|
1. **At a glance** — one sentence + small fact table (inputs, output, status)
|
|
2. **Diagram** — one or more, per tier (see below)
|
|
3. **Inputs** — what signals the mode reads
|
|
4. **Threshold policy** — how it uses / adjusts `minLevel`, `startLevel`, `maxLevel`
|
|
5. **Demand formula** — pseudocode for Tier 1/2, objective function for Tier 3
|
|
6. **Edge cases** — cold start, sensor dropout, interaction with safety layer
|
|
7. **Related** — links to other modes + functional description
|
|
|
|
The three **tiers** classify modes by how dynamic the decision surface is:
|
|
|
|
| Tier | Curve | Example modes | Diagram type |
|
|
|---|---|---|---|
|
|
| **1** — static | Memoryless `demand = f(x)`; single curve | `levelbased`, `manual` | Single-curve transfer function |
|
|
| **2** — parameterised | Shape fixed, curve moves with θ(t) | `flowbased`, `pressureBased`, `percentageBased`, `powerBased` | Transfer function + parameter overlay / family |
|
|
| **3** — horizon-based | Optimisation, no fixed curve | `hybrid-optimal`, `mpc`, weather-aware | Block diagram of signal flow + scenario time-series |
|
|
|
|
## Implementation status
|
|
|
|
| Mode | Tier | Status | Page |
|
|
|---|---|---|---|
|
|
| `levelbased` | 1 | ✅ implemented | [levelbased.md](levelbased.md) |
|
|
| `manual` | 1 | ✅ implemented (via `Qd` topic) | — |
|
|
| `flowbased` | 2 | 🚧 code placeholder, template | [flowbased.md](flowbased.md) |
|
|
| `pressureBased` | 2 | 🚧 code placeholder | — |
|
|
| `percentageBased` | 2 | 🚧 code placeholder | — |
|
|
| `powerBased` | 2 | 🚧 code placeholder, template | [powerbased.md](powerbased.md) |
|
|
| `hybrid` | 3 | 🚧 code placeholder | — |
|
|
| `mpc` | 3 | 🚧 not in code yet, template | [mpc.md](mpc.md) |
|