opf-potpourri 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opf_potpourri-0.2.0/LICENSE +22 -0
- opf_potpourri-0.2.0/PKG-INFO +252 -0
- opf_potpourri-0.2.0/README.md +204 -0
- opf_potpourri-0.2.0/pyproject.toml +111 -0
- opf_potpourri-0.2.0/setup.cfg +4 -0
- opf_potpourri-0.2.0/src/opf_potpourri.egg-info/PKG-INFO +252 -0
- opf_potpourri-0.2.0/src/opf_potpourri.egg-info/SOURCES.txt +43 -0
- opf_potpourri-0.2.0/src/opf_potpourri.egg-info/dependency_links.txt +1 -0
- opf_potpourri-0.2.0/src/opf_potpourri.egg-info/requires.txt +28 -0
- opf_potpourri-0.2.0/src/opf_potpourri.egg-info/top_level.txt +1 -0
- opf_potpourri-0.2.0/src/potpourri/__init__.py +19 -0
- opf_potpourri-0.2.0/src/potpourri/models/AC.py +487 -0
- opf_potpourri-0.2.0/src/potpourri/models/ACOPF_base.py +694 -0
- opf_potpourri-0.2.0/src/potpourri/models/DC.py +146 -0
- opf_potpourri-0.2.0/src/potpourri/models/DCOPF.py +58 -0
- opf_potpourri-0.2.0/src/potpourri/models/HC_ACOPF.py +242 -0
- opf_potpourri-0.2.0/src/potpourri/models/OPF.py +532 -0
- opf_potpourri-0.2.0/src/potpourri/models/__init__.py +1 -0
- opf_potpourri-0.2.0/src/potpourri/models/basemodel.py +652 -0
- opf_potpourri-0.2.0/src/potpourri/models/init_pyo_from_pp_res.py +50 -0
- opf_potpourri-0.2.0/src/potpourri/models/pyo_to_net.py +320 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/ACOPF_multi_period.py +283 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/AC_multi_period.py +492 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/DCOPF_multi_period.py +42 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/DC_multi_period.py +222 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/HC_ACOPF_multi_period.py +87 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/OPF_multi_period.py +382 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/__init__.py +1 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/basemodel_multi_period.py +518 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/init_pyo_from_pp_res_multi_period.py +38 -0
- opf_potpourri-0.2.0/src/potpourri/models_multi_period/pyo_to_net_multi_period.py +389 -0
- opf_potpourri-0.2.0/src/potpourri/net_augmentation/__init__.py +2 -0
- opf_potpourri-0.2.0/src/potpourri/net_augmentation/prepare_net.py +52 -0
- opf_potpourri-0.2.0/src/potpourri/plotting/__init__.py +2 -0
- opf_potpourri-0.2.0/src/potpourri/plotting/plot_functions.py +589 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/__init__.py +2 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/battery.py +204 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/demand.py +178 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/flexibility.py +116 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/generator.py +223 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/heat_pump.py +240 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/pv.py +163 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/sgens.py +201 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/shunts.py +48 -0
- opf_potpourri-0.2.0/src/potpourri/technologies/windpower.py +418 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Institute for High Voltage Equipment and Grids,
|
|
4
|
+
Digitalization and Energy Economics (IAEW), RWTH Aachen University
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opf-potpourri
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Multi-period Optimal Power Flow for distribution grids with storage — Pyomo models over pandapower networks
|
|
5
|
+
Author-email: Steffen Kortmann <s.kortmann@iaew.rwth-aachen.de>, Andreas Bong <a.bong@iaew.rwth-aachen.de>, Simon Braun <s.braun@iaew.rwth-aachen.de>, Alexander Och <a.och@iaew.rwth-aachen.de>, Farah Nasr <f.nasr@iaew.rwth-aachen.de>, Philip Kvesic <p.kvesic@iaew.rwth-aachen.de>, Nina Stumberger <n.stumberger@iaew.rwth-aachen.de>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/RWTH-IAEW/opf-potpourri
|
|
8
|
+
Project-URL: Repository, https://github.com/RWTH-IAEW/opf-potpourri
|
|
9
|
+
Project-URL: Documentation, https://opf-potpourri.readthedocs.io/
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/RWTH-IAEW/opf-potpourri/issues
|
|
11
|
+
Keywords: power systems,pandapower,optimal power flow,pyomo,distribution grid,multi-period,OPF
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
20
|
+
Classifier: Intended Audience :: Science/Research
|
|
21
|
+
Requires-Python: <3.13,>=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: loguru>=0.7
|
|
25
|
+
Requires-Dist: matplotlib>=3.7
|
|
26
|
+
Requires-Dist: numpy>=1.24
|
|
27
|
+
Requires-Dist: openpyxl>=3.1
|
|
28
|
+
Requires-Dist: pandapower>=2.13
|
|
29
|
+
Requires-Dist: pandas>=2.0
|
|
30
|
+
Requires-Dist: pyomo>=6.7
|
|
31
|
+
Requires-Dist: simbench>=1.4
|
|
32
|
+
Provides-Extra: gurobi
|
|
33
|
+
Requires-Dist: gurobipy>=10.0; extra == "gurobi"
|
|
34
|
+
Provides-Extra: notebooks
|
|
35
|
+
Requires-Dist: jupyterlab>=4.0; extra == "notebooks"
|
|
36
|
+
Requires-Dist: notebook>=7.0; extra == "notebooks"
|
|
37
|
+
Provides-Extra: docs
|
|
38
|
+
Requires-Dist: mkdocs>=1.5; extra == "docs"
|
|
39
|
+
Requires-Dist: mkdocs-material>=9.0; extra == "docs"
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
42
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
43
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
44
|
+
Requires-Dist: pre-commit>=4.0; extra == "dev"
|
|
45
|
+
Provides-Extra: performance-test
|
|
46
|
+
Requires-Dist: perfplot>=0.10.2; extra == "performance-test"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# potpourri
|
|
50
|
+
|
|
51
|
+
**Multi-Period Optimal Power Flow for Distribution Grids with Storage Application**
|
|
52
|
+
|
|
53
|
+
> *Potpourri — piece of music composed from various popular smaller works or melodies*
|
|
54
|
+
|
|
55
|
+
[](https://github.com/RWTH-IAEW/opf-potpourri/actions/workflows/ci.yml)
|
|
56
|
+
[](https://opf-potpourri.readthedocs.io/)
|
|
57
|
+
[](LICENSE)
|
|
58
|
+
|
|
59
|
+
`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](https://pyomo.readthedocs.io/) for optimisation modelling over [pandapower](https://pandapower.readthedocs.io/) network objects.
|
|
60
|
+
|
|
61
|
+
**Repository:** <https://github.com/RWTH-IAEW/opf-potpourri>
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
The project documentation is built with [MkDocs](https://www.mkdocs.org/).
|
|
68
|
+
|
|
69
|
+
To serve the documentation locally:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install -e .[docs]
|
|
73
|
+
mkdocs serve # usually available at http://127.0.0.1:8000/
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
Requires Python 3.9–3.12 and Conda (or Mamba).
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
conda env create -f environment.yaml
|
|
84
|
+
conda activate potpourri_env
|
|
85
|
+
pip install -e .
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
To update an existing environment:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
conda env update -f environment.yaml --prune
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
A Dockerfile is provided for a fully containerised setup with IPOPT 3.14.16
|
|
95
|
+
compiled from source, CBC, and SHOT solvers.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Quick start
|
|
100
|
+
|
|
101
|
+
### Single-period AC OPF
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import simbench as sb
|
|
105
|
+
from potpourri.models.ACOPF_base import ACOPF
|
|
106
|
+
|
|
107
|
+
net = sb.get_simbench_net("1-LV-rural1--0-sw")
|
|
108
|
+
opf = ACOPF(net)
|
|
109
|
+
opf.add_OPF()
|
|
110
|
+
opf.add_voltage_deviation_objective()
|
|
111
|
+
opf.solve(solver="ipopt", print_solver_output=False)
|
|
112
|
+
|
|
113
|
+
# results available in net.res_bus, net.res_line, net.res_sgen, ...
|
|
114
|
+
print(opf.net.res_bus[["vm_pu", "va_degree"]])
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Multi-period AC OPF with battery storage
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import simbench as sb
|
|
121
|
+
from potpourri.models_multi_period.ACOPF_multi_period import ACOPF_multi_period
|
|
122
|
+
from potpourri.technologies.battery import Battery_multi_period
|
|
123
|
+
|
|
124
|
+
net = sb.get_simbench_net("1-LV-urban6--0-sw")
|
|
125
|
+
opf = ACOPF_multi_period(net, toT=96, fromT=0) # 96 × 15 min = 1 day
|
|
126
|
+
|
|
127
|
+
battery = Battery_multi_period(opf.net, T=96, scenario=1)
|
|
128
|
+
battery.get_all(opf.model)
|
|
129
|
+
|
|
130
|
+
opf.add_OPF()
|
|
131
|
+
opf.add_voltage_deviation_objective()
|
|
132
|
+
opf.solve(solver="ipopt")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
See `scripts/` for runnable examples covering each feature area.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Architecture
|
|
140
|
+
|
|
141
|
+
### Single-period models (`src/potpourri/models/`)
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
Basemodel creates ConcreteModel, maps pandapower → Pyomo sets/params, solve()
|
|
145
|
+
├── AC full AC power flow (KCL/KVL, voltage magnitudes, reactive power)
|
|
146
|
+
├── DC linearised DC power flow (no reactive power)
|
|
147
|
+
└── OPF operational constraints (P/Q limits, line loading, voltage bounds)
|
|
148
|
+
|
|
149
|
+
ACOPF = AC + OPF (multiple inheritance)
|
|
150
|
+
DCOPF = DC + OPF
|
|
151
|
+
HC_ACOPF = ACOPF + binary variables for hosting-capacity analysis
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Multi-period models (`src/potpourri/models_multi_period/`)
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Basemodel_multi_period adds time index T, integrates SimBench profiles
|
|
158
|
+
└── ACOPF_multi_period (AC_multi_period + OPF_multi_period)
|
|
159
|
+
|
|
160
|
+
Flexibility_multi_period abstract base for all flexible devices
|
|
161
|
+
├── Battery_multi_period
|
|
162
|
+
├── HeatPump_multi_period
|
|
163
|
+
├── PV_multi_period
|
|
164
|
+
├── Windpower_multi_period
|
|
165
|
+
├── Demand_multi_period
|
|
166
|
+
├── Sgens_multi_period
|
|
167
|
+
└── Generator_multi_period
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Flexible devices are **composed, not inherited** — each is instantiated
|
|
171
|
+
separately and attaches its own Pyomo Sets/Params/Vars/Constraints to the
|
|
172
|
+
parent model.
|
|
173
|
+
|
|
174
|
+
### Data flow
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
pandapower net
|
|
178
|
+
→ Basemodel.__init__() pp.runpp(), extract admittance data
|
|
179
|
+
→ create_model() Pyomo ConcreteModel + sets/params/vars
|
|
180
|
+
→ add_OPF() unfix controllable vars, add limits/objectives
|
|
181
|
+
→ .solve(solver) SolverFactory → NLP/MIP
|
|
182
|
+
→ pyo_to_net() write solution back to net.res_*
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## External dependencies
|
|
188
|
+
|
|
189
|
+
| Package | Role |
|
|
190
|
+
|---|---|
|
|
191
|
+
| `pandapower >= 2.13` | Network data model, initial power flow |
|
|
192
|
+
| `pyomo >= 6.7` | Optimisation modelling |
|
|
193
|
+
| `simbench >= 1.4` | Benchmark networks and time-series profiles |
|
|
194
|
+
| `numpy`, `pandas` | Numerical / data processing |
|
|
195
|
+
| `matplotlib` | Plotting |
|
|
196
|
+
|
|
197
|
+
### Solvers
|
|
198
|
+
|
|
199
|
+
`potpourri` does not bundle any solvers. Install at least one before
|
|
200
|
+
calling `solve()`.
|
|
201
|
+
|
|
202
|
+
| Solver | Type | Install |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| **IPOPT** | NLP — AC OPF | `conda install -c conda-forge ipopt` |
|
|
205
|
+
| **GLPK** | LP / MIP — DC OPF | `conda install -c conda-forge glpk` |
|
|
206
|
+
| **CBC** | LP / MIP | `conda install -c conda-forge coincbc` |
|
|
207
|
+
| **Gurobi** | LP / MIP / NLP | `pip install gurobipy` (licence required) |
|
|
208
|
+
| **NEOS** | Remote (free) | `opf.solve(solver='neos', neos_opt='ipopt')` |
|
|
209
|
+
|
|
210
|
+
IPOPT and GLPK are included automatically when you create the environment
|
|
211
|
+
from `environment.yaml`.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
pip install -e ".[dev]" # installs ruff, pytest, pytest-cov, pre-commit
|
|
219
|
+
ruff check . # lint
|
|
220
|
+
ruff format . # format
|
|
221
|
+
pytest # run tests
|
|
222
|
+
pytest -m "not integration" # skip solver-dependent tests
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Analysis and example scripts are in `scripts/`. See `scripts/README.md`
|
|
226
|
+
for an overview of what each example demonstrates.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Authors
|
|
231
|
+
|
|
232
|
+
- Steffen Kortmann — IAEW, RWTH Aachen University
|
|
233
|
+
- Andreas Bong — IAEW, RWTH Aachen University
|
|
234
|
+
- Simon Braun — IAEW, RWTH Aachen University
|
|
235
|
+
- Alexander Och — IAEW, RWTH Aachen University
|
|
236
|
+
- Farah Nasr — IAEW, RWTH Aachen University
|
|
237
|
+
- Philip Kvesic — IAEW, RWTH Aachen University
|
|
238
|
+
- Nina Stumberger — IAEW, RWTH Aachen University
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Citation
|
|
243
|
+
|
|
244
|
+
If you use `potpourri` in your research, please cite it using the metadata in
|
|
245
|
+
[`CITATION.cff`](CITATION.cff). A BibTeX entry will be available once a
|
|
246
|
+
Zenodo DOI is registered for the release.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
`potpourri` is released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# potpourri
|
|
2
|
+
|
|
3
|
+
**Multi-Period Optimal Power Flow for Distribution Grids with Storage Application**
|
|
4
|
+
|
|
5
|
+
> *Potpourri — piece of music composed from various popular smaller works or melodies*
|
|
6
|
+
|
|
7
|
+
[](https://github.com/RWTH-IAEW/opf-potpourri/actions/workflows/ci.yml)
|
|
8
|
+
[](https://opf-potpourri.readthedocs.io/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
`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](https://pyomo.readthedocs.io/) for optimisation modelling over [pandapower](https://pandapower.readthedocs.io/) network objects.
|
|
12
|
+
|
|
13
|
+
**Repository:** <https://github.com/RWTH-IAEW/opf-potpourri>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Documentation
|
|
18
|
+
|
|
19
|
+
The project documentation is built with [MkDocs](https://www.mkdocs.org/).
|
|
20
|
+
|
|
21
|
+
To serve the documentation locally:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -e .[docs]
|
|
25
|
+
mkdocs serve # usually available at http://127.0.0.1:8000/
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
Requires Python 3.9–3.12 and Conda (or Mamba).
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
conda env create -f environment.yaml
|
|
36
|
+
conda activate potpourri_env
|
|
37
|
+
pip install -e .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
To update an existing environment:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
conda env update -f environment.yaml --prune
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
A Dockerfile is provided for a fully containerised setup with IPOPT 3.14.16
|
|
47
|
+
compiled from source, CBC, and SHOT solvers.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
### Single-period AC OPF
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import simbench as sb
|
|
57
|
+
from potpourri.models.ACOPF_base import ACOPF
|
|
58
|
+
|
|
59
|
+
net = sb.get_simbench_net("1-LV-rural1--0-sw")
|
|
60
|
+
opf = ACOPF(net)
|
|
61
|
+
opf.add_OPF()
|
|
62
|
+
opf.add_voltage_deviation_objective()
|
|
63
|
+
opf.solve(solver="ipopt", print_solver_output=False)
|
|
64
|
+
|
|
65
|
+
# results available in net.res_bus, net.res_line, net.res_sgen, ...
|
|
66
|
+
print(opf.net.res_bus[["vm_pu", "va_degree"]])
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Multi-period AC OPF with battery storage
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
import simbench as sb
|
|
73
|
+
from potpourri.models_multi_period.ACOPF_multi_period import ACOPF_multi_period
|
|
74
|
+
from potpourri.technologies.battery import Battery_multi_period
|
|
75
|
+
|
|
76
|
+
net = sb.get_simbench_net("1-LV-urban6--0-sw")
|
|
77
|
+
opf = ACOPF_multi_period(net, toT=96, fromT=0) # 96 × 15 min = 1 day
|
|
78
|
+
|
|
79
|
+
battery = Battery_multi_period(opf.net, T=96, scenario=1)
|
|
80
|
+
battery.get_all(opf.model)
|
|
81
|
+
|
|
82
|
+
opf.add_OPF()
|
|
83
|
+
opf.add_voltage_deviation_objective()
|
|
84
|
+
opf.solve(solver="ipopt")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
See `scripts/` for runnable examples covering each feature area.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Architecture
|
|
92
|
+
|
|
93
|
+
### Single-period models (`src/potpourri/models/`)
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Basemodel creates ConcreteModel, maps pandapower → Pyomo sets/params, solve()
|
|
97
|
+
├── AC full AC power flow (KCL/KVL, voltage magnitudes, reactive power)
|
|
98
|
+
├── DC linearised DC power flow (no reactive power)
|
|
99
|
+
└── OPF operational constraints (P/Q limits, line loading, voltage bounds)
|
|
100
|
+
|
|
101
|
+
ACOPF = AC + OPF (multiple inheritance)
|
|
102
|
+
DCOPF = DC + OPF
|
|
103
|
+
HC_ACOPF = ACOPF + binary variables for hosting-capacity analysis
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Multi-period models (`src/potpourri/models_multi_period/`)
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Basemodel_multi_period adds time index T, integrates SimBench profiles
|
|
110
|
+
└── ACOPF_multi_period (AC_multi_period + OPF_multi_period)
|
|
111
|
+
|
|
112
|
+
Flexibility_multi_period abstract base for all flexible devices
|
|
113
|
+
├── Battery_multi_period
|
|
114
|
+
├── HeatPump_multi_period
|
|
115
|
+
├── PV_multi_period
|
|
116
|
+
├── Windpower_multi_period
|
|
117
|
+
├── Demand_multi_period
|
|
118
|
+
├── Sgens_multi_period
|
|
119
|
+
└── Generator_multi_period
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Flexible devices are **composed, not inherited** — each is instantiated
|
|
123
|
+
separately and attaches its own Pyomo Sets/Params/Vars/Constraints to the
|
|
124
|
+
parent model.
|
|
125
|
+
|
|
126
|
+
### Data flow
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
pandapower net
|
|
130
|
+
→ Basemodel.__init__() pp.runpp(), extract admittance data
|
|
131
|
+
→ create_model() Pyomo ConcreteModel + sets/params/vars
|
|
132
|
+
→ add_OPF() unfix controllable vars, add limits/objectives
|
|
133
|
+
→ .solve(solver) SolverFactory → NLP/MIP
|
|
134
|
+
→ pyo_to_net() write solution back to net.res_*
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## External dependencies
|
|
140
|
+
|
|
141
|
+
| Package | Role |
|
|
142
|
+
|---|---|
|
|
143
|
+
| `pandapower >= 2.13` | Network data model, initial power flow |
|
|
144
|
+
| `pyomo >= 6.7` | Optimisation modelling |
|
|
145
|
+
| `simbench >= 1.4` | Benchmark networks and time-series profiles |
|
|
146
|
+
| `numpy`, `pandas` | Numerical / data processing |
|
|
147
|
+
| `matplotlib` | Plotting |
|
|
148
|
+
|
|
149
|
+
### Solvers
|
|
150
|
+
|
|
151
|
+
`potpourri` does not bundle any solvers. Install at least one before
|
|
152
|
+
calling `solve()`.
|
|
153
|
+
|
|
154
|
+
| Solver | Type | Install |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| **IPOPT** | NLP — AC OPF | `conda install -c conda-forge ipopt` |
|
|
157
|
+
| **GLPK** | LP / MIP — DC OPF | `conda install -c conda-forge glpk` |
|
|
158
|
+
| **CBC** | LP / MIP | `conda install -c conda-forge coincbc` |
|
|
159
|
+
| **Gurobi** | LP / MIP / NLP | `pip install gurobipy` (licence required) |
|
|
160
|
+
| **NEOS** | Remote (free) | `opf.solve(solver='neos', neos_opt='ipopt')` |
|
|
161
|
+
|
|
162
|
+
IPOPT and GLPK are included automatically when you create the environment
|
|
163
|
+
from `environment.yaml`.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Development
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pip install -e ".[dev]" # installs ruff, pytest, pytest-cov, pre-commit
|
|
171
|
+
ruff check . # lint
|
|
172
|
+
ruff format . # format
|
|
173
|
+
pytest # run tests
|
|
174
|
+
pytest -m "not integration" # skip solver-dependent tests
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Analysis and example scripts are in `scripts/`. See `scripts/README.md`
|
|
178
|
+
for an overview of what each example demonstrates.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Authors
|
|
183
|
+
|
|
184
|
+
- Steffen Kortmann — IAEW, RWTH Aachen University
|
|
185
|
+
- Andreas Bong — IAEW, RWTH Aachen University
|
|
186
|
+
- Simon Braun — IAEW, RWTH Aachen University
|
|
187
|
+
- Alexander Och — IAEW, RWTH Aachen University
|
|
188
|
+
- Farah Nasr — IAEW, RWTH Aachen University
|
|
189
|
+
- Philip Kvesic — IAEW, RWTH Aachen University
|
|
190
|
+
- Nina Stumberger — IAEW, RWTH Aachen University
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Citation
|
|
195
|
+
|
|
196
|
+
If you use `potpourri` in your research, please cite it using the metadata in
|
|
197
|
+
[`CITATION.cff`](CITATION.cff). A BibTeX entry will be available once a
|
|
198
|
+
Zenodo DOI is registered for the release.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
`potpourri` is released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "opf-potpourri"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Multi-period Optimal Power Flow for distribution grids with storage — Pyomo models over pandapower networks"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9,<3.13"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Steffen Kortmann", email = "s.kortmann@iaew.rwth-aachen.de" },
|
|
15
|
+
{ name = "Andreas Bong", email = "a.bong@iaew.rwth-aachen.de" },
|
|
16
|
+
{ name = "Simon Braun", email = "s.braun@iaew.rwth-aachen.de" },
|
|
17
|
+
{ name = "Alexander Och", email = "a.och@iaew.rwth-aachen.de" },
|
|
18
|
+
{ name = "Farah Nasr", email = "f.nasr@iaew.rwth-aachen.de" },
|
|
19
|
+
{ name = "Philip Kvesic", email = "p.kvesic@iaew.rwth-aachen.de" },
|
|
20
|
+
{ name = "Nina Stumberger", email = "n.stumberger@iaew.rwth-aachen.de" },
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.9",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Topic :: Scientific/Engineering",
|
|
30
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
31
|
+
"Intended Audience :: Science/Research",
|
|
32
|
+
]
|
|
33
|
+
keywords = [
|
|
34
|
+
"power systems",
|
|
35
|
+
"pandapower",
|
|
36
|
+
"optimal power flow",
|
|
37
|
+
"pyomo",
|
|
38
|
+
"distribution grid",
|
|
39
|
+
"multi-period",
|
|
40
|
+
"OPF",
|
|
41
|
+
]
|
|
42
|
+
dependencies = [
|
|
43
|
+
"loguru>=0.7",
|
|
44
|
+
"matplotlib>=3.7",
|
|
45
|
+
"numpy>=1.24",
|
|
46
|
+
"openpyxl>=3.1",
|
|
47
|
+
"pandapower>=2.13",
|
|
48
|
+
"pandas>=2.0",
|
|
49
|
+
"pyomo>=6.7",
|
|
50
|
+
"simbench>=1.4",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[project.optional-dependencies]
|
|
54
|
+
gurobi = [
|
|
55
|
+
"gurobipy>=10.0",
|
|
56
|
+
]
|
|
57
|
+
notebooks = [
|
|
58
|
+
"jupyterlab>=4.0",
|
|
59
|
+
"notebook>=7.0",
|
|
60
|
+
]
|
|
61
|
+
docs = [
|
|
62
|
+
"mkdocs>=1.5",
|
|
63
|
+
"mkdocs-material>=9.0",
|
|
64
|
+
]
|
|
65
|
+
dev = [
|
|
66
|
+
"pytest>=8.0",
|
|
67
|
+
"pytest-cov>=5.0",
|
|
68
|
+
"ruff>=0.4",
|
|
69
|
+
"pre-commit>=4.0",
|
|
70
|
+
]
|
|
71
|
+
performance-test = [
|
|
72
|
+
"perfplot>=0.10.2",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[project.urls]
|
|
76
|
+
Homepage = "https://github.com/RWTH-IAEW/opf-potpourri"
|
|
77
|
+
Repository = "https://github.com/RWTH-IAEW/opf-potpourri"
|
|
78
|
+
Documentation = "https://opf-potpourri.readthedocs.io/"
|
|
79
|
+
"Bug Tracker" = "https://github.com/RWTH-IAEW/opf-potpourri/issues"
|
|
80
|
+
|
|
81
|
+
[tool.setuptools.packages.find]
|
|
82
|
+
where = ["src"]
|
|
83
|
+
|
|
84
|
+
[tool.setuptools.package-data]
|
|
85
|
+
"potpourri" = ["data/*.pkl", "data/*.xlsx"]
|
|
86
|
+
|
|
87
|
+
[tool.ruff]
|
|
88
|
+
line-length = 79
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint]
|
|
91
|
+
extend-select = ["E501"]
|
|
92
|
+
# F403/F405: `from pyomo.environ import *` is standard Pyomo convention.
|
|
93
|
+
# E741: single-letter `l` is the standard line-index variable in power systems math.
|
|
94
|
+
ignore = ["E741", "F403", "F405"]
|
|
95
|
+
|
|
96
|
+
[tool.ruff.lint.per-file-ignores]
|
|
97
|
+
# Tutorial notebooks converted to percent-format scripts; imports appear mid-file.
|
|
98
|
+
"tutorials/*.py" = ["E402", "E501"]
|
|
99
|
+
"tutorials/*.ipynb" = ["E501"]
|
|
100
|
+
"scripts/*.py" = ["E501"]
|
|
101
|
+
"tests/**/*.py" = ["E501"]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.lint.pydocstyle]
|
|
104
|
+
convention = "google"
|
|
105
|
+
|
|
106
|
+
[tool.pytest.ini_options]
|
|
107
|
+
testpaths = ["tests"]
|
|
108
|
+
markers = [
|
|
109
|
+
"slow: marks tests as slow (deselect with -m 'not slow')",
|
|
110
|
+
"integration: marks tests that require a remote solver or network access",
|
|
111
|
+
]
|