In this page
GreyCat Powergrid Library
@library("powergrid", "0.0.0");
Power flow analysis for electrical networks:
PowerNetwork: AC load flow (Newton-Raphson) and short circuit, computing voltages, currents, power flows and losses.DcNetwork: DC load flow, PTDF / LODF sensitivities and fast N-1 security screening, for planning studies that evaluate many topologies or many contingencies.
Quick Start
// Define a simple 3-bus network: external grid → line → load
var network = PowerNetwork {};
network.configure(3, 2, 1, 1); // 3 buses, 2 lines, 1 ext grid, 1 load
// Create buses at 20 kV
network.createBus(0, 20.0);
network.createBus(1, 20.0);
network.createBus(2, 20.0);
// External grid (slack bus) at bus 0, voltage = 1.0 p.u.
network.createExtGrid(0, 1.0);
// Transmission lines
network.createLine(0, 0, 1, 10.0, 0.1, 0.4, 9.7, 0.5); // bus 0 → bus 1, 10 km
network.createLine(1, 1, 2, 5.0, 0.1, 0.4, 9.7, 0.5); // bus 1 → bus 2, 5 km
// Load at bus 2: 2 MW active, 0.5 MVar reactive
network.createLoad(2, 2.0, 0.5);
// Solve power flow
network.compute();
// Read results
var busResult = network.getBusResult(2);
info("Bus 2 voltage: ${busResult.abs} p.u., angle: ${busResult.angle_radians} rad");
var lineResult = network.getLineResult(0);
info("Line 0: ${lineResult.p_from_mw} MW, losses: ${lineResult.pl_mw} MW, loading: ${lineResult.loading_percent}%");
Workflow
- Configure — declare network dimensions with
configure() - Build topology — create buses, lines, loads, and external grids
- Solve — run Newton-Raphson power flow with
compute() - Read results — query bus and line results
API Reference
PowerNetwork
Electrical network model and power flow solver.
Constructor:
| Field | Type | Description |
|---|---|---|
tolerance |
float? |
Convergence tolerance for Newton-Raphson solver |
max_iteration |
int? |
Maximum solver iterations |
Methods:
| Method | Returns | Description |
|---|---|---|
configure(nb_bus, nb_lines, nb_ext_grids, nb_loads) |
void |
Set network dimensions. Must be called first. |
createBus(bus_id, vn_kv) |
void |
Create a bus at given nominal voltage (kV) |
createLine(line_id, from, to, length_km, r, x, c, max_i_ka) |
void |
Create a transmission line between two buses |
createLoad(bus_id, p_mw, q_mvar) |
void |
Create a load at a bus |
createExtGrid(bus_id, vm_pu) |
void |
Create an external grid (slack bus) with fixed voltage |
compute() |
void |
Run Newton-Raphson power flow analysis |
getBusResult(bus_id) |
PowerBusResult |
Get voltage/current results for a bus |
getLineResult(line_id) |
PowerLineResult |
Get power flow results for a line |
getCheckSum() |
Array<float> |
Get solver convergence metrics |
createLine Parameters
| Parameter | Unit | Description |
|---|---|---|
line_id |
— | Unique line identifier (0 to nb_lines-1) |
from_bus_id |
— | Starting bus ID |
to_bus_id |
— | Ending bus ID |
lenght_km |
km | Line length |
r_ohm_per_km |
Ω/km | Resistance per kilometer |
x_ohm_per_km |
Ω/km | Reactance per kilometer |
c_n_f_per_km |
nF/km | Capacitance per kilometer |
max_i_ka |
kA | Maximum current rating |
PowerBusResult
Results for a single bus after power flow computation.
| Field | Type | Unit | Description |
|---|---|---|---|
abs |
float |
p.u. | Voltage magnitude |
angle_radians |
float |
rad | Voltage phase angle |
voltage |
float |
— | Real component of voltage |
voltage_img |
float |
— | Imaginary component of voltage |
current |
float |
— | Real component of current |
current_img |
float |
— | Imaginary component of current |
PowerLineResult
Results for a transmission line after power flow computation.
| Field | Type | Unit | Description |
|---|---|---|---|
p_from_mw |
float |
MW | Active power at “from” bus |
q_from_mvar |
float |
MVar | Reactive power at “from” bus |
p_to_mw |
float |
MW | Active power at “to” bus |
q_to_mvar |
float |
MVar | Reactive power at “to” bus |
pl_mw |
float |
MW | Active power losses |
ql_mvar |
float |
MVar | Reactive power consumption |
i_from_ka |
float |
kA | Current at “from” bus |
i_to_ka |
float |
kA | Current at “to” bus |
i_ka |
float |
kA | Maximum current (max of from/to) |
vm_from_pu |
float |
p.u. | Voltage magnitude at “from” bus |
vm_to_pu |
float |
p.u. | Voltage magnitude at “to” bus |
va_from_radians |
float |
rad | Voltage angle at “from” bus |
va_to_radians |
float |
rad | Voltage angle at “to” bus |
loading_percent |
float |
% | Line loading percentage |
Example — Analyzing Line Loading
var network = PowerNetwork { tolerance: 1e-8, max_iteration: 50 };
network.configure(2, 1, 1, 1);
network.createBus(0, 110.0); // 110 kV bus
network.createBus(1, 110.0);
network.createExtGrid(0, 1.0);
network.createLine(0, 0, 1, 20.0, 0.05, 0.3, 11.0, 0.6);
network.createLoad(1, 10.0, 3.0); // 10 MW, 3 MVar
network.compute();
var line = network.getLineResult(0);
info("Power flow: ${line.p_from_mw} MW → ${line.p_to_mw} MW");
info("Losses: ${line.pl_mw} MW + ${line.ql_mvar} MVar");
info("Current: ${line.i_ka} kA");
info("Loading: ${line.loading_percent}%");
if (line.loading_percent > 80.0) {
warn("Line 0 is heavily loaded!");
}
DC load flow — DcNetwork
The DC approximation keeps only active power: |V| = 1 p.u., r ≪ x and small angle differences, so
P = B·θ and the flow of a branch is (θ_from − θ_to) / x. It is linear, lossless and never diverges,
which makes it the standard model for transmission expansion planning and contingency screening.
The susceptance matrix is factorized once (sparse LDLT, AMD ordering). N-1 flows then use line outage
distribution factors (f_l + LODF[l][k]·f_k): one extra solve per outage, no refactorization,
O(branches) memory. Bridges (outages that split the network) are found with Tarjan’s algorithm.
var dc = DcNetwork {};
dc.configure(3, 3, 0); // 3 buses, 3 branches, slack = bus 0
dc.setBranch(0, 0, 1, 0.1); // x in p.u.
dc.setBranch(1, 0, 2, 0.1);
dc.setBranch(2, 1, 2, 0.1);
dc.factorize();
var f = dc.flows([100.0, -50.0, -50.0]); // MW: [50, 50, 0]
// N and N-1 screening over several snapshots
var snapshots = Array<Array<float>> { [100.0, -50.0, -50.0], [60.0, -30.0, -30.0] };
var s = dc.screen(snapshots, [60.0, 60.0, 60.0], true, 10);
info("max N-1 loading ${s.max_loading_n1}, overload ${s.overload_mw} MW, islandings ${s.islanding_cases}");
| Method | Returns | Description |
|---|---|---|
configure(nb_bus, nb_branches, slack_bus_id) |
void |
Set network size and reference bus. Must be called first. |
setBranch(branch_id, from_bus_id, to_bus_id, x_pu) |
void |
Create or replace a branch (x > 0). |
factorize() |
void |
Factorize the susceptance matrix of the part connected to the slack. |
connected() |
Array<bool> |
Whether each bus is connected to the slack. |
bridges() |
Array<bool> |
Whether the outage of each branch splits the network. |
flows(injections) |
Array<float> |
N state branch flows [MW] for net injections per bus [MW]. |
ptdf() |
Array<float> |
Branches × buses PTDF, row-major (dense: small networks). |
lodf() |
Array<float> |
Branches × branches LODF, row-major (dense: small networks). |
screen(injections, ratings, n1, max_violations) |
DcScreening |
N (and N-1) screening of one injection array per snapshot. |
Buses not connected to the slack get a zero angle. In screen, a state that cuts a bus with a non-zero
injection from the slack counts as an islanding (islanding_cases, disconnected_mw) and its flows are not checked.
DcScreening: max_loading_n, max_loading_n1, overload_mw (sum of MW above rating), islanding_cases,
disconnected_mw, and violations (the first max_violations DcViolation { snapshot, outage, branch, loading };
outage = -1 for the N state, branch = -1 for an islanding).