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/
Install from PyPI with pip or uv. Python 3.9–3.12 is supported.
pip install opf-potpourrior with uv:
uv pip install opf-potpourriSolvers are not bundled. Install at least one separately before calling
solve() — see Solvers below.
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-commitTo update an existing environment:
conda env update -f environment.yaml --pruneA Dockerfile is provided for a fully containerised setup with IPOPT 3.14.16 compiled from source, CBC, and SHOT solvers.
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/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"]])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.
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.
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
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.
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_*
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.gitRun the benchmark script against a configurable PGLib subset:
python scripts/pglib_benchmark.pyThis 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.
| 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 |
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.
- 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
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.
potpourri is released under the MIT License.