Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Quickstart

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