Skip to main content

matpower-pip: A Python Package for Easy Access to MATPOWER Power System Simulation Package

Project description

matpower-pip

PyPI version License: MIT DOI

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.1) 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

Open In Colab

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.

Since matlabengine does not support sparse matrices, runpf results cannot be returned directly to Python. Use nargout=0 to print the result in MATLAB without returning it:

from matpower import start_instance

m = start_instance(engine='matlab')
m.runpf(nargout=0)
from matpower import start_instance

m = start_instance(engine='matlab')
mpc = m.loadcase('case9')
m.runpf(mpc, nargout=0)

To get the results back in Python, use the workspace workaround:

from matpower import start_instance

m = start_instance(engine='matlab')
mpc = m.loadcase('case9')
m.workspace["mpc_"] = mpc
m.eval("r1_ = runpf(mpc_);", nargout=0)
r1 = {
    "baseMVA": m.eval("r1_.baseMVA;", nargout=1),
    "version": m.eval("r1_.version;", nargout=1),
    "bus": m.eval("r1_.bus;", nargout=1),
    "gen": m.eval("r1_.gen;", nargout=1),
    "branch": m.eval("r1_.branch;", nargout=1),
    "gencost": m.eval("r1_.gencost;", nargout=1),
}

Running with wrapped engine (automatically detect oct2py or matlab.engine)

from matpower import run_matpower_cmd, start_instance

m = start_instance()
mpc = m.loadcase("case9")
r1 = run_matpower_cmd("runpf(mpc)", m=m, mpc=mpc)
m.exit()

Known engine issue

Octave

  1. m.runopf() will make mpc contain unsupported <object opf_model>. See: https://github.com/MATPOWER/matpower/issues/134#issuecomment-1007798733

    Impacted 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);"
    )
    
  2. matlabengine did not support sparse matrix, making even runpf result can't be passed to python directly. See: https://github.com/mathworks/matlab-engine-for-python/issues/60

    Impacted case:

    r1 = m.runpf(mpc, nargout=0)
    

    Solution:

    m.workspace["mpc_"] = mpc
    m.eval("r1_ = runpf(mpc_);", nargout=0)
    r1 = {
        "baseMVA": m.eval("r1_.baseMVA;", nargout=1),
        "version": m.eval("r1_.version;", nargout=1),
        "bus": m.eval("r1_.bus;", nargout=1),
        "gen": m.eval("r1_.gen;", nargout=1),
        "branch": m.eval("r1_.branch;", nargout=1),
        "gencost": m.eval("r1_.gencost;", nargout=1),
    }
    

Versioning

This package maintains MATPOWER version with an added version mark, i.e. MATPOWER 8.1 becomes 8.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

  1. conda and docker installation that includes octave-cli installation.

Authors

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matpower-8.1.0.2.3.0.tar.gz (38.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

matpower-8.1.0.2.3.0-py3-none-any.whl (41.4 MB view details)

Uploaded Python 3

File details

Details for the file matpower-8.1.0.2.3.0.tar.gz.

File metadata

  • Download URL: matpower-8.1.0.2.3.0.tar.gz
  • Upload date:
  • Size: 38.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for matpower-8.1.0.2.3.0.tar.gz
Algorithm Hash digest
SHA256 d86c77c9d3524c99d8e14cf10a174fd934965285be54f0c937370cb05c05313f
MD5 a65aa77878ea5e25bec0125cc4d229cc
BLAKE2b-256 50f51a726470d41c0476b8ec0ac1c086e4891484688e87c28cd08b813eb53eaf

See more details on using hashes here.

File details

Details for the file matpower-8.1.0.2.3.0-py3-none-any.whl.

File metadata

  • Download URL: matpower-8.1.0.2.3.0-py3-none-any.whl
  • Upload date:
  • Size: 41.4 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for matpower-8.1.0.2.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 185d441b98db9837acf8ec5dc2e6947203339b0a621cf22830b1c6837512544c
MD5 e8593bd43af7715ce95315a65ecf6a81
BLAKE2b-256 9ad3ba916f66acc5ea8f6a9fe6d0bf98e902658144a5605a176938331216caaf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page