Power flow utilities for grid-data-models distribution systems
Project description
gdm-flow
Utilities for OPF and power-flow style preprocessing on top of
grid-data-models distribution systems.
Current features
- Y-Bus Construction — Phase-domain admittance matrices from GDM components (branches, transformers, switches) with matrix and sequence impedance support
- Four Solvers — AC OPF (nonlinear least-squares), AC PF (Newton-Raphson power flow), DC OPF (quadratic programming), and LinDistFlow (backward/forward sweep)
- Multi-Phase Support — Full three-phase and split-phase (center-tapped transformer) modeling
- Component Integration — Direct integration with GDM loads, solar PV, batteries, capacitors, and regulators
- Interactive Dashboards — Plotly-based HTML dashboards with voltage profiles, power flow, branch loading, losses, and equipment state
- QSTS Simulation — Quasi-static time series with warm-starting across timesteps for any solver
- Multi-Period OPF — Joint optimization across a time horizon with battery SOC coupling and ramp constraints (DC OPF and LinDistFlow)
- Time Series Discovery — Inspect available load, solar, and battery time series profiles in GDM models
- Modern CLI — Rich terminal interface with
info,run,compare,plot,export,ts-info,qsts,multiperiod,plot-ts, and reporting commands - SQLite Export — Structured database output with voltage/loading limit tracking, violation reporting, and streaming time series results
- MCP Server — Model Context Protocol server exposing all solvers as AI-callable tools
Install
pip install -e .
If you also want sparse matrix return support:
pip install -e .[sparse]
If you want optimization support:
pip install -e '.[optimization]'
If you want interactive plotting dashboards:
pip install -e '.[plotting]'
If you want to run the MCP server:
pip install -e '.[mcp,optimization]'
gdm-flow-mcp-server
Development checks
Install development dependencies and enable pre-commit hooks:
pip install -e '.[dev]'
pre-commit install
Run the same lint checks used in CI:
pre-commit run --all-files
Examples
An end-to-end examples folder is included at examples/ with a downloaded demo
distribution model and runnable scripts for each optimization flavor:
examples/models/p5r.jsonexamples/run_ac_opf_example.pyexamples/run_dc_opf_example.pyexamples/run_lindistflow_example.pyexamples/compare_plotly_results.py— interactive Plotly comparison across all solvers
Run from the repository root:
python examples/run_ac_opf_example.py
python examples/run_dc_opf_example.py
python examples/run_lindistflow_example.py
python examples/compare_plotly_results.py
Usage
from gdm.distribution import DistributionSystem
from gdm_flow import calculate_ybus
system = DistributionSystem.from_json("path/to/system.json")
result = calculate_ybus(system, include_shunt=False)
Y = result.ybus
labels = result.index_to_label
labels[k] is a (bus_name, phase) tuple for row/column k of Y.
Optimization usage
from gdm.distribution import DistributionSystem
from gdm_flow import optimize_ac_power_flow
system = DistributionSystem.from_json("path/to/system.json")
# Specify net nodal injections in SI units: +generation, -load
p_spec_w = {("bus_5", "A"): -20_000.0, ("bus_5", "B"): -20_000.0, ("bus_5", "C"): -20_000.0}
q_spec_var = {("bus_5", "A"): -5_000.0, ("bus_5", "B"): -5_000.0, ("bus_5", "C"): -5_000.0}
result = optimize_ac_power_flow(
system,
p_spec_w=p_spec_w,
q_spec_var=q_spec_var,
)
print(result.success, result.final_objective)
Auto-build specs from components
If your model already contains DistributionLoad and DistributionSolar components,
you can build nodal injections automatically:
from gdm.distribution import DistributionSystem
from gdm_flow import optimize_ac_power_flow_from_components
system = DistributionSystem.from_json("path/to/system.json")
result = optimize_ac_power_flow_from_components(
system,
include_loads=True,
include_solar=True,
include_capacitor=True,
include_battery=False,
include_regulator_targets=True,
include_regulator_limits=True,
)
print(result.success, result.final_objective)
Notes:
include_capacitor=Trueadds capacitor reactive injections into nodalQspecs.include_regulator_targets=Trueadds soft voltage-target constraints derived from regulator controllers.include_regulator_limits=Trueadds hard voltage magnitude bounds from regulator min/max limits.
AC Power Flow (Newton-Raphson)
gdm-flow includes a classical Newton-Raphson AC power flow solver. Unlike the AC OPF
which optimises voltage magnitudes within bounds, the AC PF solves for exact bus
voltages given fixed P/Q injections and a slack bus:
from gdm.distribution import DistributionSystem
from gdm_flow import solve_ac_power_flow_from_components
system = DistributionSystem.from_json("path/to/system.json")
result = solve_ac_power_flow_from_components(
system,
include_loads=True,
include_solar=True,
include_capacitor=True,
)
print(result.success, result.iterations)
print(result.max_mismatch_pu) # convergence metric
print(result.voltage_pu) # per-unit voltage magnitudes
The solver uses sparse LU factorisation with a damped update and LinDistFlow warm-start for robust convergence on heavily loaded feeders.
DC OPF module
gdm-flow also includes a separate DC OPF module:
from gdm.distribution import DistributionSystem
from gdm_flow import solve_dc_opf_from_components
system = DistributionSystem.from_json("path/to/system.json")
result = solve_dc_opf_from_components(
system,
include_solar_generators=True,
include_battery_generators=True,
include_loads=True,
)
print(result.success, result.objective)
print(result.generator_dispatch_w)
LinDistFlow module
gdm-flow includes a separate radial LinDistFlow approximation module:
from gdm.distribution import DistributionSystem
from gdm_flow import solve_lindistflow
system = DistributionSystem.from_json("path/to/system.json")
result = solve_lindistflow(system)
print(result.success)
print(result.voltage_v) # {(bus, phase): voltage_in_volts}
print(result.p_flow_w) # {(branch_name, phase): active_flow_w}
SQLite export module
You can export results from AC OPF, DC OPF, and LinDistFlow into one SQLite database:
from gdm_flow import export_all_results_to_sqlite
run_ids = export_all_results_to_sqlite(
"results.sqlite",
ac_result=ac_result,
dc_result=dc_result,
lindistflow_result=lindistflow_result,
)
print(run_ids)
Or export each result type separately:
export_ac_opf_result_to_sqlite(...)export_dc_opf_result_to_sqlite(...)export_lindistflow_result_to_sqlite(...)
Interactive dashboards
Generate interactive Plotly HTML dashboards from the CLI:
# Generate dashboard with all four solvers
gdm-flow plot examples/models/p5r.json
# Select specific solvers
gdm-flow plot examples/models/p5r.json -s ac -s pf
# Custom output path
gdm-flow plot examples/models/p5r.json -o my_dashboard.html
Time series simulation
GDM-Flow supports time series simulation for models with time-varying load and solar profiles. Two modes are available:
QSTS (Quasi-Static Time Series)
Sequential snapshot solves at each timestep with automatic warm-starting:
from gdm.distribution import DistributionSystem
from gdm_flow import run_qsts
system = DistributionSystem.from_json("model.json")
summary = run_qsts(
system,
solver="ldf", # any solver: ac, pf, dc, ldf
timestep_range=range(96), # 24 hours at 15-min resolution
db_path="qsts_results.db", # stream results to SQLite
)
print(f"Converged: {summary.num_converged}/{summary.num_timesteps}")
Multi-Period OPF
Joint optimization across the time horizon with battery SOC coupling:
from gdm_flow import solve_multiperiod_dc_opf
from gdm_flow.dc_opf import build_dc_generators_from_components
generators = build_dc_generators_from_components(system)
result = solve_multiperiod_dc_opf(
system,
generators=generators,
timestep_range=range(96),
ramp_limit_w=5000.0,
db_path="multiperiod.db",
)
print(f"Objective: {result.objective:.2f}")
CLI commands
# Check available time series
gdm-flow ts-info model.json
# QSTS simulation
gdm-flow qsts model.json --solver ldf --end 96 --db results.db
# Multi-period DC OPF
gdm-flow multiperiod model.json --solver dc --end 96 --ramp 5000 --db results.db
# Plot time series results
gdm-flow plot-ts results.db -o timeseries.html
The dashboard includes:
- Voltage-distance profiles along feeder paths
- Per-phase voltage comparison across solvers
- Branch power flow and loading analysis
- Line loss breakdown
- Equipment state (capacitors, regulators, transformers)
Requires the plotting extra: pip install -e '.[plotting]'
CLI export from JSON
Use the CLI to load saved result JSON files and export to SQLite in one command:
gdm-flow-export --db results.sqlite --ac-json ac_result.json --dc-json dc_result.json --lindistflow-json ldf_result.json
Generate starter JSON templates:
gdm-flow-export --write-templates ./templates
This creates:
templates/ac_result.template.jsontemplates/dc_result.template.jsontemplates/lindistflow_result.template.json
Expected JSON fields:
- AC JSON:
success,message,iterations,initial_objective,final_objectiveindex_to_label:[["bus", "phase"], ...]voltage:[{"real": ..., "imag": ...}, ...]power_injection:[{"real": ..., "imag": ...}, ...]
- DC JSON:
success,message,objective,iterations,slack_injection_wgenerator_dispatch_w:{name: value}theta_rad:{"bus|phase": value, ...}nodal_balance_w:{"bus|phase": value, ...}
- LinDistFlow JSON:
success,message,source_busvoltage_v,p_flow_w,q_flow_var,p_net_w,q_net_var- All series use
{"name|phase": value, ...}format.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gdm_flow-0.1.0.tar.gz.
File metadata
- Download URL: gdm_flow-0.1.0.tar.gz
- Upload date:
- Size: 110.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c219b5b3edbfd6cb1394d2356c5f381a7f390e8af2cb60cff0c0b28613caf783
|
|
| MD5 |
58cb4aedcbcfdd60413d03b4cfc23dff
|
|
| BLAKE2b-256 |
0e7bf73c5a3d5f3bec0a55ea0883228a75f4d83ac60ae9cab98e8b8be1cf01cd
|
Provenance
The following attestation bundles were made for gdm_flow-0.1.0.tar.gz:
Publisher:
publish.yml on NLR-Distribution-Suite/gdm_flow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gdm_flow-0.1.0.tar.gz -
Subject digest:
c219b5b3edbfd6cb1394d2356c5f381a7f390e8af2cb60cff0c0b28613caf783 - Sigstore transparency entry: 2080501704
- Sigstore integration time:
-
Permalink:
NLR-Distribution-Suite/gdm_flow@ba4c5607ec9265c7392845dc8eaff92fb630bf92 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/NLR-Distribution-Suite
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ba4c5607ec9265c7392845dc8eaff92fb630bf92 -
Trigger Event:
release
-
Statement type:
File details
Details for the file gdm_flow-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gdm_flow-0.1.0-py3-none-any.whl
- Upload date:
- Size: 90.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36fd7dffa48eb9bbbf59f1097e073238e0681c0026e8470d9b85a5f76a7af589
|
|
| MD5 |
d34e522fbb21859d73643782c33d9617
|
|
| BLAKE2b-256 |
04b7f1646686ed33209ed399370e83361bab502fe83a0bdb75a457f480888331
|
Provenance
The following attestation bundles were made for gdm_flow-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on NLR-Distribution-Suite/gdm_flow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gdm_flow-0.1.0-py3-none-any.whl -
Subject digest:
36fd7dffa48eb9bbbf59f1097e073238e0681c0026e8470d9b85a5f76a7af589 - Sigstore transparency entry: 2080502302
- Sigstore integration time:
-
Permalink:
NLR-Distribution-Suite/gdm_flow@ba4c5607ec9265c7392845dc8eaff92fb630bf92 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/NLR-Distribution-Suite
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ba4c5607ec9265c7392845dc8eaff92fb630bf92 -
Trigger Event:
release
-
Statement type: