# Pump Lead/Lag v0.1 — sequence and model contract

Implemented under the user-approved 2026-09-13 proposal. Open `pump-simulator.html`
directly. Educational model only: no physical validation, manufacturer parity or
equipment selection is claimed. All defaults and bounds are teaching choices.

## Module boundaries and units

`js/pump/config.js` centralizes constants, defaults and validation;
`pressure-loop.js` owns pure PI; `controller.js` owns pure sequencing and timers;
`model.js` owns hydraulics, speed ramp, proof and runtime; `engine.js` owns time,
edits and history. `charts.js` / `ui.js` render independently. The shared
`trend-cursor.js` inspects samples without changing simulation state.
Canonical units: kPa, L/s, seconds, runtime hours and percent speed. L/s / US gpm
display changes preserve the physical value of rated flow.

## Pressure loop and output ownership

```
error = DP setpoint - measured DP
P = 100 * error / proportional band
I increment = error * integral gain * elapsed seconds / 60
Auto speed = limit(P + stored I, minimum speed, maximum speed)
```

Integral gain is percentage points per kPa per minute. Bias seeds I when automatic
control starts; zero integral gain gives biased P control. This is conventional PI,
not the Delta CO used by FCU/VAV; no unsupported derivative equation is introduced.
Conditional anti-windup blocks outward integration at a limit and lets inward
corrections unwind gradually. Corrections crossing a limit stop at that limit.
Tuning changes retain I; configured Bias changes replace I. Disabling Auto clears
loop memory. Maximum/minimum speed can leave unmet/excess DP, which remains visible.

Both commanded Auto pumps share one PI output. Manual pumps use their own 0–100%
speed, contribute to hydraulics and are excluded from Auto staging/alternation.
Manual bypasses Auto speed limits and run/off timers. System Off, individual Off
and latched faults override commands. Explicit mode changes and switching from
Assist to Standby override demand-driven minimum-run holding.

## Lead, lag and alternation

1. Select Pump 1, Pump 2 or least accumulated runtime (ties choose Pump 1).
   Unavailable preferred pumps fall back to the other eligible Auto pump.
   Stopped Auto pumps wait for minimum off time; that time is satisfied initially.
2. Assist qualifies lag start while lead proof is true, actual lead speed is at
   least the start threshold, and SP minus DP is at least the deficit threshold.
   Require the continuous start delay and an eligible minimum-off-ready lag pump.
3. Lag stop requires Auto speed command at/below the stop threshold and DP at
   least SP minus the allowed deficit, for the continuous stop delay, plus lag
   minimum run time. Broken qualification resets its timer. Separate thresholds
   provide hysteresis. Duty/Standby never adds a pump for demand assistance.
4. A positive timed-alternation interval requests the other eligible pump after
   lead minimum run time; zero disables it. Changing lead selection requests that
   pump and waits for run/off constraints instead of discarding the request.
5. Start the incoming pump while retaining the outgoing lead. Release the old
   lead after incoming proof and actual speed within 2 percentage points of the
   old lead. If assistance was already active, both stay on and roles swap.
   Reset rotation and staging qualification. DP may change during overlap.
6. An incoming fault cancels handover and retains the healthy lead. A lead fault
   transfers duty to an eligible alternative. Minimum off still applies to a
   recently stopped replacement. No eligible pump leaves automatic demand unmet.

Run/off timers use commanded state. Accumulated runtime uses actual nonzero speed,
including ramp-down and missing-proof operation. Rotation uses lead commanded-on
time and pauses during handover. This is a two-identical-pump teaching sequence.

## Proof, faults and reset

Normal proof requires actual speed at/above 5% for the configured proof delay.
Proof timeout must exceed ramp-to-threshold plus normal delay. Proof represents
motor status, not hydraulic delivery: a running pump behind a closed check valve
can have zero branch flow. Manual speed below 5% can cause a proof timeout.

- Drive trip immediately stops the modeled pump, latches alarm and removes command.
- Missing proof leaves the pump physically following its command but forces proof
  false. Continuous command without proof reaching timeout latches it out;
  command becomes zero, speed ramps down and the alternative can take over.
- Fault removal alone does not clear a latch. Select None, Apply settings, then
  Reset alarms. Reset is blocked while the injected fault remains. Paused reset
  waits for Resume. Both faults leave automatic demand unmet.

Dry-run, low-suction and manufacturer protection sequences are not modeled.

## Hydraulic and actuator assumptions

For rated pressure Pr, rated flow Qr, actual speed fraction n and branch flow q:

```
pump head = Pr * [2*n^2 - (q/Qr)^2]
q_i(H) = Qr * sqrt(2*n_i^2 - H/Pr), or 0 when the radicand is not positive
circuit pressure = Pr * R * [(q_1 + q_2)/Qr]^2
```

The zero-flow branch represents an ideal check valve preventing reverse flow.
Bounded bisection solves common pressure equality with total circuit flow.
Resistance multiplier R represents circuit restriction. At R=1, one full-speed
pump gives H=Pr and Q=Qr. Two give H=1.6Pr and Q=sqrt(1.6)*Qr, not doubled flow.
Unequal-speed pumps share pressure; the slower branch may deliver zero flow.

Actual speed changes by at most `100*dt/full-ramp-seconds` points per step.
Pressure/flow are quasi-steady at each step. Water inertia, pipe storage, static
lift, detailed branches, remote critical-valve DP, sensor dynamics, heat transfer,
power, efficiency and cavitation are omitted. The sensor spans the common circuit.
Invalid/non-finite inputs or results fail explicitly rather than being silently fixed.

## Time, lifecycle and trends

One-second physical steps are independent of playback speed. At each boundary the
controller accounts for the preceding physical interval, then evaluates any
queued edit with zero additional elapsed time. Initial evaluation uses zero time.
Live edits are atomic; paused edits and alarm resets wait for Resume. Initial
runtimes and duration lock after Start. Reset restores run-start settings and
clears model/controller memory, history, alarms and cursor. Hidden pages and long
browser interruptions pause playback.

Samples occur every five seconds, at edit boundaries and completion; before/after
edit samples can share a timestamp. Events retain the latest 100 boundary-timed
entries. Unified trends have separate flow, pressure, speed and proof axes.
Optional tags expose commands and branch flows. Zoom, Earlier/Later and All time
change only the view. Cursor values come from full recorded samples, not
interpolated or thinned plot values. Native interaction needs real-browser review.

## Exercises and verification

- Default 60 kPa: one pump settles near 77.46% speed.
- Set SP to 130 kPa: Lag starts after sustained deficit; both settle near 90.14%.
- Lower SP to 30 kPa: stop qualification releases the lag pump after recovery.
- Duty/Standby at 200 kPa: one pump reaches its limit and DP remains unmet.
- Inject a lead trip/missing proof, or set alternation to 2 min; compare trends.
- Change PB, integral gain, ramp time or circuit resistance and inspect recovery.

Run `node tests/pump-tests.cjs` and `node tests/trend-cursor-tests.cjs` for numerical
and actual-page DOM coverage. These are not browser or physical validation.
Actual file-URL rendering, native inputs, responsive visuals and console checks
remain pending: the browser tool security policy rejects file-URL navigation.
