This notebook walks through the core GDM-Flow workflow: loading a distribution system model, running each solver, and comparing results.
Setup¶
Make sure GDM-Flow is installed with optimization support:
pip install -e ".[optimization]"from pathlib import Path
import numpy as np
from gdm.distribution import DistributionSystem
from gdm_flow import (
calculate_ybus,
optimize_ac_power_flow_from_components,
solve_dc_opf_from_components,
solve_lindistflow,
)Load a Distribution System¶
GDM-Flow operates on DistributionSystem objects from grid-data-models. Load one from a JSON file:
model_path = Path("../examples/models/p5r.json")
system = DistributionSystem.from_json(str(model_path))
src = system.get_source_bus()
print(f"Source bus: {src.name}")
print(f"Phases: {[p.value for p in src.phases]}")Step 1: Build the Y-Bus Matrix¶
The Y-bus (admittance matrix) is the foundation for all solvers. It encodes the network topology and impedance in a single matrix.
ybus_result = calculate_ybus(system)
print(f"Y-bus shape: {ybus_result.ybus.shape}")
print(f"Nodes: {len(ybus_result.index_to_label)}")
print("\nFirst 5 node labels:")
for label in ybus_result.index_to_label[:5]:
print(f" {label[0]} | Phase {label[1]}")Step 2: Run the AC OPF¶
The AC OPF solves a nonlinear least-squares problem minimizing power mismatch across all nodes. It produces full complex voltages and power injections.
ac = optimize_ac_power_flow_from_components(
system,
include_loads=True,
include_solar=True,
include_capacitor=True,
)
print(f"Success: {ac.success}")
print(f"Iterations: {ac.iterations}")
print(f"Objective: {ac.final_objective:.6f}")
# Compute source bus injection
v = ac.voltage
ybus = ac.ybus_result.ybus
s = v * np.conj(ybus @ v)
src_idx = [
i for i, lbl in enumerate(ac.ybus_result.index_to_label) if lbl[0] == src.name
]
ac_source_p = sum(s[i].real for i in src_idx)
print(f"\nSource injection: {ac_source_p:.1f} W")Step 3: Run the DC OPF¶
The DC OPF linearizes the power flow equations and solves a quadratic program to minimize generation cost. It automatically creates generators for solar PV and grid import.
dc = solve_dc_opf_from_components(
system,
include_solar_generators=True,
include_battery_generators=True,
include_loads=True,
)
print(f"Success: {dc.success}")
print(f"Iterations: {dc.iterations}")
print(f"Objective: {dc.objective:.4f}")
print("\nGenerator Dispatch:")
for name, mw in sorted(dc.generator_dispatch_w.items()):
print(f" {name:40s} {mw:10.1f} W")Step 4: Run LinDistFlow¶
LinDistFlow is a fast linearized approximation for radial distribution feeders. It performs a backward/forward sweep to compute voltage drops and branch power flows.
ldf = solve_lindistflow(system)
print(f"Success: {ldf.success}")
print(f"Source bus: {ldf.source_bus}")
ldf_source_p = sum(float(v) for v in ldf.p_net_w.values())
print(f"\nSource injection: {ldf_source_p:.1f} W")
print("\nBus Voltages:")
for (bus, phase), v in sorted(ldf.voltage_v.items()):
print(f" {bus:30s} Phase {phase}: {v:.2f} V")Step 5: Compare Results¶
All three solvers should agree on source bus power injection (within a few watts due to AC losses).
# DC source = grid import only (solar injects at load buses)
dc_grid_import = sum(
v for k, v in dc.generator_dispatch_w.items() if k.startswith("grid:")
)
print("=" * 50)
print(f"{'Solver':<15} {'Source P (W)':>15} {'Status':>10}")
print("-" * 50)
print(f"{'AC OPF':<15} {ac_source_p:>15.1f} {'PASS' if ac.success else 'FAIL':>10}")
print(f"{'DC OPF':<15} {dc_grid_import:>15.1f} {'PASS' if dc.success else 'FAIL':>10}")
print(
f"{'LinDistFlow':<15} {ldf_source_p:>15.1f} {'PASS' if ldf.success else 'FAIL':>10}"
)
print("=" * 50)
vals = [ac_source_p, dc_grid_import, ldf_source_p]
print(f"\nMax disagreement: {max(vals) - min(vals):.1f} W")Using the CLI¶
All of the above can also be done from the command line:
# View system info
gdm-flow info examples/models/p5r.json
# Run all solvers and compare
gdm-flow compare examples/models/p5r.json
# Run a specific solver with verbose output
gdm-flow run examples/models/p5r.json -s ac -v
# Export results to SQLite
gdm-flow export examples/models/p5r.json --db results.db