potpourri
Multi-Period Optimal Power Flow for Distribution Grids with Storage Application
Potpourri — piece of music composed from various popular smaller works or melodies
potpourri is a Python library for AC/DC Optimal Power Flow (OPF) in distribution grids, with support for multi-period planning and flexible resources (batteries, EVs, heat pumps, PV, wind). It wraps Pyomo for optimisation modelling over pandapower network objects.
Documentation: https://opf-potpourri.readthedocs.io/
Repository: https://github.com/RWTH-IAEW/opf-potpourri
PyPI: https://pypi.org/project/opf-potpourri/
Installation
For users
Install from PyPI with pip or uv. Python 3.9–3.12 is supported.
pip install opf-potpourri
or with uv:
uv pip install opf-potpourri
Solvers are not bundled. Install at least one separately before calling
solve() — see Solvers below.
For developers
Clone the repository and create the Conda environment, which includes IPOPT and GLPK:
git clone --recurse-submodules https://github.com/RWTH-IAEW/opf-potpourri.git
cd opf-potpourri
conda env create -f environment.yaml # creates potpourri_env, includes solvers
conda activate potpourri_env
pip install -e ".[dev]" # editable install + ruff, pytest, pre-commit
To update an existing environment:
conda env update -f environment.yaml --prune
A Dockerfile is provided for a fully containerised setup with IPOPT 3.14.16 compiled from source, CBC, and SHOT solvers.
Documentation
Full documentation is available at https://opf-potpourri.readthedocs.io/, including:
To build and serve the documentation locally (contributors):
pip install -e ".[docs]"
mkdocs serve # available at http://127.0.0.1:8000/
Quick start
Single-period AC OPF
import simbench as sb
from potpourri.models.ACOPF_base import ACOPF
net = sb.get_simbench_net("1-LV-rural1--0-sw")
opf = ACOPF(net)
opf.add_OPF()
opf.add_voltage_deviation_objective()
opf.solve(solver="ipopt", print_solver_output=False)
# results available in net.res_bus, net.res_line, net.res_sgen, ...
print(opf.net.res_bus[["vm_pu", "va_degree"]])
Multi-period AC OPF with battery storage
import simbench as sb
from potpourri.models_multi_period.ACOPF_multi_period import ACOPF_multi_period
from potpourri.technologies.battery import Battery_multi_period
net = sb.get_simbench_net("1-LV-urban6--0-sw")
opf = ACOPF_multi_period(net, toT=96, fromT=0) # 96 × 15 min = 1 day
battery = Battery_multi_period(opf.net, T=96, scenario=1)
battery.get_all(opf.model)
opf.add_OPF()
opf.add_voltage_deviation_objective()
opf.solve(solver="ipopt")
See scripts/ for runnable examples covering each feature area.
Solvers
potpourri does not bundle any solvers. Install at least one before
calling solve().
| Solver | Type | Install |
|---|---|---|
| IPOPT | NLP — AC OPF | conda install -c conda-forge ipopt |
| GLPK | LP / MIP — DC OPF | conda install -c conda-forge glpk |
| CBC | LP / MIP | conda install -c conda-forge coincbc |
| Gurobi | LP / MIP / NLP | pip install gurobipy (licence required) |
| NEOS | Remote (free) | opf.solve(solver='neos', neos_opt='ipopt') |
IPOPT and GLPK are included automatically in the developer Conda environment
(environment.yaml). PyPI users must install solvers separately.
Architecture
Single-period models (src/potpourri/models/)
Basemodel creates ConcreteModel, maps pandapower → Pyomo sets/params, solve()
├── AC full AC power flow (KCL/KVL, voltage magnitudes, reactive power)
├── DC linearised DC power flow (no reactive power)
└── OPF operational constraints (P/Q limits, line loading, voltage bounds)
ACOPF = AC + OPF (multiple inheritance)
DCOPF = DC + OPF
HC_ACOPF = ACOPF + binary variables for hosting-capacity analysis
Multi-period models (src/potpourri/models_multi_period/)
Basemodel_multi_period adds time index T, integrates SimBench profiles
└── ACOPF_multi_period (AC_multi_period + OPF_multi_period)
Flexibility_multi_period abstract base for all flexible devices
├── Battery_multi_period
├── HeatPump_multi_period
├── PV_multi_period
├── Windpower_multi_period
├── Demand_multi_period
├── Sgens_multi_period
└── Generator_multi_period
Flexible devices are composed, not inherited — each is instantiated separately and attaches its own Pyomo Sets/Params/Vars/Constraints to the parent model.
Data flow
pandapower net
→ Basemodel.__init__() pp.runpp(), extract admittance data
→ create_model() Pyomo ConcreteModel + sets/params/vars
→ add_OPF() unfix controllable vars, add limits/objectives
→ .solve(solver) SolverFactory → NLP/MIP
→ pyo_to_net() write solution back to net.res_*
Benchmarking against PGLib-OPF
PGLib-OPF is the IEEE PES Power Grid Library benchmark suite for optimal power flow. Each case ships with a published reference objective (DC and AC, solved by PowerModels.jl + IPOPT) so results from different solvers and formulations can be compared directly.
The repository includes PGLib-OPF as a git submodule under benchmarks/pglib-opf/.
Clone with submodules to enable it:
git clone --recurse-submodules https://github.com/RWTH-IAEW/opf-potpourri.git
Run the benchmark script against a configurable PGLib subset:
python scripts/pglib_benchmark.py
This solves DC and AC OPF on each case with PGLib-compatible flags
(thermal_limit='mva', free_slack_vm=True, angle_limits=True) and writes
results/pglib_benchmark.{csv,md} with a BASELINE.md-style comparison table.
The potpourri.benchmarks package provides load_pglib_case for loading any
.m case file into a pandapower network ready for OPF, and reference baseline
dicts (PGLIB_BASELINE_TYP, PGLIB_BASELINE_API, PGLIB_BASELINE_SAD)
parsed from PGLib's upstream BASELINE.md.
The PGLib submodule is only needed for benchmarking. Normal pip install opf-potpourri is unaffected — the submodule is not part of the PyPI package.
External dependencies
| Package | Role |
|---|---|
pandapower >= 2.13 |
Network data model, initial power flow |
pyomo >= 6.7 |
Optimisation modelling |
simbench >= 1.4 |
Benchmark networks and time-series profiles |
numpy, pandas |
Numerical / data processing |
matplotlib |
Plotting |
Development
ruff check . # lint
ruff format . # format
pytest -m "not integration" # unit tests (no solver required)
pytest # all tests (integration tests need IPOPT)
Analysis and example scripts are in scripts/. See scripts/README.md
for an overview of what each example demonstrates.
Authors
- Steffen Kortmann — IAEW, RWTH Aachen University
- Andreas Bong — IAEW, RWTH Aachen University
- Simon Braun — IAEW, RWTH Aachen University
- Alexander Och — IAEW, RWTH Aachen University
- Farah Nasr — IAEW, RWTH Aachen University
- Philip Kvesic — IAEW, RWTH Aachen University
- Nina Stumberger — IAEW, RWTH Aachen University
Citation
If you use potpourri in your research, please cite it using the metadata in
CITATION.cff. A BibTeX entry will be available once a
Zenodo DOI is registered for the release.
License
potpourri is released under the MIT License.
Metadata
Release files for opf-potpourri 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| opf_potpourri-0.4.2.tar.gz | 110.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| opf_potpourri-0.4.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 238.3 kB
Release files / opf_potpourri-0.4.2.tar.gz
| Download URL | opf_potpourri-0.4.2.tar.gz |
|---|---|
| Size | 110.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e9e2e137aa80108bb15fdfdf991b2f9771ca26314db6a8be7c06f5e0252b7aa
|
|
BLAKE2b-256 checksum How to use checksums |
992c8a697ccb3b67d4f4724f7cc9b284858e884b8ae87f12e45163e69807a783
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / opf_potpourri-0.4.2-py3-none-any.whl
| Download URL | opf_potpourri-0.4.2-py3-none-any.whl |
|---|---|
| Size | 127.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a9bae43eaa8ab2721f8640fb712851b1e82a5993b8d9d85f4ae474c5a7d8e87
|
|
BLAKE2b-256 checksum How to use checksums |
d932934f4bcef238da399e5f67041cc40a17cd4d6406c87ba187c6134c9c759b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|