Files
pumpingStation/wiki/modes/powerbased.md
znetsixe 66fd3feff8 Add eval harness + Tier 2/3 mode template pages
### 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>
2026-04-22 16:49:41 +02:00

3.8 KiB
Raw Permalink Blame History

title, mode, tier, status, updated
title mode tier status updated
Power-based mode powerBased 2 placeholder 2026-04-22

Power-based mode — Tier 2 template

Status — not yet implemented. Placeholder. This page documents the intended shape of a grid-aware / netcongestion-aware station.

At a glance

Item Value
Tier 2 — parameterised transfer function
Signal driving demand basin level (primary), max-power budget (clip)
Secondary inputs measured pump power, live grid-price / peak-hours signal
Output demand 0100 % clipped so Σ pump power ≤ maxPowerKW(t)
Thresholds adjusted at runtime? maxPowerKW(t) yes — level thresholds no
Use when Grid has peak-hour tariffs or net-congestion caps

Diagram — the levelbased curve with a moving clip ceiling

demand %                                     ← dashed line: levelbased curve
 100 ┤                ───────                ← solid: clip at powerBudget(t)
     │                          clip lowers
     │                          during grid peak
     │                   ─────────
     │                                
  0  ┼────────●───────●─────────────────────► level
             startLevel    maxLevel

         ↑ the family of curves:
           clip=100% (grid idle),
           clip=70% (shoulder),
           clip=40% (peak).

The shape stays levelbased; the ceiling drops when the grid is strained. That's the Tier-2 signature: same input axis, parameter shifts the curve.

Inputs

Signal Where from Role
current level as in levelbased primary input
config.control.powerBased.maxPowerKW editor, static hard cap on station power
config.control.powerBased.powerControlMode limit / optimize whether to just clip or to schedule
live grid signal (future) external topic or forecast modulates the cap over time
measured pump power power.measured.* from children real-time feedback against the cap

Threshold policy

Level thresholds (minLevel, startLevel, maxLevel) are identical to levelbased — they define the shape of the underlying curve. What's new is a runtime-varying ceiling demandCap(t) derived from the power budget.

demandCap(t) = 100 × (maxPowerKW(t) / nominalStationPowerAtFull) — where maxPowerKW(t) may come from config (static limit mode) or an external grid-price feed (dynamic).

Demand formula

rawDemand = levelbasedDemand(level)          # the underlying Tier-1 curve
demandCap = min(100, 100 × maxPowerKW(t) / nominalStationPower)
demand    = min(rawDemand, demandCap)

When demandCap < rawDemand, the mode sacrifices drainage rate to stay within power budget. Level may rise — the overfill safety layer still applies as the last line of defence.

Edge cases

  • Peak hour with rising level. demandCap drops faster than level rises → demand gets clipped; level approaches overflowLevel. If overfill safety trips, it overrides the clip (safety wins).
  • Power signal dropout. Fall back to static maxPowerKW from config; log warning.
  • Grid exit from peak while basin is nearly full. demandCap jumps back to 100; PID is memoryless so demand rises in one tick to match rawDemand.
  • Measured vs predicted pump power. Cap is enforced on predicted (decisions are made before the pump responds). Reconcile against measured for logging/diagnostics.