CANDUsim — Game Design Document & System Architecture
Version 0.1 · A 3D operator simulation of a generic 480-channel CANDU unit (Bruce-class geometry, CANDU 6 public state points). This document specifies what is simulated, how it is computed, how the player interacts with it, and how faults are injected. It is written for a reader who already knows the plant.
PLANT table in assets/candu-core.js is the single place to substitute your own.
Contents
- Part 0 — Design pillars & scope
- 1.1 Time & tick architecture
- 1.2 Neutron kinetics
- 1.3 Spatial model
- 1.4 Reactivity feedback & coefficients
- 1.5 Fuel & fuel management
- 1.6 Reactivity devices
- 1.7 Reactor Regulating System
- 1.8 Heat transport architecture
- 1.9 Secondary side & turbine-generator
- 1.10 Electrical classes & instrument air
- 2.1 Roles & 3D spaces
- 2.2 The core loop: keep the zones in band
- 2.3 Gamified procedures
- 2.4 HMI design
- 2.5 Scoring & progression
- 3.1 Fault engine architecture
- 3.2 Scenario catalogue
- 3.3 Special Safety Systems interaction
- 3.4 Severe-accident boundary
- Part 4 — Technical architecture
Part 0 — Design pillars & scope
Pillars
The plant is the antagonist
There is no enemy, timer, or score multiplier. Pressure is generated by the physics: xenon that will poison the core out in forty minutes, a zone average creeping toward 80 %, a stepback that undershoots. Every moment of tension must be traceable to a state variable.
Authenticity ladder
Fidelity is layered and audited in this order: physics (kinetics, thermalhydraulics, control), then procedures (what the operator does and in what order), then HMI (what it looks like). A pretty panel over wrong physics fails the ladder; correct physics with a simplified panel passes.
Learnable, not simplified
Difficulty tiers change the amount of assistance, never the physics. A Trainee sees the next control highlighted and hears the tutor; a Shift Supervisor sees the same plant with no prompts and a cold annunciator wall.
Difficulty tiers
| Tier | Assistance | Consequence model | Unlock |
|---|---|---|---|
| Trainee | Procedure sidebar with next step highlighted, tutor narration, alarm explanations on hover, time acceleration always available, undo of the last panel action within 10 s. | Trips and events are logged and explained; no career consequence. | Default. |
| Authorized Nuclear Operator | Procedure sidebar available but not auto-advancing; no highlighting; alarm text only; time acceleration limited to quiet plant states. | Reportable events and unplanned trips count against the unit; poison-outs cost a shift of production. | Complete tutorial campaign. |
| Shift Supervisor | None. Paper procedures in a binder object; operating memos; call-outs to field operators must be made explicitly. | Full OP&P evaluation; a second unplanned trip in a quarter ends the career run. | Complete 12 catalogued scenarios at ANO tier. |
Simulated versus abstracted
Simulated (state-driven, continuous)
- 14-zone coupled neutron kinetics with delayed and photoneutron groups
- Iodine/xenon per zone; samarium; burnup drift; moderator poison
- Fuel/coolant/moderator temperature and void feedback
- All reactivity devices with realistic worths and drive rates
- RRS (bulk and spatial control, setback, stepback, mode logic)
- Lumped heat transport: pressure, temperature, flow, inventory, pressuriser
- Steam generator pressure/level, BPC, turbine load, CSDV/ASDV
- SDS1/SDS2 trip logic (2-of-3), ECCS staging, containment pressure
- Fault library with sensor and process failures
Abstracted (table-driven, discrete)
- Per-channel thermalhydraulics (channel-level dryout is a lookup on channel power, flow and pressure, not a two-phase solve)
- Turbine mechanics beyond governor/load/vacuum (vibration, differential expansion are event tables)
- Chemistry (pH, conductivity, D2O isotopic) as slow first-order states with sampling events
- Fuelling machine mechanics as a sequenced state machine with fault hooks
- Radiological fields as zone-based dose rates keyed to plant state
- Severe-accident progression (see 3.4)
Engine recommendation
design decision The physics core is a separate deterministic module with no engine dependency, integrated by a thin adapter. The JavaScript reference implementation in assets/candu-core.js defines the contract: PLANT (constants), ReactorCore (kinetics, feedback, devices), RRS (regulation), HeatTransport (primary and secondary lumped model), SafetySystems (SDS1, SDS2, ECCS, containment), and Unit (scheduler, annunciator, fault injection). A game-engine port (C# for Unity, GDScript or C++ for Godot 4) is expected to be line-for-line, and the JS core stays as the golden reference for regression tests. Godot 4 is preferred for an independent developer (open licence, good 3D, built-in multiplayer); Unity is acceptable if the team already knows it. The 3D world must never own plant state; it reads a snapshot and posts commands.
Part 1 — Core simulation architecture
1.1 Time & tick architecture
Plant phenomena span nine orders of magnitude in time: the prompt neutron lifetime is under a millisecond, an MCA drop takes seconds, a zone fills in minutes, xenon peaks in ten hours, burnup drifts over months. A single tick rate cannot serve all of them, so the simulation is layered:
| Layer | Nominal step | Contents | Integration |
|---|---|---|---|
| Kinetics | 20 ms (adaptive up to 2 s) | Zone powers, precursors, photoneutron precursors | Fully implicit in the prompt and coupling terms; semi-implicit precursors |
| Controls | Same substep as kinetics (RRS is evaluated every kinetics step; real DCC cycle is ~0.5 s and can be emulated with a hold) | RRS power error, valve lifts, device drives, SDS logic | Discrete update |
| Plant / thermal | Same substep; internal time constants 2–60 s | Fuel and coolant temperatures, HT pressure, pressuriser, SG pressure and level, turbine load, containment pressure | First-order lags, exponential relaxation (unconditionally stable) |
| Poisons & fuel | Same substep (implicit) | I-135, Xe-135, Sm-149, burnup, moderator poison concentration | Semi-implicit; exact for constant flux across the step |
| Bookkeeping | 1 s of simulated time | History record, annunciator evaluation, event log, telemetry | — |
Adaptive step and time acceleration
The scheduler in Unit.advance(wallDt) multiplies wall time by the selected time scale and substeps. The substep is 20 ms whenever anything fast is happening (|log rate| > 2 %/s, shutoff rods or poison in motion, power above 105 %FP); 100 ms when the rate exceeds 0.2 %/s; otherwise up to 0.5 s at real time and up to 2 s when accelerated. Two numerical choices make large steps safe:
- The prompt term (ρ−β)/Λ, which is stiff (a −80 mk trip gives a rate of −95 s⁻¹), and the inter-zone coupling term are solved fully implicitly: the 14 zone powers are the unknowns of a 14×14 linear system solved by Gaussian elimination with partial pivoting (
solveDense). The system matrix is diagonally dominant, so any step length is stable. - Precursor groups, iodine and xenon are advanced semi-implicitly (production explicit, decay and burn-out implicit), which is unconditionally stable and exact for constant flux within a step. The 3.01 s⁻¹ sixth delayed group and the 0.277 s⁻¹ shortest photoneutron group would otherwise force steps below 0.3 s.
Time acceleration is offered in ×1, ×10, ×60 and ×600. At Trainee tier it is always available; at higher tiers it is inhibited while any annunciator is unacknowledged or any device is in motion. design decision
Determinism and replay
All randomness (transmitter noise, fault onset jitter, fuelling machine hiccups) comes from a seeded generator. The event log — every operator command with its simulated timestamp, every fault activation, every trip — is the ground truth of a session; a replay is the event log re-applied to the same seed. A save is the state vector (zone powers, precursors, poisons, temperatures, device positions, HTS state, SSS state, per-channel fuel state) plus the seed and event log. Golden-run regression tests (Part 4) compare state vectors at fixed checkpoints.
1.2 Neutron kinetics
Each of the 14 zones carries its own set of point-kinetics equations. For one zone with relative power n, delayed precursor concentrations Ck, photoneutron precursors Cpj, and a coupling term to the other zones:
dn/dt = ((ρ − β)/Λ)·n + Σ_k λ_k·C_k + Σ_j λ^p_j·C^p_j + S + κ·Σ_i w_i·(n_i − n) dC_k/dt = (β_k/Λ)·n − λ_k·C_k k = 1..6 (fission-product delayed groups) dC^p_j/dt = (β^p_j/Λ)·n − λ^p_j·C^p_j j = 1..9 (D2O photoneutron groups) β = Σ_k β_k + Σ_j β^p_j (β_eff is the TOTAL delayed fraction) ρ = ρ_fuel + ρ_cool + ρ_mod + ρ_void + ρ_Xe + ρ_LZC + ρ_adj + ρ_MCA + ρ_SDS1 + ρ_SDS2 + ρ_poison + ρ_burnup + ρ_zone κ = 2·Δk_harmonic / Λ, Σ_i w_i = 1 (see 1.3)
Delayed-neutron data
The six fission-product groups use Keepin's U-235 thermal relative yields and decay constants, scaled so that their sum plus the photoneutron fraction equals βeff. βeff is a PLANT parameter because it drifts with burnup: a fresh natural-uranium core is dominated by U-235 (β ≈ 0.0065), while an equilibrium core derives a large share of its fissions from bred Pu-239 (β ≈ 0.0021), pulling the effective value to roughly 0.0056 assumed. The fuel-management module (1.5) supplies the current value; the kinetics module never assumes it.
| Group | Relative yield | λ (s⁻¹) | Half-life |
|---|---|---|---|
| 1 | 0.033 | 0.0124 | 55.7 s |
| 2 | 0.219 | 0.0305 | 22.7 s |
| 3 | 0.196 | 0.111 | 6.2 s |
| 4 | 0.395 | 0.301 | 2.3 s |
| 5 | 0.115 | 1.14 | 0.61 s |
| 6 | 0.042 | 3.01 | 0.23 s |
Why the CANDU is "soft"
The prompt neutron lifetime in a heavy-water lattice is about 0.9 ms, thirty to fifty times longer than in a light-water core. Combined with the delayed fraction, this means the stable period for a given reactivity is long and the power response to a device movement is gentle: a 1 mk ramp over 100 s peaks at 100.1 %FP under RRS control in the reference model, and a −80 mk shutoff-rod insertion drops power by a factor of about 15 in the prompt jump rather than by orders of magnitude. The other side of the coin is that positive reactivity is also slow to arrest; the positive void coefficient (1.4) is only tolerable because two independent fast shutdown systems exist.
Photoneutrons
Deuterium has a (γ,n) threshold of 2.22 MeV, and several fission-product gamma emitters exceed it. Their decay produces neutrons long after fission has stopped. The model carries nine photoneutron groups assumed yields with half-lives from 2.5 s to 12.8 d and a total fraction near 3×10⁻⁴ of neutrons at equilibrium. Consequences that the player will experience:
- After a trip the log rate settles at a few tenths of a percent per second negative and keeps flattening for hours; the reactor never reaches a "zero" reading, which is why the start-up instrumentation reads a genuine signal from a recently-operated core.
- A restart within a day is an approach to critical from a strong internal source; a restart after weeks is a source-range start-up with the external neutron source and a much longer, more careful 1/M procedure (2.3).
- Photoneutrons slightly increase the effective delayed fraction in steady operation, and the model accounts for their share inside βeff — omitting it produced a persistent +0.29 mk imbalance during development, a useful reminder that the bookkeeping must close.
1.3 Spatial model
A CANDU core is large compared with the neutron migration length, so it is loosely coupled: one side of the core can rise in power while the other falls, with the bulk power unchanged. This is what makes xenon spatial oscillations possible and is the entire reason liquid zone control exists. Point kinetics cannot show it. A full 3-D diffusion solve at game frame rates is unnecessary. The chosen model is fourteen coupled point-kinetics nodes, one per liquid zone compartment, laid out in two axial halves of seven (top-left, top-centre, top-right, mid-left, mid-right, bottom-left, bottom-right).
Coupling weights are proportional to 1/d² between zone centres and row-normalised. The coupling strength κ is not a free constant; it is set from the eigenvalue separation between the fundamental and first-harmonic flux modes, a quantity with physical meaning that a reactor physicist can adjust. With a first non-trivial eigenvalue of the weight matrix near 0.5, a pure tilt mode decays at κ(1−λ₁), giving κ ≈ 2·Δkharmonic/Λ. The default Δkharmonic = 13 mk assumed; at 12 mk the xenon oscillation diverges violently, at 14 mk and above it is stable — 13 mk gives the slowly divergent behaviour a large CANDU actually has.
Tier-2 option: coarse-mesh diffusion for display
design decision For the flux-mapping display and the fuelling engineer's channel-power map, a coarse-mesh two-group diffusion solve on roughly 22×22×12 nodes can run asynchronously every simulated two minutes (matching the real flux-mapping cadence), constrained to reproduce the 14 zone powers from the kinetics model. It has no feedback into the game state; it exists to make the channel power map and CPPF (1.5) spatially credible. If it is never built, channel powers are synthesised from zone powers, a stored reference shape, and per-channel fuel age.
Instrumentation model
| Detector | Count (representative) | Range | Used by | Failure modes in the fault library |
|---|---|---|---|---|
| Ion chambers (log range) | 3 (RRS) + 3 per SDS | 10⁻⁷ to 1.5 FP, log rate | RRS at low power, SDS log-rate and low-power trips | Loss of HV, moisture, gamma shine after trip (over-reads) |
| Platinum in-core detectors | ~28 for RRS, ~34 per SDS channel set | Linear, 5 %–120 % | RRS zone power, ROP/high neutron power trips | Drift, open circuit, wrong calibration after fuelling |
| Vanadium flux-mapping detectors | 102 | Linear, slow (5.5 min half-life) | Flux mapping every ~2 min; calibration of the platinum detectors | Failed detector, mapping program halted |
| Thermal power (ΔT × flow) | Per channel via outlet RTDs and instrumented channels | — | Calibration of neutron power above ~15 % | RTD failure, flow instrument failure |
1.4 Reactivity feedback & coefficients
| Effect | Value (equilibrium fuel) | Sign / note | Model implementation |
|---|---|---|---|
| Fuel temperature | −0.0045 mk/°C assumed | Negative (Doppler). Fresh fuel is somewhat more negative. | Per-zone fuel temperature, 6 s lag to power |
| Coolant temperature | +0.03 mk/°C assumed | Positive at equilibrium; small | Per-zone coolant temperature, 15 s lag |
| Moderator temperature | +0.07 mk/°C equilibrium; negative in a fresh core assumed | Sign flips with burnup — a fresh-core scenario must flip it | Single moderator temperature state |
| Coolant void, full core | +10 mk assumed | Positive; about half per loop in a two-loop plant. The defining CANDU safety characteristic. | Per-zone void fraction from ROH pressure vs. saturation |
| Power coefficient, 0 → 100 % | ≈ −3 mk net (fuel dominates) assumed | Sum of the above along the operating line | Emergent |
| Xenon-135 equilibrium load | −28 mk at 100 %FP | Normalisation constant of the I/Xe chain | Per-zone I and Xe; burn-out rate 2.6×10⁻⁴ s⁻¹ at FP |
| Xenon transient after trip | Peak ≈ −125 mk at ~10 h; initial growth ≈ 0.45 mk/min | Emergent from the chain constants above | — |
| Poison-override window | ≈ 35–45 min after a trip from full power | Adjuster worth (16 mk) divided by the xenon growth rate, less margins | Emergent |
| Samarium-149 | ≈ −6 mk equilibrium; rises a few mk after shutdown, no burn-out recovery on its own | Slow (Pm-149 half-life 53 h) | Single-state chain, updated with the poisons |
| Moderator poison (Gd or B) | Operator-set; up to −30 mk or more for guaranteed shutdown state | Added by chemistry; removed by ion exchange over hours | moderatorPoisonMk state with addition and removal rates |
| Burnup drift | Loss of ~0.4 mk/day at full power without fuelling assumed | Negative; fuelling restores it | burnupMk plus per-zone bias |
The iodine–xenon chain
dI/dt = γ_I·φ − λ_I·I dX/dt = γ_X·φ + λ_I·I − λ_X·X − σ_X·φ·X λ_I = 2.87e-5 s⁻¹ (6.6 h) λ_X = 2.09e-5 s⁻¹ (9.1 h) γ_I = 0.0639 γ_X = 0.0025 σ_X·φ_FP = 2.6e-4 s⁻¹ (σ ≈ 2.65e6 b, φ ≈ 1e14 n·cm⁻²·s⁻¹) ρ_Xe = −28 mk · X / X_eq(FP)
Because the burn-out rate at full power is more than ten times the xenon decay constant, the post-trip peak is severe: burn-out stops instantly while the accumulated iodine keeps decaying into xenon. This is the physical fact behind the poison-override window, and it is the single most important number in the operator's day.
Fresh cores
A core loaded entirely with fresh natural-uranium fuel has far more excess reactivity than the devices can hold and a moderator temperature coefficient of the opposite sign. The initial load therefore contains depleted-uranium bundles in selected positions, and the first months of operation are a distinct regime (the "plutonium peak", when bred Pu-239 raises reactivity before fission products and burnup bring it down). The game treats the fresh-core state as a separate scenario family with its own coefficient set; the default career starts in an equilibrium core. design decision
1.5 Fuel & fuel management
| Item | Value | Note |
|---|---|---|
| Fuel | Natural UO₂, 37-element bundle, Zircaloy-4 sheath | 0.495 m long, ~19 kg U, ~23.7 kg total |
| Channels / bundles per channel | 480 / 13 | Generic Bruce-class geometry; CANDU 6 is 380 / 12 |
| Discharge burnup | ≈ 7–8 MWd/kgU (≈ 170–190 MWh/kgU) | Natural uranium; no enrichment |
| Refuelling rate at full power | ≈ 2 channels/day, ~16–18 bundles/day | Emergent from burnup drift and channel count |
| Bundle-shift scheme | 8-bundle shift (CANDU 6); 2- or 4-bundle shift for Bruce-class | design decision selectable per plant profile; affects the reactivity worth of one refuelling |
| Fuelling direction | Alternating between adjacent channels | Balances axial flux shape |
| Maximum channel power | ≈ 7 MW assumed | Licence limit; CPPF measured against it |
| Maximum bundle power | ≈ 900 kW assumed | Fuel integrity limit |
Channel power peaking factor and the ROP margin
The regional overpower (ROP) trip protects against fuel dryout in the highest-powered channel. Its setpoint is not a fixed 122 %: it is adjusted for the current channel power peaking factor (CPPF), the ratio of the highest actual channel power to its reference value. Refuelling a channel raises its power for days (fresh bundles in the highest-flux positions, before the plutonium peak passes), raising CPPF and lowering the effective ROP margin. This gives the fuelling engineer's list its constraints: fuel channels that are burnt out, but not so many high-flux channels at once that the ROP margin collapses, and keep the zone average in band (2.2). In the model:
ROP_setpoint_effective = ROP_base / CPPF (ROP_base ≈ 1.22 FP, CPPF typically 1.06–1.12) Trip if any zone-mapped detector reading > ROP_setpoint_effective
Data model
Channel {
id: "L12", row, col, zone: 4,
bundles: [ { burnupMWdkg, ageDays, positionIndex } × 13 ],
powerMW, referencePowerMW, cppfContribution,
flowKgS, outletTempC, dryoutMargin, // channel-level lookup
feederStatus, pressureTubeStatus, annulusGasDewPoint
}
Zone { index, powerFraction, lzcLevel, xenon, iodine, bias_mk }
Each refuelling raises the target zone's bias_mk by a scheme-dependent amount (≈ +0.3 mk for a 4-bundle shift, ≈ +0.5 mk for an 8-bundle shift assumed), which then decays toward the burnup baseline over the following weeks. The bulk burnupMk falls continuously at full power. The sum of the two is the reactivity budget the operator manages with the zones.
1.6 Reactivity devices
| Device | Count | Worth | Rate | Normal position | Controlled by |
|---|---|---|---|---|---|
| Liquid zone controllers | 14 compartments in 6 tubes | ≈ 7 mk total (≈ 0.5 mk each) | ≈ 0.1 mk/s for all 14 at full valve lift | 20–70 % level | RRS (bulk + spatial); manual per zone available |
| Adjuster rods | 21, in 7 banks | ≈ 16 mk when all withdrawn | ≈ 0.03 mk/s (bank sequence, ~10 min total) | Fully IN (flux flattening) | RRS when zones out of band; manual for poison override |
| Mechanical control absorbers | 4 | ≈ 10 mk when all inserted | Drive ≈ 0.05 mk/s; gravity drop in seconds on stepback | Fully OUT | RRS (stepback and zones high); manual |
| Moderator poison | — | As required; ≥ 30 mk for guaranteed shutdown state | Addition minutes; removal by ion exchange, hours | Near zero at equilibrium | Operator via chemistry |
| SDS1 shutoff rods | 28–32 | ≈ −80 mk | Full insertion ≤ 2 s (spring-assisted gravity drop); withdrawal by motor in two banks, ~3 min each | Fully OUT (poised) | SDS1 logic; manual trip; operator withdrawal after reset |
| SDS2 liquid poison injection | 6–8 nozzles | ≈ −300 mk | ≈ 1 s (helium-driven gadolinium nitrate) | Poised | SDS2 logic; manual trip; clean-up by ion exchange over hours |
All worths are equilibrium-core representative values assumed. Device worths interact (a rod's worth depends on where the flux is), which the reference model ignores; the Tier-2 diffusion option can supply position-dependent worths later.
1.7 Reactor Regulating System
RRS is a program on the dual digital control computers. DCC X and DCC Y each run the full program; one is in control, the other tracks and takes over on watchdog failure. The game models both computers as objects with health states so that a DCC failure is a first-class fault (3.2).
RRS.step(). The setpoint generator is where operator intent, unit power regulator, setback and stepback compete; the power error is where RRS decides how hard to move which device.Power error
e_P = (P − P_d) / P_d fractional power error
e_R = logRate − demandedRate demandedRate = clamp(ln(P_d/P)/5 s, ±2 %/s)
E = K_P·e_P + K_R·e_R K_P = 40, K_R = 60 (design decision)
→ 100 % valve lift at 2.5 % power error or ≈1.7 %/s rate error
zone lift_i = clamp(E + K_S·(n_i − n̄)/n̄, −1, +1) K_S = 4 (spatial control gain)
Positive E means power is high: zones fill (inflow valve opens, adding light-water absorber). Negative E drains them. The spatial term acts on the deviation of each zone from the mean, so the bulk and spatial functions share the same valves. When the average zone level leaves its 20–80 % band and the power error agrees, RRS calls on the slower devices in a fixed order: zones low and power low → MCAs out first, then adjuster banks out; zones high and power high → adjusters in first, then MCAs in. Nothing moves when the band is satisfied, which is why a unit at steady state can sit for hours with zone levels drifting and no device motion — and why the operator is watching that average.
Modes
| Mode | Who leads | Reactor setpoint from | Steam pressure held by | Used when |
|---|---|---|---|---|
| Normal | Turbine | Unit power regulator, adjusting reactor demand to hold boiler pressure at the turbine's load | Reactor power | Normal at-power operation |
| Alternate | Reactor | Operator target and ramp rate | BPC via governor valves and CSDVs | Start-up, low power, shutdown, upset recovery, any time the turbine is not available as the lead |
Setback and stepback
| Action | Mechanism | Representative initiators | Endpoint |
|---|---|---|---|
| Setback | Setpoint ramped down at a fixed rate (0.1–0.5 %FP/s depending on initiator) using zones, then adjusters/MCAs as needed | High zone power, high local (bundle) power, loss of spatial control (flux tilt), high SG level, low condenser vacuum, high moderator temperature, low deaerator level, loss of Class IV to one HT pump group | Target depends on initiator (2 %, 20 %, 60 % FP) and holds until cleared |
| Stepback | MCAs released (gravity drop) until power is below the endpoint, then re-clutched; setpoint set to the endpoint | Turbine trip, loss of line (load rejection), HT pump trip, high HT pressure, high log rate above threshold, loss of both DCCs | 60 % (poison-prevent, for turbine/grid initiators) or 2 % (for HT initiators) |
The stepback endpoint of 60 % on turbine and grid initiators is the poison-prevent level: the reactor stays high enough that the xenon transient does not poison it out, with CSDVs dumping steam to the condenser until the turbine returns. If the condenser is lost too, the ASDVs relieve to atmosphere and the unit is on a clock: ASDV capacity alone does not sustain 60 %, and the operator must reduce power further and accept the poison-out risk.
Post-trip behaviour
design decision On a trip the setpoint is driven to a post-trip value of 10⁻⁴ FP. Zones keep regulating against it, so they fill while power is still above it (the conservative direction), and adjusters and MCAs are inhibited from automatic motion until the shutoff rods are fully out. The poison-override decision — whether to withdraw adjusters manually to chase the xenon — is deliberately the operator's, not the computer's. Stations differ in the details of post-trip RRS behaviour; this is the behaviour the game commits to, and it is one line in RRS.step() to change.
Loss of regulation
Any failure that leaves RRS unable to hold power at the setpoint is a loss of regulation: a DCC failure with a failed transfer, a zone drain on a failed valve or a wrong-sign power signal, a stuck adjuster bank, or a false-low power signal driving the zones empty. LOR events are the primary source of the "slow-then-fast" dramatic arc in the game (3.2): the plant does nothing alarming for a minute, then the rate meter moves, then either the operator or SDS1 ends it.
1.8 Heat transport architecture
HeatTransport. Headers are the observable state points; feeders and channels are abstracted to a channel-level table.Topology profiles
design decision The plant profile selects a topology: CANDU 6 (two figure-of-eight loops, each with 2 RIH, 2 ROH, 2 pumps, 2 SGs; loops can be isolated on a LOCA signal) or Bruce-class (single loop, 4 pumps, 8 SGs with integral preheaters, 4 RIH/4 ROH representative). The lumped model carries one pressure and temperature per header group and a per-loop inventory; loop isolation makes the two halves independent in the CANDU 6 profile.
Components and their state
| Component | Model state | Representative value | Why the operator cares |
|---|---|---|---|
| Fuel channel: pressure tube | Per channel: status, creep sag, hydrogen ingress (career-scale) | Zr-2.5Nb, 103.4 mm ID, 4.2 mm wall | Pressure-tube leak → annulus gas dew point rises; rupture → LOCA into calandria |
| Calandria tube and CO2 annulus | Annulus gas dew point, flow, pressure | Dew point normally below −25 °C assumed | First indication of a pressure-tube leak; a leak-before-break cue that gives time to shut down |
| End fittings, shield plugs, closure plugs | Fuelling machine interaction state | — | Fuelling sequence; leakage at closure |
| Feeders | Per channel flow (lookup); blockage fault | — | Low channel flow → localised boiling → dryout |
| Headers | Pressure, temperature per RIH/ROH group | RIH 266 °C / 11.2 MPa; ROH 310 °C / 9.9 MPa | Trip parameters (high/low HT pressure), void formation |
| HT pumps | Running count, speed, rundown | 4 (Bruce-class) or 4 (CANDU 6, two per loop); rundown ~30 s to natural circulation | Low flow trip; pump trip stepback; thermosyphoning after loss of Class IV |
| Pressuriser | Level, pressure, heater state, steam bleed | Level setpoint rises with power (shrink/swell), 30 % → 65 % representative | Low pressuriser level trip; pressure control |
| Feed and bleed | Feed pump state, bleed valve lift, bleed condenser level/pressure | Restores pressuriser level over ~1 min in auto | Backup pressure control; failure family in 3.2 |
| D2O collection, purification, storage | Storage tank inventory, IX state, recovered vs. lost D2O | — | D2O losses are an economic and tritium-dose metric |
| Moderator | Temperature, level, cover gas D2 concentration, poison concentration | ≈ 5 % of thermal power; ~62 °C; He cover gas with recombiners | High moderator temperature trip and setback; emergency heat sink; poison addition/removal |
| End shields and shield tank | Cooling flow, temperature | — | Loss of end-shield cooling is a slow shutdown-required event |
| Leak detection | Tritium in secondary side, beetles (moisture detectors), sump levels | — | SG tube leak → tritium in feedwater; D2O leak localisation for the field operator |
Boiling at the outlet
A CANDU at full power operates with a few percent steam quality at the outlet of the highest-powered channels. The lumped model computes a saturation temperature from ROH pressure (Tsat ≈ 180 + 13.5·PMPa across 8–11 MPa, a linear fit accurate to ~1 °C assumed fit) and a bulk void fraction from the ROH temperature margin to it. Void is fed to the kinetics as a positive reactivity. A depressurisation therefore does two things at once — it takes away the coolant's ability to remove heat and it adds reactivity — which is the physics behind the high and low HT pressure trips and the sizing of SDS1 and SDS2.
1.9 Secondary side & turbine-generator
| System | Model | Representative parameters |
|---|---|---|
| Steam generators (8, integral preheaters) | Single lumped pressure and level; heat transfer ∝ (Tprimary − Tsat,secondary) | 4.7 MPa, 260 °C saturated; level control 3-element (level, steam flow, feed flow) |
| Boiler pressure control (BPC) | Holds SG pressure by governor valves (turbine available) then CSDVs then ASDVs | Setpoint 4.7 MPa; CSDV capacity ≈ 70 % of full steam flow; ASDV ≈ 10 % |
| Main steam safety valves | Lift on high pressure; used for crash cool-down on a LOCA signal | Lift ≈ 5.2 MPa assumed |
| Turbine | Governor valve position → load; HP and LP sections with moisture separator reheaters as an efficiency table; vibration and expansion as event tables | ≈ 915 MW gross at 100 %FP; synchronisation window; overspeed trip 110 % |
| Generator / exciter | MW, MVAr, voltage; grid breaker | Loss of line opens the breaker; house load is carried by the unit service transformer |
| Condenser | Vacuum as a state; loss of CCW or air in-leakage faults | Low vacuum setback then turbine trip |
| Feedwater | Deaerator level/pressure, BFPs, auxiliary feed pump, feedwater heaters as a temperature table | Loss of all feed → SG level falls; low SG level trip; aux feed and emergency water supply as heat sinks |
Load rejection response
The sequence the game reproduces on a loss of line: the generator breaker opens; the turbine governor closes to hold speed on house load; SG pressure rises immediately; BPC opens the CSDVs; RRS steps back to 60 % by dropping the MCAs; power undershoots (to ~38 % in the reference run) and recovers to 60 % on the zones; xenon begins to rise and the zones drift down, and after some minutes RRS begins withdrawing adjusters to hold 60 %. The operator's tasks are to confirm CSDV operation, confirm the stepback endpoint, verify house load is stable, and decide with the grid operator whether to resynchronise. If the condenser is lost as well, the sequence becomes a race against the poison-out.
1.10 Electrical classes & instrument air
| Class | Source | Feeds | On loss |
|---|---|---|---|
| Class IV | Grid or the unit's own generator via the unit service transformer | HT pumps, boiler feed pumps, condenser cooling water pumps, large auxiliaries | HT pumps run down to natural circulation (thermosyphoning), feedwater lost, condenser lost; reactor stepback then trip on low flow; Class III diesels start |
| Class III | Class IV normally; standby diesel generators on loss (start ≤ 30 s, load within ~2 min) | Auxiliary feed, shutdown cooling, ECC pumps, moderator cooling, D2O feed, instrument air compressors, chargers | Only Class II/I remain: the plant depends on batteries and the emergency power supply |
| Class II | Inverters from Class I batteries, charged from Class III | DCCs, control power, RRS, SDS logic, essential instrumentation | Loss of computer control; SDS trips on loss of power (fail-safe); a genuine emergency |
| Class I | Batteries (typically hours of capacity) | DC controls, breaker control, emergency lighting, turbine emergency lube oil | Same as Class II; battery duration is the clock in a station blackout scenario |
| EPS / QPS | Seismically qualified diesels and distribution, separate from the above | Emergency water supply, ECC recovery, some SDS support | — |
| Instrument air | Compressors on Class III, receivers with minutes of capacity | Pneumatic valves and actuators (CSDVs, feedwater regulating valves, zone control valves) | Valves fail to their designed position (zone valves fail closed → zones freeze; CSDVs fail closed; feedwater valves fail open or closed by design) — a rich source of "the plant misbehaves in a consistent way" faults |
Part 2 — Gameplay loop & operator mechanics
2.1 Roles & 3D spaces
Control Room Operator
Sits or stands at the unit's control panels: from left to right (representative layout design decision), reactor and reactivity mechanisms, heat transport and moderator, boilers and feedwater, turbine-generator, electrical. Above the panels, a wall of annunciator windows grouped by system. On the desk, DCC CRTs with mimic, trend and alarm summary displays and the keyboard for setpoint entry. Every control on the panel is a 3D object that can be operated by looking at it and pressing, turning, or holding it; every readout is a live render from the state snapshot.
Field Operator
Walks the plant: fuelling machine vaults and the maintenance lock, boiler room, turbine hall, HT pump rooms, D2O management area, the sampling stations, diesel generator rooms, the vacuum building duct. Field tasks are physical: local valve operation, reading local gauges, confirming pump status, collecting samples, finding leaks with a moisture meter, resetting a fuelling machine fault. Dose fields are real and accumulate on the player's dosimeter.
Shift Supervisor
Approves and authorises: fuelling lists, reactivity changes beyond limits, entering an Operating Memo, calling the grid operator, declaring events. Manages people: assigns the field operator, calls in maintenance. In single-player the SS role is an AI voice that must be consulted for approvals; in co-op it is a third player.
A twelve-hour shift
| Time | CRO | Field operator | Notes |
|---|---|---|---|
| 07:00 | Turnover: read the log, review outstanding alarms, deficiencies, fuelling status, zone average, xenon state, planned tests | Turnover with outgoing FO; check the round sheet | The turnover briefing is the tutorial for every scenario: it tells the player what is already wrong |
| 07:30 | Panel walkdown: every readout compared against expected; annunciator lamp test | Start the round: pump rooms, D2O areas, local readings, leak inspection | Deviations found here are latent faults (3.1) |
| 08:00–11:00 | Fuelling coordination with the fuelling operator; monitor zone levels and CPPF; log entries every hour; respond to routine alarms | Fuelling machine vault support; chemistry samples (HT, moderator, SG blowdown) | Refuelling of one channel: 45–90 min of game time, accelerable |
| 11:00 | Routine surveillance test (e.g. SDS1 channel D trip test, ECC valve stroke) | Local support for the test | Tests are procedures with their own error modes; a wrong step can cause a real trip |
| 13:00–17:00 | Power manoeuvre if requested by the grid; moderator poison adjustment as burnup and fuelling dictate | Second round; D2O recovery drumming; sump checks | — |
| Any time | Alarm response: acknowledge, diagnose from the mimic, act per procedure, log | Investigate field cues on request | The fault engine decides when |
| 18:30 | Log completion; turnover briefing prepared | Round sheet completed | The player's briefing quality is evaluated at SS tier |
2.2 The core loop: keep the zones in band
The average liquid zone level is the reactor's reactivity budget shown as a single number. Everything that adds reactivity raises it (RRS fills the zones to hold power): refuelling, xenon burn-down after a power increase, moderator poison removal, moderator temperature rise. Everything that removes reactivity lowers it: burnup, xenon build-up after a power reduction, poison addition. RRS keeps power exactly at the setpoint as long as the zones can, and asks for adjusters or MCAs only outside 20–80 %. The operator's standing job is to keep the average comfortably inside the band, with enough margin in both directions to absorb the next disturbance:
- Too high (approaching 80 %): the next refuelling would push RRS into driving adjusters in, which distorts the flux shape and reduces ROP margin; the operator defers fuelling or adds a little moderator poison.
- Too low (approaching 20 %): a power reduction or a lost fuelling day would push RRS into withdrawing adjusters, again distorting the flux; the operator requests fuelling or removes poison.
- Tilt: a zone sitting at 90 % while the others sit at 40 % means the spatial control is working hard against a local perturbation — a recently fuelled channel, a xenon oscillation seed, or a failed zone valve. The operator watches individual zone levels, not only the average.
This loop is not invented; it is what the RRS design creates, and it is satisfying for the same reason the real job is: the numbers move slowly enough to reason about, every action has a visible consequence over the next hour, and there is always a next disturbance on the way. The fuelling list, the poison concentration, the ROP margin and the zone average are the four dials of the strategic layer; the annunciator wall is the tactical layer that interrupts it.
2.3 Gamified procedures
Each procedure below is described as: the real procedure skeleton; the in-game interaction; scoring and consequence; what is deliberately not abstracted.
On-power refuelling
| Real skeleton | In-game interaction | Scoring / consequence | Not abstracted |
|---|---|---|---|
| Fuelling engineer issues a channel list with bundle counts and direction. Fuelling operator: verify channel, fuel-handling system status, D2O supply; move both fuelling machines to the channel; lock on, pressurise to HT pressure, unlock and remove closure plugs and shield plugs; the upstream machine pushes new bundles from its magazine while the downstream machine receives spent bundles; reinstall plugs, depressurise, unlock; travel to the new-fuel port / spent-fuel port; discharge to the spent fuel bay. | The CRO selects a channel from the list and checks the constraints (zone average, CPPF, ROP margin, channel age) shown beside each entry. The fuelling sequence runs as a state machine on its own mimic with a clock; the CRO watches the zone that will be perturbed and the D2O leakage rate at the machine head. At Trainee tier the sequence runs itself; at higher tiers the operator confirms each pressurisation and plug step and handles faults. As FO the player operates the machine head locally when the sequence stalls. | A refuelling that pushes a zone over 90 % or CPPF over the limit is an operating limit violation. A stalled machine on a channel with fuel partially withdrawn is a hazard state: the channel must be re-secured within a time window or the unit must be shut down. D2O losses are logged. | The reactivity worth of each refuelling, its zone location, the CPPF change, and the timing. The ram sequence and magazine mechanics are shown but not simulated below the step level. |
Liquid zone control management
| Real skeleton | In-game interaction | Scoring / consequence | Not abstracted |
|---|---|---|---|
| Zones normally in automatic. A zone is placed in manual to hold a level when its valve or level transmitter is suspect, or to bias it deliberately; the remaining zones continue in automatic. Alarms on zone level high/low, on average out of band, and on flux tilt. | Each zone has an auto/manual switch and a manual valve lift control on the panel and a level bar on the mimic. The player can take a zone to manual, set a level, and watch the spatial control redistribute the other thirteen. A stuck-valve fault leaves a zone frozen; the tilt grows; the player must recognise which zone is wrong from the pattern. | A tilt above the setback threshold with no operator action causes a setback; sustained tilt is a reportable event. Correctly isolating a failed zone and holding the tilt under limit is the win condition. | The bulk/spatial coupling: the zone the player moves affects all the others through RRS. The player cannot cheat by setting all zones manually — power then drifts and the RRS will call for adjusters. |
Reactivity mechanism handling and Approach to Critical
| Real skeleton | In-game interaction | Scoring / consequence | Not abstracted |
|---|---|---|---|
| Poison override: after a trip, reset SDS1 when the parameter clears, withdraw shutoff rods in banks, withdraw adjuster banks manually while watching the zones, raise power to the poison-prevent level before the xenon wins. Approach to critical from a long shutdown: with the core subcritical on poison and rods, remove poison in steps and plot 1/M (inverse count rate) against poison concentration or device position, extrapolating to criticality; withdraw rods in banks with holds. | The panel exposes the SDS1 reset pushbutton, the rod bank withdrawal switch (bank A, then bank B, with a hold at any time), the adjuster bank selector and drive switch, the MCA drive, the moderator poison addition request and the ion-exchange removal request. The trend display plots power and rate; a 1/M plot tool is provided in the procedure sidebar. The player must hold rod withdrawal when the rate rises and let the zones catch up. | Withdrawing the second rod bank without holds trips the reactor on high log rate — the reference model does exactly this at 0.44 mk/s with no holds and succeeds with one hold. Missing the poison-override window costs a ~30-hour outage (the xenon must decay) and is scored as lost production. Exceeding the approach-to-critical rate limits is a violation. | The xenon clock, the rod bank worths, the device drive rates, the RRS response. |
Power manoeuvres
| Real skeleton | In-game interaction | Scoring / consequence | Not abstracted |
|---|---|---|---|
| Enter target and rate on the DCC keyboard; RRS ramps the setpoint. Turbine: run-up, synchronise to the grid within phase/frequency/voltage windows, load; transfer between reactor-leading and turbine-leading modes. Load changes follow grid dispatch. | Keyboard entry of target and rate in %FP and %FP/s; the mode switch; the synchroscope and breaker close with a window. Ramp rates above limits are refused by the DCC with a message. The player watches SG pressure and zone levels during the ramp. | Synchronising out of window trips the turbine. Ramping into the zone band limits triggers device motion and a flux shape penalty. Load following as requested by the grid earns capability factor. | The thermal lag between reactor power and steam pressure; the xenon response to the power change (a reduction from 100 % to 60 % is followed hours later by a rise in zone levels that the operator must be ready for). |
Start-ups, shutdowns and the guaranteed shutdown state
| Real skeleton | In-game interaction | Scoring / consequence | Not abstracted |
|---|---|---|---|
| Guaranteed shutdown state is established by moderator poison at a concentration that keeps the core subcritical with all devices out, or by shutoff rods with their drives disabled. Heat-up and cool-down are rate-limited to protect pressure tubes and SGs. Start-up: establish heat sinks, warm the HTS on pump heat, pressurise, approach critical, raise power, roll the turbine, synchronise. | A multi-hour procedure run at up to ×60 with holds at the checkpoints: HT pressure and temperature within the heat-up envelope, moderator poison removal steps, SDS poised, RRS in alternate mode. | Exceeding heat-up rates is a violation; starting up without the SDS poised is an impossible state (interlocked) and an attempt is logged. | Reactivity balance through the whole sequence: temperature coefficients change sign relative to hot conditions; poison removal by ion exchange is slow. |
Routine tests
SDS channel trip tests (trip one channel of three, verify the logic, reset), ECC valve stroke tests, emergency diesel starts, and annunciator lamp tests are short procedures with real risk: a second channel failing during a test trips the reactor. They give the fault engine a natural place to reveal latent failures (a valve that does not stroke, a diesel that does not start) and give the player a reason to walk to the field.
2.4 HMI design
Alarm philosophy
- Annunciator windows are grouped by system, lamp-tested at shift start, and follow the standard sequence: new alarm flashes with an audible; acknowledge stops the flash; the window stays lit until the condition clears; a cleared-but-unacknowledged window flashes at a different rate. The reference model's
Unit.annunciatorimplements alarm / acknowledged / clear states with timestamps. - Sequence of events: every alarm is logged with a simulated timestamp to the millisecond on the DCC; the player can scroll it. Post-event analysis (the debrief screen) is built from this log.
- Alarm flooding is modelled honestly. A large LOCA produces dozens of windows in seconds. Prioritisation is by colour and by position in the summary display; the tutorial teaches the player to look at the first-out and at the safety-system status before anything else.
- DCC mimic displays present the system flowsheets with live values; trend displays present up to eight selected variables against time; both exist as objects in the 3D control room and as a 2D overlay for practicality.
Physical interlocks
Key-locked controls (SDS test switches, rod drive enable), guarded switches (manual trip, manual ECC initiation), and two-hand actions (poison injection, containment button-up override) are modelled as their physical objects: the player must obtain the key, lift the guard, or hold two controls. These are not decoration; they are the reason accidental trips are rare, and they make deliberate ones feel deliberate.
Learnability layer
| Aid | Trainee | ANO | SS |
|---|---|---|---|
| Procedure sidebar | Open, auto-advances, next step highlighted on the panel | Open on request, manual advance, no highlight | Paper binder object; no sidebar |
| Tutor voice | Explains each alarm and each step | Only for safety-system events | Off |
| Hover explanations | Every control and readout | Readouts only | Off |
| Undo of last panel action | 10 s | Off | Off |
| Time acceleration | Always | Quiet plant only | Quiet plant only |
2.5 Scoring & progression
There is no score. There is an evaluation, modelled on how a unit and a crew are actually assessed:
| Metric | Computed from | Shown as |
|---|---|---|
| Operating Policies & Principles compliance | Every violation of a stated limit (zone band, ramp rate, heat-up rate, CPPF, tilt, poison concentration) with its duration | List with timestamps in the debrief |
| Reportable events | Unplanned trips, SDS actuations, ECC actuations, containment button-ups, loss of a safety system's availability | Count per quarter; a narrative summary |
| Unit capability factor | MWh delivered / MWh possible over the career period | Percentage |
| Dose | Field time in dose fields; tritium uptake from D2O handling | mSv per shift and cumulative against limits |
| D2O losses | Leakage not recovered | kg per shift; cost |
| Alarm response | Time from alarm to acknowledgment and to first correct action | Distribution; outliers highlighted |
| Poison-outs | Trips not recovered within the override window | Hours of outage |
Career progression is Trainee → ANO → SS by completing the tutorial campaign and then catalogued scenarios at the tier above. Scenario unlocks are gated on the corresponding tutorial lesson, never on score.
Part 3 — Fault injection & emergency scenarios
3.1 Fault engine architecture
The fault engine is separate from the plant model. It never edits plant state directly; it edits the parameters and boundary conditions the plant model reads (a valve's stroke, a transmitter's transfer function, a break area, a pump's availability). This keeps the plant model honest and the faults composable.
Fault {
id: "lzc.valve.stuck",
target: { system: "lzc", component: "zone[7].inletValve" },
kind: "process" | "sensor" | "logic" | "power",
onset: { profile: "step" | "ramp" | "intermittent", duration_s, jitter_s },
severity: 0..1, // maps to break area, drift rate, stuck position...
latent: true | false, // latent faults show only when the component is demanded
observability: [ // ordered chain, each with a delay
{ layer: "physical", cue: "zone 7 level frozen", delay_s: 0 },
{ layer: "sensor", cue: "zone 7 level transmitter reads constant", delay_s: 0 },
{ layer: "alarm", cue: "FLUX TILT HIGH", delay_s: 300..1200 },
{ layer: "field", cue: "valve positioner air leak audible in LZC room", delay_s: 0 }
],
clears: { by: "field.repair" | "auto" | "never", time_s }
}
Scenario scripts
# scenario: lor-zone-drain-with-failed-dcc-transfer
seed: 8841
plant: bruce-class-480
initial: { power: 1.0, xenon: equilibrium, zoneAvg: 0.62, cppf: 1.09, shiftTime: "09:40" }
timeline:
- at: 00:12:00
inject: { id: "dcc.x.powerSignal.failLow", severity: 0.6, onset: { profile: "ramp", duration_s: 90 } }
- at: 00:12:30
inject: { id: "dcc.transfer.fail", latent: true } # DCC Y will not take over
- at: 00:20:00
condition: { trip: false }
inject: { id: "field.fo.busy", duration_s: 600 } # FO is in the turbine hall
evaluation:
win: [ "manual trip before highNeutronPower", "post-trip actions complete within 10 min" ]
fail: [ "SDS1 trip on HIGH NEUTRON POWER", "no acknowledgement within 60 s of first alarm" ]
Randomiser and plausibility
The procedural randomiser draws faults from the library with weights derived from representative failure rates (valves and transmitters often, DCC and SDS logic rarely), applies plausibility constraints (no two independent SSS failures in one shift unless the scenario is tagged "beyond design basis"; latent faults are placed before the shift and revealed by demand), and keeps a difficulty budget per shift so that the plant is usually quiet. The scenario director mode exposes the same library to an instructor or a second player, who can inject faults live and see what the operator sees.
Sensor versus process failures
Half of the fault library is instrumentation: transmitters failing high, low, stuck or drifting; detectors losing HV; RTDs open. These are the faults that make the game about diagnosis rather than reaction. A stuck SG level transmitter with the real level falling is an entirely different event from a real low level, and the plant gives the operator the information to tell them apart — redundant channels, the sequence of events, the physics (feed flow versus steam flow) — if the operator looks.
Implemented fault ids in the reference core
Unit.inject(id): load-rejection · turbine-trip · ht-pump-trip · loss-of-regulation ·
small-loca · large-loca · loss-of-feedwater · loss-of-condenser ·
channel-blockage · feed-bleed-fail · moderator-cooling-loss · clear
3.2 Scenario catalogue
| # | Scenario | Initiating event | First thing the operator sees | Expected actions | Safety system response | Win / fail |
|---|---|---|---|---|---|---|
| 1 | LOR — zone drain | Zone control valve fails, zones draining on a false demand | Zone levels falling on the mimic; power creeping above setpoint; rate meter positive | Recognise LOR; place zones in manual or trip manually before the trip parameter | SDS1 HIGH NEUTRON POWER (or HIGH LOG RATE) at ~2 min if nothing is done | Win: manual action before SDS; Fail: SDS trip |
| 2 | LOR — DCC failure | DCC X fails; transfer to Y fails | DCC FAILURE window; RRS DEVICES not responding; setpoint frozen | Manual control of zones; manual trip if power diverges; call maintenance | Stepback on loss of both DCCs; SDS as backup | Win: stable at manual hold; Fail: unplanned trip |
| 3 | LOR — false low power signal | RRS power measurement drifts low | Zones draining, adjusters starting out, thermal power rising while neutron power reads normal | Cross-check against thermal power and other channels; put RRS on the good signal; trip if needed | SDS on independent detectors trips on real high power | Win: diagnose from the ΔT × flow disagreement |
| 4 | Small feeder break | Small LOCA inside containment | HT PRESSURE LOW, pressuriser level falling, D2O collection sump alarms, RB pressure rising slowly | Confirm feed & bleed maxing out; crash cool if pressure keeps falling; ECC conditioning | ECC on low HT pressure with conditioning after ~30 s; containment button-up on RB pressure | Win: ECC injects, inventory recovered; Fail: fuel damage flag |
| 5 | Large RIH break | Large LOCA | Alarm flood; HT pressure collapsing; power rising on void before trip | Verify SDS trip, verify ECC stages, verify loop isolation and crash cool, confirm containment | SDS1 and SDS2 (void-driven overpower and low pressure); ECC high-pressure stage within seconds; PRVs to vacuum building; dousing | Win: all SSS confirmed; Fail: any missed manual backup |
| 6 | Pressure tube rupture into calandria | Pressure tube and calandria tube fail | Annulus gas dew point alarm hours earlier (latent); then moderator level high, HT inventory loss | On the dew-point alarm: shut down orderly; on rupture: as small LOCA with moderator system cues | ECC conditioned on high moderator level | Win: orderly shutdown on the leak-before-break cue |
| 7 | SG tube leak | Primary to secondary leak | Tritium in feedwater alarm; slow pressuriser level fall; D2O storage falling | Identify the SG by sampling; reduce power; isolate SG; cool down | None unless the leak grows | Win: isolated within the D2O loss limit |
| 8 | Single-channel flow blockage | Feeder partially blocked | Channel outlet temperature high on one channel; local void; small tilt | Reduce power; confirm with flow verification; shut down if dryout margin is gone | ROP trip if bundle power/flow margin is exceeded | Win: power reduced before fuel damage |
| 9 | Grid load rejection | Loss of line | LOSS OF LINE, generator breaker open, SG pressure up, CSDVs opening, STEPBACK | Confirm CSDVs and house load; hold 60 %; coordinate resynchronisation | Stepback to 60 % | Win: no poison-out; resync |
| 10 | Turbine trip | Turbine protective trip | TURBINE TRIP; setback; CSDVs | Diagnose the turbine cause; hold at poison-prevent; restart turbine if allowed | Setback to 60 % | Win: turbine back on within the window |
| 11 | Loss of Class IV | Grid and generator both lost | Everything on Class IV stops; diesels starting; HT pumps running down | Confirm diesels loaded; confirm thermosyphoning (ROH temperature stable); confirm aux feed; trip verified | SDS on low flow; Class III auto-start; aux feedwater | Win: heat sink maintained on natural circulation |
| 12 | Loss of feedwater | All BFPs trip | SG level falling fast; setback | Start auxiliary feed; trip if levels reach the limit; establish alternate heat sink | SDS on low SG level; aux feed; emergency water supply | Win: SG level recovered before dry-out |
| 13 | Loss of instrument air | Compressor failure, receiver depleting | Air pressure low; valves drifting to failure positions over minutes | Predict which valves fail where; secure the plant before they do | Various; stepback likely | Win: orderly shutdown; Fail: transient trip |
| 14 | Stuck-open ASDV / MSSV | Relief valve fails open | SG pressure falling; steam flow mismatch; noise in the field | Reduce power; isolate if possible; cool-down management | Low SG pressure conditioning of ECC if severe | Win: pressure controlled without a trip |
| 15 | Loss of moderator cooling | Moderator heat exchanger flow lost | Moderator temperature rising ~3 °C/min; positive reactivity from the coefficient | Reduce power; restore cooling; trip before the temperature trip | Setback on high moderator temperature; SDS at 80 °C | Win: cooling restored under the limit |
| 16 | Loss of end-shield cooling | End-shield cooling pump trip | End-shield temperature rising slowly | Restore within the time limit or shut down (thermal stress limit on the end shields) | None | Win: restored or shut down within limit |
| 17 | D2O leak, unlocated | Valve packing leak in a pump room | D2O collection flow, beetle alarms, storage falling, tritium-in-air high | Dispatch FO with moisture meter; locate; isolate; log losses | None | Win: located within the dose and loss budget |
| 18 | Fuelling machine stuck on channel | Ram or latch fault with the channel open | Fuelling machine fault; sequence halted; D2O leakage at the head | Attempt recovery per procedure; secure the channel; if not possible within the window, shut down | None unless the channel loses cooling | Win: channel secured |
| 19 | Xenon oscillation with a failed zone | One zone frozen in manual after a valve fault | Tilt growing over hours; other zones diverging | Identify the failed zone; use adjusters or manual zone bias to damp the oscillation | Setback on flux tilt | Win: tilt damped without setback |
| 20 | ECC accumulator nitrogen leak (latent) | Accumulator pressure slowly falling | Only during the surveillance test or on a LOCA | Find it on the round or the test; declare the safety system impaired; act per the impairment rules | Reduced ECC high-pressure capacity if unfound | Win: found on the round |
| 21 | Containment ventilation damper failure | Damper fails to close on button-up | Containment isolation not complete indication | Manual close from the panel or dispatch FO | Button-up partially effective | Win: isolated within the time limit |
| 22 | Station blackout | Loss of Class IV and all diesels | Only Class I/II alive; no pumps; battery clock | Emergency water supply, EPS, thermosyphoning verification, battery load shedding | SDS tripped; passive systems only | Win: heat sink until Class III is restored; Fail: fuel damage flag |
3.3 Special Safety Systems interaction
The operator's hands are tied by design. The Special Safety Systems act automatically, on their own instrumentation, with their own logic, and cannot be prevented from acting by anything the operator does in the control room. The player's job during an event is verification (did each system do what it should?), backup manual initiation (if a system should have acted and did not), and the Emergency Operating Procedure flow (establish and maintain heat sinks, control inventory, monitor containment). The game makes this explicit: the SSS status panel is the first thing the tutor points to after any trip.
SDS1
| Trip parameter | Representative setpoint | Conditioning |
|---|---|---|
| High neutron power (ROP) | ROP setpoint / CPPF; base ≈ 122 %FP | None; CPPF-adjusted |
| High log rate | 10 %/s | None |
| Low HT flow | 90 % of nominal on any core pass | Conditioned out below ~2 %FP |
| Low ROH pressure | 8.6 MPa | Conditioned out at low power |
| High ROH pressure | 10.45 MPa | None |
| Low SG level | 25 % of span | Conditioned out at low power |
| Low pressuriser level | 10 % | Conditioned by power |
| High reactor building pressure | 3.5 kPa(g) | None |
| High moderator temperature | 80 °C | None |
| Low core differential pressure | Plant-specific | Conditioned by power |
| Manual | Two guarded pushbuttons | None |
Logic is two-out-of-three on channels D, E and F for each parameter; a single failed channel trips its own channel (fail-safe) and annunciates but does not trip the reactor. Rod drop is spring-assisted gravity, complete within two seconds. Reset requires all rods fully inserted and no trip parameter present; withdrawal is by motor in two banks of roughly half the rods, about three minutes each, and the player can hold at any time. In the reference model the reset guard and banked withdrawal are implemented in SafetySystems.resetSds1() and SafetySystems.step().
SDS2
Channels G, H and J, two-out-of-three, on a parameter set that overlaps SDS1 but with independent sensors, cabling and logic. Actuation opens fast-acting valves and helium pressure drives gadolinium nitrate solution through nozzles into the moderator within about a second; the worth is about −300 mk. Recovery is slow: the gadolinium is removed by the moderator ion-exchange columns over hours, which is why an SDS2 actuation is a guaranteed poison-out and a multi-day event. The game models the clean-up as a rate, and the operator initiates it from the moderator panel.
ECCS
| Stage | Source | Trigger / duration in the model | What the operator verifies or does |
|---|---|---|---|
| Signal | — | ROH pressure below 5.5 MPa, conditioned on high RB pressure, high moderator level, or 30 s sustained low pressure | Confirms the LOCA signal on the SSS status panel; if conditions are met and no signal, manual initiation |
| Loop isolation and crash cool | — | Immediately on the signal (CANDU 6 profile); MSSVs open to depressurise the SGs and thus the HTS | Confirms MSSVs open and the intact loop isolated |
| High pressure | Gas-pressurised water tanks (or high-pressure pumps in some designs) | Within seconds of the signal; ~2 minutes of injection in the model | Confirms injection valves open and flow present |
| Medium pressure | Dousing tank / reserve water via pumps | After the high-pressure stage; ~8 minutes | Confirms pump start and valve line-up |
| Recovery (recirculation) | Reactor building sump through heat exchangers | After ~10 minutes; indefinitely | Confirms sump level, pump start, heat exchanger cooling water; manages long-term cooling |
Containment
Button-up closes ventilation dampers and isolates penetrations on high RB pressure or high activity. In the Bruce-class profile the reactor buildings connect by a pressure relief duct to a vacuum building held well below atmospheric pressure; pressure relief valves open at about +7 kPa(g) assumed and the vacuum building absorbs the steam release; dousing sprays in the vacuum building condense steam above about 14 kPa(g). Filtered air discharge manages long-term pressure; hydrogen igniters and recombiners manage the deuterium and hydrogen that a degraded core would release. The reference model implements the pressure, PRV and dousing thresholds in SafetySystems.step(); the CANDU 6 profile replaces the vacuum building with in-building dousing.
Emergency heat sinks
The EOP flow the game teaches is the heat-sink hierarchy: steam generators with main feed, then auxiliary feed, then the emergency water supply; shutdown cooling once the HTS is depressurised; the moderator as a heat sink if the fuel channels lose cooling entirely; and ECC recirculation for a LOCA. The player's decisions are about which is available, which to establish next, and in what order to line up valves — which is also what sends the field operator into the plant.
3.4 Severe-accident boundary
The model stops at the point where a fuel channel fails. If a channel is predicted to lose cooling (dryout margin exhausted and no ECC), the channel is flagged as damaged, activity is released into the HTS and then containment, and the moderator becomes the heat sink for that channel. The game does not model core disassembly, calandria failure, or anything beyond a core damage state flag with its radiological consequence modelled as containment activity and a filtered release. The reasons are practical and principled: severe-accident phenomenology is not operator-facing in the sense this game cares about; it would require a different class of model; and the events that matter to an operator — everything up to and including the last heat sink — are already the hard part. A scenario that reaches the core damage state ends with a debrief, not a spectacle. design decision
Part 4 — Technical architecture
Interface contract
Unit.advance(wallDt: seconds) // advances simulation by wallDt × timeScale
Unit.snapshot(): Readonly<State> // immutable copy for HMI/3D; never a live reference
Unit.command(op, args, actor): Result // e.g. ("rrs.setTarget", {fraction:0.6, rate:0.002}, "CRO")
// validated: permission (role, key, guard), interlocks,
// two-hand actions (requires two concurrent holds)
Unit.inject(faultId | Fault) // fault engine entry point
Unit.on(event, handler) // "alarm", "trip", "sss", "violation", "milestone"
Unit.serialize() / Unit.restore(blob) // state vector + seed + event log
Performance budget
| Item | Budget | Measured in the reference core |
|---|---|---|
| Kinetics + controls + plant at ×1 | < 0.5 ms per simulated second | ~0.02 ms per 20 ms substep (14×14 solve dominates); 50 substeps/s ≈ 1 ms |
| Time acceleration ×600 | < 8 ms per frame | 2 s substeps when quiet: 300 substeps per wall-second ≈ 6 ms |
| Validation suite (all scenarios, ~30 h simulated) | < 10 s | 2.0 s |
| Tier-2 diffusion (optional) | Asynchronous, < 200 ms per solve every 120 simulated seconds | Not built |
Multiplayer
design decision Co-op with one authoritative simulation host (the CRO's machine or a dedicated server) and clients that receive snapshots at 10 Hz plus event deltas. The field operator client renders the plant areas and posts field commands; the SS client renders approvals and the log. Latency is not critical: nothing in the plant needs sub-second reaction, and the physics is deterministic, so clients can interpolate.
Test strategy
Golden-run regression: each validation scenario is run from a fixed seed and its state vector compared at checkpoints against a stored baseline with tolerances. The current baselines, all produced by the reference core in this session:
| Scenario | Checkpoint | Baseline |
|---|---|---|
| Steady state, 10 min | Power, zone average, MW | 100.00 %FP, 50.0 %, 915 MW; log rate 0.00 %/s |
| +1 mk ramp over 100 s | Peak power; final devices | 100.1 %FP; zones ~64 %, no coarse device motion, no trip |
| Refuelled channel, zone 4 (+0.3 mk) | Max tilt; zone 4 level | 1.0 %; 100 % |
| Same, spatial control off, 20 h | Max tilt | 16 % at 20 h and still growing (divergent xenon oscillation) |
| Loss of regulation (zone drain) | Trip time and parameter | ~1.9 min, HIGH NEUTRON POWER |
| Load rejection | Stepback endpoint, undershoot, recovery | 60 %; MCA drop to 56 % then re-clutch (26 % in); holding 60 % from 3 min; MCAs withdraw to 6 % in by 19 min as xenon builds |
| Large LOCA | RB pressure, ECC stage | PRVs at +7 kPa(g); ECC high-pressure at 3.5 min; inventory recovered |
| Trip, xenon | Peak load, time | −125 mk at 10.3 h; −40 mk at 30 min |
| Poison override, rods out with one hold | Trip? | No trip; RRS holds 10⁻⁴ FP on zones |
| Late restart at 90 min | Reactivity margin | −5 mk with adjusters out and zones empty: poisoned out |
Roadmap
| Milestone | Deliverable | Status |
|---|---|---|
| M0 | Reference physics core in JS with validation suite; this document; art-direction selection | Complete |
| M1 | 2D panel game: full RRS/HTS/SSS panel, annunciators, mimics, trends, procedures sidebar, tutorial campaign, six scenarios | Next |
| M2 | 3D main control room with the chosen art direction; panel objects; DCC CRTs; alarm audio | — |
| M3 | Field operator: plant areas, rounds, sampling, local operations, dose | — |
| M4 | Fault engine, full scenario catalogue, scenario director mode, career evaluation | — |
| M5 | Co-op multiplayer (CRO, FO, SS); Tier-2 diffusion for flux mapping | — |