Source code for andes.interop.matpower
"""
Interoperability with MATPOWER through ``matpower-pip``.
Please install the Python package ``matpower`` and configure MATLAB or Octave,
following the instructions at matpower-pip_.
To create a MATLAB/Octave instance, do:
.. code:: python
from andes.interop.matpower import start_instance
m = start_instance()
.. _matpower-pip: https://github.com/yasirroni/matpower-pip
"""
import logging
from functools import wraps
import andes
from andes.shared import Oct2PyError
logger = logging.getLogger(__name__)
[docs]def require_matpower(f):
"""
Decorator for functions that require matpower.
"""
@wraps(f)
def wrapper(*args, **kwds):
try:
from matpower import start_instance # NOQA
except ImportError:
raise ModuleNotFoundError("Package `matpower` needs to be manually installed.")
return f(*args, **kwds)
return wrapper
[docs]@require_matpower
def from_matpower(m, varname, system=None):
"""
Retrieve a MATPOWER mpc case from a MATLAB/Octave instance.
Parameters
----------
m : MATLAB/Octave instance
Instance from which to retrieve the MATPOWER case.
varname : str
Name of the variable in the MATPOWER MPC format to retrieve.
Returns
-------
:class:`~andes.system.System`
System from the mpc case. The system will not have been set up.
Examples
--------
To retrieve a case from MATPOWER from instance ``m``, do the following:
.. code:: python
from andes.interop.matpower import start_instance, to_matpower, from_matpower
system = from_matpower(m, 'mpc')
One can create an Excel file with dynamic data only and use the ``xlsx``
parser to load data into ``system``:
.. code:: python
from andes.io import xlsx
xlsx.read(system, andes.get_case('ieee14/ieee14_dyn_only.xlsx'))
The ``ieee14_dyn_only.xlsx`` is an example spreadsheet that only contains
dynamic components. One will need to create the ``idx`` correctly for
dynamic components to match these from the MATPOWER case. If not sure about
the indices, one can save the ANDES system to an Excel file, using:
.. code:: python
xlsx.write(system, 'system_static.xlsx')
"""
if m is None:
raise ImportError("MATPOWER is not installed or not properly configured.")
mpc = {}
mpc['baseMVA'] = m.eval(f'{varname}.baseMVA;')
mpc['version'] = m.eval(f'{varname}.version;')
mpc['bus'] = m.eval(f'{varname}.bus;')
mpc['gen'] = m.eval(f'{varname}.gen;')
mpc['branch'] = m.eval(f'{varname}.branch;')
try:
mpc['gencost'] = m.eval(f'{varname}.gencost;')
except Oct2PyError:
logger.debug("No gencost in mpc")
try:
mpc['bus_names'] = m.eval(f'{varname}.bus_names;')
except Oct2PyError:
logger.debug("No bus_name in mpc")
if system is None:
system = andes.System()
andes.io.matpower.mpc2system(mpc, system)
return system
[docs]@require_matpower
def to_matpower(m, varname, system):
"""
Send an ANDES case to a running MATLAB instance.
Parameters
----------
m : MATLAB/Octave instance
Instance to which to send the MATPOWER case.
varname : str
Name of the variable to store the mpc case in MATLAB/Octave.
system : :class:`~andes.system.System`
System whose power flow data to send to MATPOWER.
Examples
--------
The code below will create an IEEE 14-bus example system in ANDES, convert it to
MATPOWER's case, and send to the MATLAB/Octave instance.
.. code:: python
import andes
from andes.interop.matpower import (start_instance,
to_matpower, from_matpower)
m = start_instance()
ss = andes.system.example()
mpc = to_matpower(m, 'mpc', ss)
m.eval("runpf(mpc)")
mpc_out = m.pull("mpc") # retrieve the mpc case from MATLAB/Octave
"""
if m is None:
raise ImportError("MATPOWER is not installed or not properly configured.")
mpc = andes.io.matpower.system2mpc(system)
m.push(varname, mpc)
return mpc