Physics-informed GNN · Module 5
GNN Preliminary · Graphs and Message Passing
In AI Preliminary, an MLP learned a function from examples. A microgrid adds relationships: a bus connects to particular buses through lines with particular impedances. This chapter makes those relationships part of the computation, then trains a small graph neural network (GNN) on a transparent voltage-learning task.
1. A graph describes who connects to whom
Prerequisites: vectors, a weighted sum, tanh, MSE, and gradient descent from the previous chapter. Power-flow familiarity helps interpret the example, but the message calculation itself needs no power-flow solver.
Nodes represent entities; edges represent relationships. Here a node is an electrical bus and an edge is a physical line or tie. In other problems, nodes could be molecules’ atoms or people, with entirely different features. Bus numbers identify rows; they are not numerical measurements or spatial coordinates.
An ordinary dense MLP can take a flattened vector of bus data, but that requires a fixed convention for ordering and representing connectivity. A message-passing GNN uses the neighborhood explicitly and reuses the same local rule at each bus. This is a structural choice, not a guarantee that every GNN outperforms an MLP.
Undirected electrical connections, directed computational messages
A series line connects two buses without prescribing the actual power-flow direction. We model it as one undirected physical edge. To exchange information both ways, create two computational arcs, j → i and i → j. A radial five-bus network has four active physical lines and eight such arcs. These arrows describe data movement, not the sign of current or real power.
The binary adjacency A records active neighbors: Aᵢⱼ = 1 for a connected pair, otherwise 0. It differs from Ybus: A is a connectivity table; Ybus is a complex-valued physical network operator. In this example A has no self-loops; a separate self term retains each bus’s own state.
2. Attach features to buses and lines
Introduce the five-bus teaching microgrid before assigning numbers to its features. Bus 1 is the only external reference; bus 2 is a junction with load; buses 3 and 5 have loads; bus 4 has load plus a photovoltaic inverter. Active lines are 1–2, 2–3, 2–4, and 4–5. A normally open 3–5 tie can add an alternate route.
Physical assumptions and input convention
- Balanced three-phase steady state, series lines, and specified net constant-PQ devices.
- Three-phase base 1 MVA; line-to-line voltage base 0.4 kV. Per-unit impedances use Zbase = 0.16 Ω.
- Positive node P and Q denote net consumption, load minus generation. The fixed-PQ solar inverter supplies active power with Q = 0; it does not regulate voltage or sustain a disconnected island.
- Bus 1 has known reference voltage 1∠0 pu. Its input P = Q = 0 is a placeholder, not its solved supply; a reference flag distinguishes it.
| Bus | Load P / Q at multiplier 1 | Generation | Net P / Q at defaults |
|---|---|---|---|
| 1 | Reference bus | External source | Input placeholders 0 / 0 |
| 2 | 80 kW / 30 kvar | None | 80 kW / 30 kvar |
| 3 | 100 kW / 40 kvar | None | 100 kW / 40 kvar |
| 4 | 60 kW / 25 kvar | 50 kW solar | 10 kW / 25 kvar |
| 5 | 100 kW / 40 kvar | None | 100 kW / 40 kvar |
The multiplier scales all demand, including the bus-5 base-load slider; solar remains an independent setting. Bus 5 uses Q/P = 0.4 for its demand. The graph-data panel shows the resulting physical quantities and normalized inputs.
Node matrix X
For bus 2, 80 kW = 0.08 pu and 30 kvar = 0.03 pu, so x₂ = [0.4, 0.3, 0]. The normalization constants are fixed teaching scales, not fitted using validation labels. Solved voltages are targets, not input features. Node IDs and drawing coordinates are also excluded from X.
Edge table and sparse indices
| Line | r (pu) | x (pu) | Default status |
|---|---|---|---|
| 1–2 | 0.040 | 0.025 | Closed |
| 2–3 | 0.060 | 0.035 | Closed |
| 2–4 | 0.050 | 0.030 | Closed |
| 4–5 | 0.055 | 0.035 | Closed |
| 3–5 | 0.080 | 0.050 | Open tie |
Each physical row stores [r, x, status]. The impedance multiplier scales r and x. An open line remains in this equipment table but creates no arcs in the message graph. For each closed line we attach the same reciprocal series attributes to both computational directions.
edge_index has shape [2, number of arcs]: row 1 contains senders, row 2 receivers. Python/PyG-style indices start at zero, so physical bus 1 is array index 0. For line 1–2 alone:
edge_index = [[0, 1], # senders: bus 1, bus 2
[1, 0]] # receivers: bus 2, bus 1
3. Message → aggregate → update
A message-passing layer first constructs one message per active directed arc, then combines incoming messages with an order-independent operator, and finally updates the destination state. This structure is described in the MPNN paper and the official PyG message-passing tutorial.
φ and ψ can be MLPs, and hidden dimensions can change across layers. Sum preserves information about the number of contributions; mean divides by the active incoming degree. Both ignore the order in which neighbors are listed. Neither is universally preferable. In our example an empty neighborhood aggregates to zero.
One layer is one hop, not one training epoch
Every destination reads the previous layer. Updating buses in place would let later buses read already-updated values and destroy the intended synchronous computation. One local layer can depend on one-hop neighbors; K layers can depend on nodes at most K hops away, assuming only local message passing. A graph-level pooling operation introduces a different dependency and is not used inside this example’s local layers.
The same parameters act at every bus and arc. Relabeling all nodes consistently reorders node outputs in the same way: permutation equivariance. A symmetric graph readout, such as a mean of node embeddings, is permutation invariant. An arbitrary edge-dependent network is not guaranteed to have these properties unless its inputs and parameter sharing respect the relabeling.
4. Work through one actual layer
To keep every multiplication inspectable, use a small edge-weighted MPNN with three hidden channels:
r and x are numerical pu values, so aₑ is dimensionless. This gate is a chosen feature transformation, not an electrical admittance or power-transfer law. Disabling it sets every active gate to 1 and removes impedance information from messages. α retains the old self state, β weights neighbors, and γ adds a skip from the original input. The tanh acts elementwise.
For this teaching model, α, β, and γ are scalar coefficients shared across channels, buses, and layers. A more general GNN can use matrices or MLPs with different parameters per layer. The shared update here keeps the model small enough to derive and train entirely in readable code.
At the default manual weights α = 0.5, β = 0.6, γ = 0.4, bus 2 receives the following first-layer messages:
| Arc | Gate | Sender h⁽⁰⁾ | Message aₑh⁽⁰⁾ |
|---|---|---|---|
| 1 → 2 | 0.514563 | [0, 0, 1] | [0, 0, 0.514563] |
| 3 → 2 | 0.418542 | [0.5, 0.4, 0] | [0.209271, 0.167417, 0] |
| 4 → 2 | 0.461640 | [0.05, 0.25, 0] | [0.023082, 0.115410, 0] |
The mean aggregate is [0.077451, 0.094276, 0.171521]. With h₂⁽⁰⁾ = x₂ = [0.4, 0.3, 0], the new representation is:
The third channel becomes nonzero because a reference-marked neighbor sent information. After this transformation, channels are latent features, not P, Q, and voltage. Keeping the width at three does not preserve the original physical meanings.
5. Explore the microgrid graph
Start with bus 2 at layer 1 and compare its incoming-message table with the worked example. Next inspect bus 1 while changing bus-5 demand: the baseline path is 5–4–2–1, so its embedding cannot change at bus 1 before layer 3. The source voltage readout is fixed separately; use the embedding plot for this locality experiment.
Five-bus microgrid · graph and message lab
Change settings, select buses, inspect layersManual mode adjusts three shared coefficients with the initial readout. Learned mode uses all seven parameters from the training panel below and disables manual sliders.
Layer 0 is the normalized input. Layer ℓ has completed ℓ synchronous updates; it does not mean ℓ training epochs.
Current node representations
Selected bus update
Individual incoming messages
| Direction | aₑ | m₁ | m₂ | m₃ |
|---|
Inspect current graph data: X, edge features, adjacency, and edge_index
| Bus | P (pu) | Q (pu) | ref | X₁ | X₂ | X₃ |
|---|
| Line | r (pu) | x (pu) | status | aₑ |
|---|
| Bus | 1 | 2 | 3 | 4 | 5 |
|---|
edge_index · zero-based indices
Row 1 contains senders; row 2 contains receivers. Index 0 corresponds to physical bus 1.
Then close the 3–5 tie, or open 2–4. Re-examine the neighbor set and receptive field. A line status must change the computation graph; keeping the old adjacency and merely setting a label to “open” would allow messages to cross a nonexistent connection. If a bus loses its only source, graph operations still return numbers; those numbers do not establish a supplied electrical operating point.
6. Add a readout and learn its parameters
The message layers produce embeddings. A shared node readout maps the last embedding to a scaled voltage drop:
This model has seven trainable scalars: α, β, γ, w₁, w₂, w₃, b. Training backpropagates through the readout and every message layer, accumulating contributions for parameters reused across layers and nodes. It is not just fitting a readout on frozen embeddings.
Where do the voltage labels come from?
To focus on GNN mechanics, generate labels with a small linearized balanced-voltage model, rather than running a hidden AC solver. Let V = 1 + ΔV, set the reference ΔV₁ = 0, use series-line Ybus, and omit second-order power terms. With positive net consumption Sload = P + jQ:
The sign follows load current entering the devices rather than net injection into the network. Build YLL from the active graph and solve its real block system for ΔV. The baseline reference magnitudes are [1, 0.985025, 0.977625, 0.977575, 0.970675] pu. Losses and nonlinear voltage terms are omitted. These targets are an educational approximation, not a full AC or unbalanced power-flow solution.
Generate 32 radial training cases and 16 separate radial validation cases using fixed seeds. Load multiplier spans 0.6–1.4, bus-5 base demand 60–160 kW, bus-4 solar 0–100 kW, and line-impedance multiplier 0.8–1.2. Both sets retain the default radial topology. The label generator is excluded from the GNN inputs; it is used only to form targets and evaluate predictions.
One full-batch update is one training epoch. It changes θ; it does not change the number of message layers K. A forward pass with frozen θ on a new operating case is inference.
Train a small GNN, then change the operating case
Train on 32 generated radial cases and validate on 16 other radial cases. These datasets are independent of the operating sliders above. Layers, aggregation, and impedance gating select the model. Training updates all of α, β, γ, w₁, w₂, w₃, and b.
Not trained yet; the lab currently uses manual weights.
Current case: linear reference and GNN readout
Training and validation loss (log₁₀ MSE)
| Bus | Linear reference pu | GNN readout pu | |error| pu |
|---|
Inspect all active model weights
Bus 1 is fixed at 1 pu and excluded from loss/MAE. Training MSE uses voltage drops divided by 0.05 pu; MAE uses actual pu errors. Topology changes are outside this training distribution and demonstrate inference, not validated N-1 generalization.
Train once, then change the physical sliders while retaining learned weights. Changes to K, aggregation, or impedance gating define a different model configuration and invalidate the previous fit. The default validation MAE drops from about 0.01534 to 0.00527 pu after 400 epochs; this describes this seeded linear-reference experiment only. A held-out topology or nonlinear AC evaluation requires a new validation design.
What remains before N-1 security prediction?
A complete security task needs an explicit definition of supplied operation and voltage/current limits, accurate labels, appropriate scenario/contingency splits, and evaluation of errors near limits. Closing ties or tripping lines here demonstrates how the graph and outputs change; those topologies were not included in this training distribution. A GNN can be equivariant and still be inaccurate. It also does not automatically satisfy Kirchhoff’s laws. Later physics-informed training can add specified AC residuals and constraints after their variables and units are defined.
7. Inspect and edit the Python experiment
The browser lab and Python download implement the same graph, equations, seeded cases, gradients, and training loop. Expand the source before editing dependencies, or start by changing one parameter in the annotated main program. The panel plots embeddings so the same computation remains inspectable even when the physical reference is unavailable.
1 · case: operating settings, model configuration, and weights
case copies the controls and active θ. The inspected bus and replay layer are display choices, not model parameters. Python performs a complete forward pass by default; commented lines show how to train separately.
2 · Expand model.py: graph building, messages, reference, and full backpropagation
Only the standard-library math module is required. build_graph() creates X and lines; arcs() creates directed computational edges; forward() runs synchronous layers; reference() solves the linear voltage model; solve() organizes the current experiment; loss_gradient() and train_model() train every parameter. There is no hidden PyG model or remote API.
3 · main(): copy → run → inspect → return
main calls solve(parameters), prints graph dimensions, final node embeddings, and reference status. result = main() sends the return value to the feature plot. Code edits affect only this Python experiment.
The first run downloads Pyodide. Computation runs in a separate stoppable browser worker with no third-party Python dependencies. Source edits do not change the JavaScript lab; download edits before reloading.
Ready to run.
Final node embeddings returned by Python (not voltage)
Try parameters["open23"] = True; verify that both directions of the 2–3 arc disappear. Or override theta with a copy whose β = 0 to remove neighbor dependence. The Notebook below includes a node-permutation check, a locality experiment, and a finite-difference check of all seven gradients.
8. Practice: trace information before interpreting predictions
- Write X and the two arcs for a two-bus network with one line. Explain how these differ from Ybus and from solved voltages.
- Reproduce the first component of h₂⁽¹⁾ in the worked example. Change mean to sum and explain the degree factor.
- Inspect bus 1 while changing bus-5 load at layers 0, 1, 2, and 3. Repeat after changing topology. Explain the difference between a possible dependency and a guaranteed numerical effect.
- Set β = 0, then disable impedance gating. Which information paths have you removed in each case?
- Relabel buses and permute X, edge endpoints, reference flags, and outputs consistently. Why should the predicted physical quantities follow the same permutation?
- Trip 2–4 with the tie open, then close 3–5. Explain why a finite embedding is not evidence of supplied operation.
- Train the model. Distinguish the roles of 400 epochs, K = 3, 32 training graphs, 16 validation graphs, and seven parameters. Propose an evaluation split for unseen contingencies.
Checkpoint and next-step ideas
A graph supplies connectivity; features supply observations; shared message/update functions build embeddings; a readout supplies task-specific outputs. Training learns parameter values from labeled examples. Synchronous layers establish local receptive fields; permutation symmetry concerns consistent relabeling, not arbitrary changes to topology. More layers can bring more context, but can also make optimization or representation quality worse; depth is not an automatic improvement.
A larger model could replace the scalar update with MLPs, add generator/device features, predict phase-resolved voltages and branch quantities, and compare MLP and GNN baselines under controlled topology splits. Keep measurements, specified quantities, and prediction targets distinct to avoid label leakage.
9. Download and continue reading
Next: Physics-informed GNN · Microgrid N-1 Security, combining full AC residuals with learning and contingency screening.
- Self-contained GNN Notebook — complete source, plots, training, locality, permutation, and gradient checks. The model needs only the standard library; figures use Matplotlib.
- Complete Python model — the same source as the expandable editor; download a snapshot from the panel to include current inputs and main.
- Gilmer et al.: Message Passing Neural Networks and PyG: Creating Message Passing Networks — original framework and implementation conventions.
- Distill: A Gentle Introduction to GNNs — visual explanations of graph representations, message passing, and output choices.