Awesome
matpower-pip
matpower-pip: A Python Package for Easy Access to MATPOWER Power System Simulation Package
This package is intended to make MATPOWER installable from PyPI
. We did not change anything from MATPOWER
package, instead, we used a copy of MATPOWER
(currently Version 8.0
) and wrapped it as python package
published on PyPI. Use this package with mypower
(the recommended way) or oct2py
to run MATPOWER
using octave
client. matlab.engine
is also supported. For the latest docs, read README on GitHub.
This project is also listed on related links on MATPOWER
official website. Please visit that site to find other useful resources.
Installation
matpower
For downloading MATPOWER
only (maybe you will run it using matlab.engine
or any other method, or simply want an easy MATPOWER
downloader):
pip install matpower
oct2py
(Windows)
For callable matpower
via oct2py
(require octave on environment system PATH
). You can follow the oct2py instalation tutorial in mypower repository.
Usage
See notebooks/
for complete examples. All examples should be compatible with Google Colab.
Running with an engine (require oct2py
or matlab.engine
)
If oct2py
or matlab.engine
is installed, matpower.start_instance
can be used to run octave
or MATLAB
with MATPOWER
path added. The default engine is octave
. You also can use mypower
for added functionality as shown in mypower tutorial
.
from matpower import start_instance
m = start_instance()
m.runpf()
from matpower import start_instance
m = start_instance()
mpc = m.eval('case9', verbose=False)
mpc = m.runpf(mpc)
from matpower import Matpower
with Matpower(engine='octave') as m: # run as context manager
mpc = m.eval('case9', verbose=False)
mpc = m.runpf(mpc)
print(m._engine is None) # engine cleanly terminated
from matpower import path_matpower
print(path_matpower) # matpower installation location
Since mpc = m.runopf()
will make mpc
contain unsupported <object opf_model>
, we can avoid it by requesting a maximum number of outputs using nout='max_nout'
in octave
.
from matpower import start_instance
m = start_instance()
mpc = m.loadcase('case9')
mpopt = m.mpoption('verbose', 2)
[baseMVA, bus, gen, gencost, branch, f, success, et] = m.runopf(mpc, mpopt, nout='max_nout')
Or we can remove unsupported objects.
from matpower import start_instance
m = start_instance()
mpc = m.loadcase('case9')
mpopt = m.mpoption('verbose', 2)
m.push("_mpopt", mpopt)
m.push("_mpc", mpc, verbose=False)
m.eval("_r1 = runopf(_mpc, _mpopt);", verbose=False)
# `_r1` containts unsupported `<object opf_model>`, needs to be removed first
m.eval(
"""
_r1.raw = rmfield(_r1.raw, 'task');
_r1 = rmfield(_r1, 'om');
"""
)
mpc = m.pull("_r1")
Alternatively, only select values that will be used on python using oct2py
.eval
method. Combine it with the use of ;
to avoid octave print output on running the command.
# import start_instance to start matpower instance
from matpower import start_instance
# start instance
m = start_instance()
m.eval(
"""
mpopt = mpoption('verbose', 2);
mpc = loadcase('case9');
_r1 = runopf(mpc, mpopt);
"""
)
# fech data to python (.eval is used because .pull is not working in acessing field)
r1_mpc = m.eval(
"struct("
" 'baseMVA', _r1.baseMVA, 'version', _r1.version, 'bus', _r1.bus, 'gen', _r1.gen,"
" 'branch', _r1.branch, 'gencost', _r1.gencost);"
)
# modify variable if necessary
[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, MU_PMAX,
MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX,
RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = m.idx_gen(nout='max_nout')
gen_index = 2 # index of generator to be changed
gen_index_ = int(gen_index - 1) # -1 due to python indexing start from 0
PMAX_ = int(PMAX -1) # -1 due to python indexing start from 0
r1_mpc['gen'][gen_index_,PMAX_] = 110 # in this example, we modify PMAX to be 110
[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS,
BUS_AREA, VM, VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P,
LAM_Q, MU_VMAX, MU_VMIN] = m.idx_bus(nout='max_nout')
bus_index = 7 # index of bus to be changed
bus_index_ = int(bus_index - 1) # -1 due to python indexing start from 0
PD_ = int(PD-1) # -1 due to python indexing start from 0
r1_mpc['bus'][bus_index_,int(PD-1)] = 80 # in this example, we modify PD to be 150
# push back value to octave client
m.push('mpc', r1_mpc) # push r1_mpc in python to mpc in octave
# test if we can retrive pushed value
mpc = m.pull('mpc')
# test if our pushed variable can be used
m.eval("_r1 = runopf(mpc, mpopt);")
matpower-pip
also support using matlab.engine
.
from matpower import start_instance
m = start_instance(engine='matlab') # specify using `matlab.engine` instead of `oct2py`
mpc = m.runpf('case5', nargout=0)
Known engine issue
Octave
-
m.runopf()
will makempc
contain unsupported<object opf_model>
. See: https://github.com/MATPOWER/matpower/issues/134#issuecomment-1007798733Impacted case:
_r1 = m.runopf(mpc)
Solution:
m.push('mpc', mpc) r1_mpc = m.eval( """ mpopt = mpoption('verbose', 2); _r1 = runopf(mpc, mpopt); """ "struct(" " 'baseMVA', _r1.baseMVA, 'version', _r1.version, 'bus', _r1.bus, 'gen', _r1.gen," " 'branch', _r1.branch, 'gencost', _r1.gencost);" )
Versioning
This package maintains MATPOWER
version with an added version mark, i.e. MATPOWER 7.1
becomes 7.1.0.x.x.x
where the .x.x.x
comes from matpower-pip
versioning. The matpower-pip
versioning is not released on pypi
since matpower-pip
is restricted for development only (and development should use git instead).
TODO
conda
anddocker
installation that includes octave-cli installation.
Authors
- Muhammad Yasirroni - yasirroni
Cite
We do request that publications derived from the use of matpower-pip
explicitly acknowledge that fact by including all related MATPOWER publications and the following citation:
M. Yasirroni, Sarjiya, and L. M. Putranto, "matpower-pip: A Python Package for Easy Access to MATPOWER Power System Simulation Package," [Online]. Available: https://github.com/yasirroni/matpower-pip.
M. Yasirroni, Sarjiya, and L. M. Putranto, "matpower-pip". Zenodo, Jun. 13, 2024. doi: 10.5281/zenodo.11626845.
@misc{matpower-pip,
author = {Yasirroni, M. and Sarjiya and Putranto, L. M.},
title = {matpower-pip: A Python Package for Easy Access to MATPOWER Power System Simulation Package},
year = {2023},
howpublished = {\url{https://github.com/yasirroni/matpower-pip}},
}
@software{yasirroni_2024_11626845,
author = {Yasirroni, Muhammad and
Sarjiya, Sarjiya and
Putranto, Lesnanto Multa},
title = {matpower-pip},
month = jun,
year = 2024,
publisher = {Zenodo},
version = {8.0.0.2.1.8},
doi = {10.5281/zenodo.11626845},
url = {\url{https://doi.org/10.5281/zenodo.11626845}}
}
If a journal publication from the author appears soon should be cited instead.
Contributing
See the CONTRIBUTING.md.
Acknowledgment
This repository was supported by the Faculty of Engineering, Universitas Gadjah Mada under the supervision of Mr. Sarjiya. If you use this package, we would be very glad if you cite any relevant publication under Mr. Sarjiya's name that can be found in the semantic scholar or IEEE in the meantime, since publication related to this repository is ongoing. This work is also partly motivated after I found out that oct2py
supports running octave
client from python
, but the only implementation for running MATPOWER
that I know is oct2pypower which requires docker
and is not newbie-friendly. Nevertheless, I would like to say thank you to all the people who have contributed to oct2py
, oct2pypower
, and more importantly MATPOWER
.