Contingency analysis
Six CLI verbs answer "what happens if something fails or the load grows":
trip (lose a generator), screen (rank every credible single loss),
nminus1 (outage every branch), nminus1-sweep (the same, parallel and at
scale), stress (load-to-collapse), and chain (consecutive warm-started
solves). The GUI adds a right-click trip on the network map.
Run every verb through the CLI project:
dotnet run --project src/GridSim.Cli <verb> [flags]
A flag with an unparseable value fails loudly with exit code 2 - it is never silently replaced by the default.
trip - lose one generator
dotnet run --project src/GridSim.Cli trip [<gen>] [--dir <case-dir>] [--export <csv>]
| Flag | Default | Meaning |
|---|---|---|
<gen> |
largest non-slack unit with H > 0 | substring match on the generator name (case-insensitive) |
--dir |
data/uk |
JSON case directory to trip on |
--export |
off | write the frequency trajectory to a CSV (dtm,f columns) |
The verb removes the unit's output and its spinning inertia, integrates the swing response, and prints: the tripped unit and MW lost, system inertia before -> after, initial RoCoF, nadir (with time), settling frequency, an ASCII sparkline of the trajectory, and - for context - the same trip at half the remaining inertia.
A name that matches no generator exits 2 and lists what is available; it never
falls back to a different unit. An exported trajectory can be played back in
the console: dotnet run --project src/GridSim.Cli replay <csv>.
trip is the one dynamics verb that honours --inertia-model distributed
(full multi-domain integration, reporting the centre-of-inertia response).
screen - rank credible single losses
dotnet run --project src/GridSim.Cli screen [--dir <case-dir>] [--top 12] [--csv <path>]
| Flag | Default | Meaning |
|---|---|---|
--dir |
data/uk |
case directory |
--top |
12 | rows printed (all losses are still screened and counted) |
--csv |
off | write every result to a CSV |
For each credible single loss the table shows MW lost, remaining inertia,
initial RoCoF, nadir, and a verdict: ok, >0.125 Hz/s (RoCoF breach),
<49.5 Hz (statutory breach) or LFDD RISK. The footer gives the breach
count, the worst RoCoF, and for the binding case the minimum spinning inertia
needed to hold 0.125 Hz/s, with the current headroom against it.
nminus1 - branch outage screening
dotnet run --project src/GridSim.Cli nminus1 [--dir <case-dir>]
(n-1 is accepted as an alias; default case directory data/uk.)
Each branch is removed in turn and the case re-solved. Per outage the table
reports Status, max branch loading, worst boundary loading, and the voltage
range. Read the status column as:
- secure - converged with no violations.
- VIOLATIONxN - converged, but N limit violations. A violation is one of:
a branch loaded above 100 % of its rating (
branch <name> <pct>%), a boundary above its limit (boundary <name> <pct>%), any bus below 0.94 pu (undervoltage) or above 1.06 pu (overvoltage). - ISLANDED - the power flow could not converge, typically because the outaged element was the only feed to some load.
The footer totals outages screened, secure, with violations, and islanded.
nminus1-sweep - the full sweep, in parallel
dotnet run --project src/GridSim.Cli nminus1-sweep <case|--all> [--parallel N] [--sample N] [--out <path>]
| Flag | Default | Meaning |
|---|---|---|
<case> |
case118 |
a built-in case name or a .m file; --all sweeps the whole case registry |
--parallel |
logical CPU count | worker threads |
--sample |
full sweep | screen only N evenly spaced branches (logged, never silent) |
--out |
results/nminus1-sweep.md (under the current directory) |
markdown report path; a .csv sibling and run-metadata.json land beside it |
Output is one summary row per case: buses, branches, outages screened,
secure / violations / islanded counts, solves per second and wall time.
Sampled cases are marked (sampled). Use nminus1 on a single case when you
want the per-outage detail; use the sweep for coverage and throughput.
Continuous N-1 in the cycle engine
Beyond these one-shot verbs, N-1 also runs continuously inside the real-time
cycle engine - the CYCLE tab, and the gridsim cycle verb (see
19-cli-reference.md). Each cycle re-screens the hot
branch set as High-priority work every cycle, while the remaining branches
rotate through Low-priority shards that reach full coverage over several
cycles. The ContingencyAnalysis.ScreenBranchesParallel primitive these verbs
share gained an optional CancellationToken (wired onto its ParallelOptions)
so a deferred shard aborts cleanly between outages when a cycle hits its
deadline; the default token is a no-op, so the standalone verbs above are
unchanged.
stress - load-to-collapse
dotnet run --project src/GridSim.Cli stress <case|--all> [--from 0.5] [--to 2.0] [--step 0.05] [--parallel N] [--out <path>]
| Flag | Default | Meaning |
|---|---|---|
<case> |
case118 |
case name or .m file; --all for the registry |
--from / --to / --step |
0.5 / 2.0 / 0.05 | load-factor sweep (x base load); --step must be positive (exit 2 otherwise) |
--parallel |
logical CPU count | load points solved concurrently |
--out |
results/stress.md |
report path (.csv sibling, run-metadata.json) |
Every load point is solved independently; max loadability is the highest
factor that still converges before the first non-convergence, reported with
the minimum voltage at that point. A case that converges across the whole
range is noted "did not collapse in range" - widen --to if you need the
actual limit.
chain - consecutive warm-started solves
dotnet run --project src/GridSim.Cli chain <case> [--steps 50] [--mode fixed|ramp|daily] [--ramp-pct 0.5] [--out <path>]
| Flag | Default | Meaning |
|---|---|---|
<case> |
case118 |
case name or .m file |
--steps |
50 | number of consecutive solves |
--mode |
fixed |
fixed = same point re-solved; ramp = +--ramp-pct % load per step; daily = a 24 h demand curve |
--ramp-pct |
0.5 | per-step load growth for ramp mode |
--out |
results/chain-<case>.md |
report path (.csv sibling) |
Each step feeds the previous solved voltages in as the initial condition. The
report gives per-step iterations, mismatch and voltage range, plus the cold
(flat-start) iteration count for comparison. In fixed mode expect warm-start
iterations to drop to <= 1 with no drift - if they do not, something is wrong
with the case or the build.
The GUI right-click trip
On the NETWORK map, right-click behaviour depends on the mode:
- Live sim (and local replay): right-click a bus to trip the largest generator dispatched at that bus. The loss is injected into the live frequency integrator, the event is logged with its headline RoCoF and nadir, an alarm is raised, and the GENERATION & INERTIA tab's trace plot and read-outs update with the with/without-device comparison. A bus with no generation logs "No generation to trip" and does nothing.
- Bridge mode: right-click opens a context menu of on-demand GDA physics queries - on a bus, "Feasibility: +500 MW here" and "Scenario: trip nearest generator" (the largest unit on that bus, else the largest in the model); on a branch, "Scenario: trip this". The returned solve renders as a what-if overlay on the map (live frames held off), and the results panel shows the verdict, the binding constraint, and each violation as kind / element / value-vs-limit / message. Pick Return to live stream (in the same menu, or the toolbar button) to drop the overlay and resume the stream.
See frequency studies for watching the transient a trip produces at a fine time-step.
Note on default output locations
nminus1-sweep, stress and chain write under results/ in your current
working directory. trip, screen and nminus1 print to the console (plus
whatever --csv/--export path you give). Pass --out/--csv explicitly
when you want the artefacts somewhere specific.
See also
- Running power flows - solver selection and the
--gpu/--bfsswitches these verbs inherit - Frequency studies -
freq,transient, and the live GUI frequency sim - Loading networks - case names and directories accepted by
<case>/--dir - CLI reference - every verb and flag in one table