diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 788fa95..37602b0 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -26,7 +26,7 @@ jobs:
build:
strategy:
matrix:
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
+ python-version: ["3.10", "3.14"]
platform: [octave]
os: [ubuntu-latest]
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 339c39a..0d16d05 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -7,7 +7,7 @@ jobs:
build:
strategy:
matrix:
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
platform: [octave]
os: [ubuntu-latest]
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4c20be2..ab189dc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,20 +5,19 @@
```sh
uv venv env --python 3.14
source env/bin/activate
-uv pip install pip
```
## packages
```sh
-pip install pru
+uv pip install pru
pru -r requirements-all.txt
```
## Install in development mode
```shell
-pip install -e ."[dev]"
+uv pip install -e ."[dev]"
```
## Pytest
diff --git a/matpowercaseframes/constants.py b/matpowercaseframes/constants.py
index 7fe3012..9ebf361 100644
--- a/matpowercaseframes/constants.py
+++ b/matpowercaseframes/constants.py
@@ -15,6 +15,7 @@
"dcline",
"dclinecost",
"case",
+ "reserves",
)
COLUMNS = {
@@ -112,6 +113,11 @@
"MU_QMINT",
"MU_QMAXT",
],
+ "reserves": {
+ "req": ["PREQ"],
+ "cost": ["C1"],
+ "qty": ["PQTY"],
+ },
"if": {
# negative 'BRANCHIDX' defines opposite direction
"map": ["IFNUM", "BRANCHIDX"],
diff --git a/matpowercaseframes/core.py b/matpowercaseframes/core.py
index fa71eb1..11f5517 100644
--- a/matpowercaseframes/core.py
+++ b/matpowercaseframes/core.py
@@ -20,6 +20,38 @@
MATPOWER_EXIST = False
+class ReservesFrames:
+ """A struct-like container for reserves data, similar to CaseFrames."""
+
+ def __init__(self, data=None):
+ """
+ Initialize ReservesFrames with optional data.
+
+ Args:
+ data (dict, optional): Dictionary containing reserves DataFrames.
+ Expected keys: 'zones', 'req', 'cost', 'qty'
+ """
+ self._attributes = []
+
+ if data is not None:
+ if isinstance(data, dict):
+ for key, value in data.items():
+ self.setattr(key, value)
+ else:
+ raise TypeError(f"ReservesFrames data must be a dict, got {type(data)}")
+
+ def setattr(self, name, value):
+ """Set attribute and track it in _attributes list."""
+ if name not in self._attributes:
+ self._attributes.append(name)
+ self.__setattr__(name, value)
+
+ @property
+ def attributes(self):
+ """List of attributes in this ReservesFrames object."""
+ return self._attributes
+
+
class CaseFrames:
def __init__(
self,
@@ -281,6 +313,9 @@ def _read_oct2py_struct(self, struct, allow_any_keys=False):
value = list_
elif attribute in ["bus_name", "branch_name", "gen_name"]:
value = pd.Index([name[0] for name in list_], name=attribute)
+ elif attribute in ["reserves"]:
+ dfs = reserves_data_to_dataframes(list_)
+ value = ReservesFrames(dfs)
else: # bus, branch, gen, gencost, dcline, dclinecost
list_ = np.atleast_2d(list_)
n_cols = list_.shape[1]
@@ -510,37 +545,52 @@ def _update_index(self, allow_any_keys=False):
attribute_data.set_index(attribute_name_data, drop=False, inplace=True)
except AttributeError:
attribute_data.set_index(
- pd.RangeIndex(1, len(attribute_data.index) + 1),
+ pd.RangeIndex(1, len(attribute_data.index) + 1, name=attribute),
drop=False,
inplace=True,
)
# gencost is optional
+ # NOTE: try except is better than checking hasattr for common possitive
try:
if "gen_name" in self._attributes:
self.gencost.set_index(self.gen_name, drop=False, inplace=True)
else:
self.gencost.set_index(
- pd.RangeIndex(1, len(self.gen.index) + 1), drop=False, inplace=True
+ pd.RangeIndex(1, len(self.gen.index) + 1, name="gen"),
+ drop=False,
+ inplace=True,
)
except AttributeError:
+ # for when self.gencost doesn't exist
pass
+ # NOTE: try hasattr is better than try except for common negative
+ if hasattr(self, "reserves"):
+ self.reserves.zones.columns = pd.RangeIndex(
+ start=1, stop=len(self.gen.index) + 1, name="gen"
+ )
+
# other attributes
if allow_any_keys:
- for attribute in self._attributes:
- if attribute in ["bus", "branch", "gen", "gencost"]:
- continue
- attribute_data = getattr(self, attribute)
- if isinstance(attribute_data, (pd.DataFrame, pd.Series)):
- # check if index is a RangeIndex
- if attribute_data.index.dtype == int:
- # replace the index with a new RangeIndex starting at 1
- attribute_data.set_index(
- pd.RangeIndex(start=1, stop=len(attribute_data) + 1),
- drop=False,
- inplace=True,
- )
+ self._update_index_any()
+
+ def _update_index_any(self):
+ for attribute in self._attributes:
+ if attribute in ["bus", "branch", "gen", "gencost", "reserves"]:
+ continue
+ attribute_data = getattr(self, attribute)
+ if isinstance(attribute_data, (pd.DataFrame, pd.Series)):
+ # check if index is a RangeIndex
+ if attribute_data.index.dtype == int:
+ # replace the index with a new RangeIndex starting at 1
+ attribute_data.set_index(
+ pd.RangeIndex(
+ start=1, stop=len(attribute_data) + 1, name=attribute
+ ),
+ drop=False,
+ inplace=True,
+ )
def infer_numpy(self):
"""
@@ -608,6 +658,10 @@ def reset_index(self):
)
self.gen["GEN_BUS"] = self.gen["GEN_BUS"].replace(bus_map)
+ # TODO:
+ # Since mpc.reserves.zones columns use cf.gen.index, don't forget to update
+ # the columns of mpc.reserves.zones if exists.
+
def add_schema_case(self, F=None):
# add case to follow casefromat/schema
# !WARNING:
@@ -806,3 +860,42 @@ def to_schema(self, path, prefix="", suffix=""):
if "case" not in self._attributes:
self.add_schema_case()
self.to_csv(path, prefix=prefix, suffix=suffix)
+
+
+def reserves_data_to_dataframes(reserves):
+ """
+ Convert all mpc.reserves struct data to DataFrames.
+
+ Args:
+ reserves: Octave struct or dictionary of mpc.reserves object from MATPOWER
+
+ Returns:
+ Dictionary containing:
+ - 'zones': Reserve zones DataFrame
+ - 'req': Reserve requirements DataFrame
+ - 'cost': Reserve costs DataFrame (if exists)
+ - 'qty': Reserve quantities DataFrame (if exists)
+ """
+ dfs = {}
+ n_zones, n_gens = reserves.zones.shape
+ dfs["zones"] = pd.DataFrame(
+ reserves.zones,
+ index=pd.RangeIndex(start=1, stop=n_zones + 1, name="zone"),
+ columns=pd.RangeIndex(start=1, stop=n_gens + 1, name="gen"),
+ )
+ zone_sum = dfs["zones"].sum(axis=0)
+ idx_gen_with_reserves = zone_sum[zone_sum > 0].index
+ dfs["req"] = pd.DataFrame(
+ reserves.req,
+ index=pd.RangeIndex(start=1, stop=n_zones + 1, name="zone"),
+ columns=["PREQ"],
+ )
+ if hasattr(reserves, "cost"):
+ dfs["cost"] = pd.DataFrame(
+ reserves.cost, index=idx_gen_with_reserves, columns=["C1"]
+ )
+ if hasattr(reserves, "qty"):
+ dfs["qty"] = pd.DataFrame(
+ reserves.qty, index=idx_gen_with_reserves, columns=["PQTY"]
+ )
+ return dfs
diff --git a/notebooks/load_case9.ipynb b/notebooks/load_case9.ipynb
new file mode 100644
index 0000000..93f3870
--- /dev/null
+++ b/notebooks/load_case9.ipynb
@@ -0,0 +1,1538 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The autoreload extension is already loaded. To reload it, use:\n",
+ " %reload_ext autoreload\n"
+ ]
+ }
+ ],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from matpower import start_instance\n",
+ "\n",
+ "from matpowercaseframes import CaseFrames"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = start_instance()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " F_BUS | \n",
+ " T_BUS | \n",
+ " BR_R | \n",
+ " BR_X | \n",
+ " BR_B | \n",
+ " RATE_A | \n",
+ " RATE_B | \n",
+ " RATE_C | \n",
+ " TAP | \n",
+ " SHIFT | \n",
+ " BR_STATUS | \n",
+ " ANGMIN | \n",
+ " ANGMAX | \n",
+ "
\n",
+ " \n",
+ " | branch | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 4 | \n",
+ " 0.0000 | \n",
+ " 0.0576 | \n",
+ " 0.000 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 0.0170 | \n",
+ " 0.0920 | \n",
+ " 0.158 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5 | \n",
+ " 6 | \n",
+ " 0.0390 | \n",
+ " 0.1700 | \n",
+ " 0.358 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 0.0000 | \n",
+ " 0.0586 | \n",
+ " 0.000 | \n",
+ " 300 | \n",
+ " 300 | \n",
+ " 300 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
+ " 6 | \n",
+ " 7 | \n",
+ " 0.0119 | \n",
+ " 0.1008 | \n",
+ " 0.209 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " 7 | \n",
+ " 8 | \n",
+ " 0.0085 | \n",
+ " 0.0720 | \n",
+ " 0.149 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 7 | \n",
+ " 8 | \n",
+ " 2 | \n",
+ " 0.0000 | \n",
+ " 0.0625 | \n",
+ " 0.000 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 8 | \n",
+ " 8 | \n",
+ " 9 | \n",
+ " 0.0320 | \n",
+ " 0.1610 | \n",
+ " 0.306 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 9 | \n",
+ " 9 | \n",
+ " 4 | \n",
+ " 0.0100 | \n",
+ " 0.0850 | \n",
+ " 0.176 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " F_BUS T_BUS BR_R BR_X BR_B RATE_A RATE_B RATE_C TAP \\\n",
+ "branch \n",
+ "1 1 4 0.0000 0.0576 0.000 250 250 250 0 \n",
+ "2 4 5 0.0170 0.0920 0.158 250 250 250 0 \n",
+ "3 5 6 0.0390 0.1700 0.358 150 150 150 0 \n",
+ "4 3 6 0.0000 0.0586 0.000 300 300 300 0 \n",
+ "5 6 7 0.0119 0.1008 0.209 150 150 150 0 \n",
+ "6 7 8 0.0085 0.0720 0.149 250 250 250 0 \n",
+ "7 8 2 0.0000 0.0625 0.000 250 250 250 0 \n",
+ "8 8 9 0.0320 0.1610 0.306 250 250 250 0 \n",
+ "9 9 4 0.0100 0.0850 0.176 250 250 250 0 \n",
+ "\n",
+ " SHIFT BR_STATUS ANGMIN ANGMAX \n",
+ "branch \n",
+ "1 0 1 -360 360 \n",
+ "2 0 1 -360 360 \n",
+ "3 0 1 -360 360 \n",
+ "4 0 1 -360 360 \n",
+ "5 0 1 -360 360 \n",
+ "6 0 1 -360 360 \n",
+ "7 0 1 -360 360 \n",
+ "8 0 1 -360 360 \n",
+ "9 0 1 -360 360 "
+ ]
+ },
+ "execution_count": 26,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "CASE_NAME = \"case9.m\"\n",
+ "cf_9 = CaseFrames(CASE_NAME)\n",
+ "cf_9.infer_numpy()\n",
+ "cf_9.branch"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " F_BUS | \n",
+ " T_BUS | \n",
+ " BR_R | \n",
+ " BR_X | \n",
+ " BR_B | \n",
+ " RATE_A | \n",
+ " RATE_B | \n",
+ " RATE_C | \n",
+ " TAP | \n",
+ " SHIFT | \n",
+ " BR_STATUS | \n",
+ " ANGMIN | \n",
+ " ANGMAX | \n",
+ "
\n",
+ " \n",
+ " | branch | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 4 | \n",
+ " 0.0000 | \n",
+ " 0.0576 | \n",
+ " 0.000 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 0.0170 | \n",
+ " 0.0920 | \n",
+ " 0.158 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5 | \n",
+ " 6 | \n",
+ " 0.0390 | \n",
+ " 0.1700 | \n",
+ " 0.358 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 0.0000 | \n",
+ " 0.0586 | \n",
+ " 0.000 | \n",
+ " 300 | \n",
+ " 300 | \n",
+ " 300 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
+ " 6 | \n",
+ " 7 | \n",
+ " 0.0119 | \n",
+ " 0.1008 | \n",
+ " 0.209 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " 7 | \n",
+ " 8 | \n",
+ " 0.0085 | \n",
+ " 0.0720 | \n",
+ " 0.149 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 7 | \n",
+ " 8 | \n",
+ " 2 | \n",
+ " 0.0000 | \n",
+ " 0.0625 | \n",
+ " 0.000 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 8 | \n",
+ " 8 | \n",
+ " 9 | \n",
+ " 0.0320 | \n",
+ " 0.1610 | \n",
+ " 0.306 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 9 | \n",
+ " 9 | \n",
+ " 4 | \n",
+ " 0.0100 | \n",
+ " 0.0850 | \n",
+ " 0.176 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " F_BUS T_BUS BR_R BR_X BR_B RATE_A RATE_B RATE_C TAP \\\n",
+ "branch \n",
+ "1 1 4 0.0000 0.0576 0.000 250 250 250 0 \n",
+ "2 4 5 0.0170 0.0920 0.158 250 250 250 0 \n",
+ "3 5 6 0.0390 0.1700 0.358 150 150 150 0 \n",
+ "4 3 6 0.0000 0.0586 0.000 300 300 300 0 \n",
+ "5 6 7 0.0119 0.1008 0.209 150 150 150 0 \n",
+ "6 7 8 0.0085 0.0720 0.149 250 250 250 0 \n",
+ "7 8 2 0.0000 0.0625 0.000 250 250 250 0 \n",
+ "8 8 9 0.0320 0.1610 0.306 250 250 250 0 \n",
+ "9 9 4 0.0100 0.0850 0.176 250 250 250 0 \n",
+ "\n",
+ " SHIFT BR_STATUS ANGMIN ANGMAX \n",
+ "branch \n",
+ "1 0 1 -360 360 \n",
+ "2 0 1 -360 360 \n",
+ "3 0 1 -360 360 \n",
+ "4 0 1 -360 360 \n",
+ "5 0 1 -360 360 \n",
+ "6 0 1 -360 360 \n",
+ "7 0 1 -360 360 \n",
+ "8 0 1 -360 360 \n",
+ "9 0 1 -360 360 "
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "CASE_NAME = \"case9.m\"\n",
+ "cf_9_lc = CaseFrames(CASE_NAME, load_case_engine=m)\n",
+ "cf_9_lc.infer_numpy()\n",
+ "cf_9_lc.branch"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "MATPOWER Version 8.1, 12-Jul-2025\n",
+ "Power Flow -- AC-polar-power formulation\n",
+ "\n",
+ "Newton's method converged in 4 iterations.\n",
+ "PF successful\n",
+ "\n",
+ "Converged in 0.09 seconds\n",
+ "================================================================================\n",
+ "| System Summary |\n",
+ "================================================================================\n",
+ "\n",
+ "How many? How much? P (MW) Q (MVAr)\n",
+ "--------------------- ------------------- ------------- -----------------\n",
+ "Buses 9 Total Gen Capacity 820.0 -900.0 to 900.0\n",
+ "Generators 3 On-line Capacity 820.0 -900.0 to 900.0\n",
+ "Committed Gens 3 Generation (actual) 319.6 22.8\n",
+ "Loads 3 Load 315.0 115.0\n",
+ " Fixed 3 Fixed 315.0 115.0\n",
+ " Dispatchable 0 Dispatchable -0.0 of -0.0 -0.0\n",
+ "Shunts 0 Shunt (inj) -0.0 0.0\n",
+ "Branches 9 Losses (I^2 * Z) 4.64 48.38\n",
+ "Transformers 0 Branch Charging (inj) - 140.5\n",
+ "Inter-ties 0 Total Inter-tie Flow 0.0 0.0\n",
+ "Areas 1\n",
+ "\n",
+ " Minimum Maximum\n",
+ " ------------------------- --------------------------------\n",
+ "Voltage Magnitude 0.996 p.u. @ bus 9 1.040 p.u. @ bus 1\n",
+ "Voltage Angle -3.99 deg @ bus 9 9.28 deg @ bus 2\n",
+ "P Losses (I^2*R) - 2.30 MW @ line 8-9\n",
+ "Q Losses (I^2*X) - 15.83 MVAr @ line 8-2\n",
+ "\n",
+ "================================================================================\n",
+ "| Bus Data |\n",
+ "================================================================================\n",
+ " Bus Voltage Generation Load\n",
+ " # Mag(pu) Ang(deg) P (MW) Q (MVAr) P (MW) Q (MVAr)\n",
+ "----- ------- -------- -------- -------- -------- --------\n",
+ " 1 1.040 0.000* 71.64 27.05 - -\n",
+ " 2 1.025 9.280 163.00 6.65 - -\n",
+ " 3 1.025 4.665 85.00 -10.86 - -\n",
+ " 4 1.026 -2.217 - - - -\n",
+ " 5 1.013 -3.687 - - 90.00 30.00\n",
+ " 6 1.032 1.967 - - - -\n",
+ " 7 1.016 0.728 - - 100.00 35.00\n",
+ " 8 1.026 3.720 - - - -\n",
+ " 9 0.996 -3.989 - - 125.00 50.00\n",
+ " -------- -------- -------- --------\n",
+ " Total: 319.64 22.84 315.00 115.00\n",
+ "\n",
+ "================================================================================\n",
+ "| Branch Data |\n",
+ "================================================================================\n",
+ "Brnch From To From Bus Injection To Bus Injection Loss (I^2 * Z)\n",
+ " # Bus Bus P (MW) Q (MVAr) P (MW) Q (MVAr) P (MW) Q (MVAr)\n",
+ "----- ----- ----- -------- -------- -------- -------- -------- --------\n",
+ " 1 1 4 71.64 27.05 -71.64 -23.92 0.000 3.12\n",
+ " 2 4 5 30.70 1.03 -30.54 -16.54 0.166 0.90\n",
+ " 3 5 6 -59.46 -13.46 60.82 -18.07 1.354 5.90\n",
+ " 4 3 6 85.00 -10.86 -85.00 14.96 0.000 4.10\n",
+ " 5 6 7 24.18 3.12 -24.10 -24.30 0.088 0.75\n",
+ " 6 7 8 -75.90 -10.70 76.38 -0.80 0.475 4.03\n",
+ " 7 8 2 -163.00 9.18 163.00 6.65 0.000 15.83\n",
+ " 8 8 9 86.62 -8.38 -84.32 -11.31 2.300 11.57\n",
+ " 9 9 4 -40.68 -38.69 40.94 22.89 0.258 2.19\n",
+ " -------- --------\n",
+ " Total: 4.641 48.38\n"
+ ]
+ }
+ ],
+ "source": [
+ "mpc = cf_9.to_mpc()\n",
+ "_ = m.runpf(mpc)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "MATPOWER Version 8.1, 12-Jul-2025\n",
+ "Power Flow -- AC-polar-power formulation\n",
+ "\n",
+ "Newton's method converged in 4 iterations.\n",
+ "PF successful\n",
+ "\n",
+ "Converged in 0.04 seconds\n",
+ "================================================================================\n",
+ "| System Summary |\n",
+ "================================================================================\n",
+ "\n",
+ "How many? How much? P (MW) Q (MVAr)\n",
+ "--------------------- ------------------- ------------- -----------------\n",
+ "Buses 9 Total Gen Capacity 820.0 -900.0 to 900.0\n",
+ "Generators 3 On-line Capacity 820.0 -900.0 to 900.0\n",
+ "Committed Gens 3 Generation (actual) 319.6 22.8\n",
+ "Loads 3 Load 315.0 115.0\n",
+ " Fixed 3 Fixed 315.0 115.0\n",
+ " Dispatchable 0 Dispatchable -0.0 of -0.0 -0.0\n",
+ "Shunts 0 Shunt (inj) -0.0 0.0\n",
+ "Branches 9 Losses (I^2 * Z) 4.64 48.38\n",
+ "Transformers 0 Branch Charging (inj) - 140.5\n",
+ "Inter-ties 0 Total Inter-tie Flow 0.0 0.0\n",
+ "Areas 1\n",
+ "\n",
+ " Minimum Maximum\n",
+ " ------------------------- --------------------------------\n",
+ "Voltage Magnitude 0.996 p.u. @ bus 9 1.040 p.u. @ bus 1\n",
+ "Voltage Angle -3.99 deg @ bus 9 9.28 deg @ bus 2\n",
+ "P Losses (I^2*R) - 2.30 MW @ line 8-9\n",
+ "Q Losses (I^2*X) - 15.83 MVAr @ line 8-2\n",
+ "\n",
+ "================================================================================\n",
+ "| Bus Data |\n",
+ "================================================================================\n",
+ " Bus Voltage Generation Load\n",
+ " # Mag(pu) Ang(deg) P (MW) Q (MVAr) P (MW) Q (MVAr)\n",
+ "----- ------- -------- -------- -------- -------- --------\n",
+ " 1 1.040 0.000* 71.64 27.05 - -\n",
+ " 2 1.025 9.280 163.00 6.65 - -\n",
+ " 3 1.025 4.665 85.00 -10.86 - -\n",
+ " 4 1.026 -2.217 - - - -\n",
+ " 5 1.013 -3.687 - - 90.00 30.00\n",
+ " 6 1.032 1.967 - - - -\n",
+ " 7 1.016 0.728 - - 100.00 35.00\n",
+ " 8 1.026 3.720 - - - -\n",
+ " 9 0.996 -3.989 - - 125.00 50.00\n",
+ " -------- -------- -------- --------\n",
+ " Total: 319.64 22.84 315.00 115.00\n",
+ "\n",
+ "================================================================================\n",
+ "| Branch Data |\n",
+ "================================================================================\n",
+ "Brnch From To From Bus Injection To Bus Injection Loss (I^2 * Z)\n",
+ " # Bus Bus P (MW) Q (MVAr) P (MW) Q (MVAr) P (MW) Q (MVAr)\n",
+ "----- ----- ----- -------- -------- -------- -------- -------- --------\n",
+ " 1 1 4 71.64 27.05 -71.64 -23.92 0.000 3.12\n",
+ " 2 4 5 30.70 1.03 -30.54 -16.54 0.166 0.90\n",
+ " 3 5 6 -59.46 -13.46 60.82 -18.07 1.354 5.90\n",
+ " 4 3 6 85.00 -10.86 -85.00 14.96 0.000 4.10\n",
+ " 5 6 7 24.18 3.12 -24.10 -24.30 0.088 0.75\n",
+ " 6 7 8 -75.90 -10.70 76.38 -0.80 0.475 4.03\n",
+ " 7 8 2 -163.00 9.18 163.00 6.65 0.000 15.83\n",
+ " 8 8 9 86.62 -8.38 -84.32 -11.31 2.300 11.57\n",
+ " 9 9 4 -40.68 -38.69 40.94 22.89 0.258 2.19\n",
+ " -------- --------\n",
+ " Total: 4.641 48.38\n"
+ ]
+ }
+ ],
+ "source": [
+ "mpc = cf_9_lc.to_mpc()\n",
+ "_ = m.runpf(mpc)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'version'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'2'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'baseMVA'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "100"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'bus'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " BUS_I | \n",
+ " BUS_TYPE | \n",
+ " PD | \n",
+ " QD | \n",
+ " GS | \n",
+ " BS | \n",
+ " BUS_AREA | \n",
+ " VM | \n",
+ " VA | \n",
+ " BASE_KV | \n",
+ " ZONE | \n",
+ " VMAX | \n",
+ " VMIN | \n",
+ "
\n",
+ " \n",
+ " | bus | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 3 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 4 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
+ " 5 | \n",
+ " 1 | \n",
+ " 90 | \n",
+ " 30 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " 6 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 7 | \n",
+ " 7 | \n",
+ " 1 | \n",
+ " 100 | \n",
+ " 35 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 8 | \n",
+ " 8 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ " | 9 | \n",
+ " 9 | \n",
+ " 1 | \n",
+ " 125 | \n",
+ " 50 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 345 | \n",
+ " 1 | \n",
+ " 1.1 | \n",
+ " 0.9 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " BUS_I BUS_TYPE PD QD GS BS BUS_AREA VM VA BASE_KV ZONE VMAX \\\n",
+ "bus \n",
+ "1 1 3 0 0 0 0 1 1 0 345 1 1.1 \n",
+ "2 2 2 0 0 0 0 1 1 0 345 1 1.1 \n",
+ "3 3 2 0 0 0 0 1 1 0 345 1 1.1 \n",
+ "4 4 1 0 0 0 0 1 1 0 345 1 1.1 \n",
+ "5 5 1 90 30 0 0 1 1 0 345 1 1.1 \n",
+ "6 6 1 0 0 0 0 1 1 0 345 1 1.1 \n",
+ "7 7 1 100 35 0 0 1 1 0 345 1 1.1 \n",
+ "8 8 1 0 0 0 0 1 1 0 345 1 1.1 \n",
+ "9 9 1 125 50 0 0 1 1 0 345 1 1.1 \n",
+ "\n",
+ " VMIN \n",
+ "bus \n",
+ "1 0.9 \n",
+ "2 0.9 \n",
+ "3 0.9 \n",
+ "4 0.9 \n",
+ "5 0.9 \n",
+ "6 0.9 \n",
+ "7 0.9 \n",
+ "8 0.9 \n",
+ "9 0.9 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'gen'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " GEN_BUS | \n",
+ " PG | \n",
+ " QG | \n",
+ " QMAX | \n",
+ " QMIN | \n",
+ " VG | \n",
+ " MBASE | \n",
+ " GEN_STATUS | \n",
+ " PMAX | \n",
+ " PMIN | \n",
+ " ... | \n",
+ " PC2 | \n",
+ " QC1MIN | \n",
+ " QC1MAX | \n",
+ " QC2MIN | \n",
+ " QC2MAX | \n",
+ " RAMP_AGC | \n",
+ " RAMP_10 | \n",
+ " RAMP_30 | \n",
+ " RAMP_Q | \n",
+ " APF | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 72.3 | \n",
+ " 27.03 | \n",
+ " 300 | \n",
+ " -300 | \n",
+ " 1.040 | \n",
+ " 100 | \n",
+ " 1 | \n",
+ " 250 | \n",
+ " 10 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2 | \n",
+ " 163.0 | \n",
+ " 6.54 | \n",
+ " 300 | \n",
+ " -300 | \n",
+ " 1.025 | \n",
+ " 100 | \n",
+ " 1 | \n",
+ " 300 | \n",
+ " 10 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 3 | \n",
+ " 85.0 | \n",
+ " -10.95 | \n",
+ " 300 | \n",
+ " -300 | \n",
+ " 1.025 | \n",
+ " 100 | \n",
+ " 1 | \n",
+ " 270 | \n",
+ " 10 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
3 rows × 21 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " GEN_BUS PG QG QMAX QMIN VG MBASE GEN_STATUS PMAX PMIN \\\n",
+ "gen \n",
+ "1 1 72.3 27.03 300 -300 1.040 100 1 250 10 \n",
+ "2 2 163.0 6.54 300 -300 1.025 100 1 300 10 \n",
+ "3 3 85.0 -10.95 300 -300 1.025 100 1 270 10 \n",
+ "\n",
+ " ... PC2 QC1MIN QC1MAX QC2MIN QC2MAX RAMP_AGC RAMP_10 RAMP_30 \\\n",
+ "gen ... \n",
+ "1 ... 0 0 0 0 0 0 0 0 \n",
+ "2 ... 0 0 0 0 0 0 0 0 \n",
+ "3 ... 0 0 0 0 0 0 0 0 \n",
+ "\n",
+ " RAMP_Q APF \n",
+ "gen \n",
+ "1 0 0 \n",
+ "2 0 0 \n",
+ "3 0 0 \n",
+ "\n",
+ "[3 rows x 21 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'branch'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " F_BUS | \n",
+ " T_BUS | \n",
+ " BR_R | \n",
+ " BR_X | \n",
+ " BR_B | \n",
+ " RATE_A | \n",
+ " RATE_B | \n",
+ " RATE_C | \n",
+ " TAP | \n",
+ " SHIFT | \n",
+ " BR_STATUS | \n",
+ " ANGMIN | \n",
+ " ANGMAX | \n",
+ "
\n",
+ " \n",
+ " | branch | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 4 | \n",
+ " 0.0000 | \n",
+ " 0.0576 | \n",
+ " 0.000 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 0.0170 | \n",
+ " 0.0920 | \n",
+ " 0.158 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5 | \n",
+ " 6 | \n",
+ " 0.0390 | \n",
+ " 0.1700 | \n",
+ " 0.358 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 0.0000 | \n",
+ " 0.0586 | \n",
+ " 0.000 | \n",
+ " 300 | \n",
+ " 300 | \n",
+ " 300 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
+ " 6 | \n",
+ " 7 | \n",
+ " 0.0119 | \n",
+ " 0.1008 | \n",
+ " 0.209 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 150 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " 7 | \n",
+ " 8 | \n",
+ " 0.0085 | \n",
+ " 0.0720 | \n",
+ " 0.149 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 7 | \n",
+ " 8 | \n",
+ " 2 | \n",
+ " 0.0000 | \n",
+ " 0.0625 | \n",
+ " 0.000 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 8 | \n",
+ " 8 | \n",
+ " 9 | \n",
+ " 0.0320 | \n",
+ " 0.1610 | \n",
+ " 0.306 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ " | 9 | \n",
+ " 9 | \n",
+ " 4 | \n",
+ " 0.0100 | \n",
+ " 0.0850 | \n",
+ " 0.176 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 250 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1 | \n",
+ " -360 | \n",
+ " 360 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " F_BUS T_BUS BR_R BR_X BR_B RATE_A RATE_B RATE_C TAP \\\n",
+ "branch \n",
+ "1 1 4 0.0000 0.0576 0.000 250 250 250 0 \n",
+ "2 4 5 0.0170 0.0920 0.158 250 250 250 0 \n",
+ "3 5 6 0.0390 0.1700 0.358 150 150 150 0 \n",
+ "4 3 6 0.0000 0.0586 0.000 300 300 300 0 \n",
+ "5 6 7 0.0119 0.1008 0.209 150 150 150 0 \n",
+ "6 7 8 0.0085 0.0720 0.149 250 250 250 0 \n",
+ "7 8 2 0.0000 0.0625 0.000 250 250 250 0 \n",
+ "8 8 9 0.0320 0.1610 0.306 250 250 250 0 \n",
+ "9 9 4 0.0100 0.0850 0.176 250 250 250 0 \n",
+ "\n",
+ " SHIFT BR_STATUS ANGMIN ANGMAX \n",
+ "branch \n",
+ "1 0 1 -360 360 \n",
+ "2 0 1 -360 360 \n",
+ "3 0 1 -360 360 \n",
+ "4 0 1 -360 360 \n",
+ "5 0 1 -360 360 \n",
+ "6 0 1 -360 360 \n",
+ "7 0 1 -360 360 \n",
+ "8 0 1 -360 360 \n",
+ "9 0 1 -360 360 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'gencost'"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " MODEL | \n",
+ " STARTUP | \n",
+ " SHUTDOWN | \n",
+ " NCOST | \n",
+ " C2 | \n",
+ " C1 | \n",
+ " C0 | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 2 | \n",
+ " 1500 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 0.1100 | \n",
+ " 5.0 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2 | \n",
+ " 2000 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 0.0850 | \n",
+ " 1.2 | \n",
+ " 600 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 2 | \n",
+ " 3000 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " 0.1225 | \n",
+ " 1.0 | \n",
+ " 335 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " MODEL STARTUP SHUTDOWN NCOST C2 C1 C0\n",
+ "gen \n",
+ "1 2 1500 0 3 0.1100 5.0 150\n",
+ "2 2 2000 0 3 0.0850 1.2 600\n",
+ "3 2 3000 0 3 0.1225 1.0 335"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "for attr in cf_9.attributes:\n",
+ " display(attr, getattr(cf_9, attr))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m.exit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "env",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.14.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/notebooks/load_most_ex_case3a.ipynb b/notebooks/load_most_ex_case3a.ipynb
new file mode 100644
index 0000000..126ee8e
--- /dev/null
+++ b/notebooks/load_most_ex_case3a.ipynb
@@ -0,0 +1,1835 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "eae79aa2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# # install octave\n",
+ "# !sudo apt-get -qq update\n",
+ "# !sudo apt-get -qq install octave octave-signal liboctave-dev\n",
+ "\n",
+ "# # install oct2py that compatible with colab\n",
+ "# import os\n",
+ "\n",
+ "# from pkg_resources import get_distribution\n",
+ "\n",
+ "# os.system(\n",
+ "# f\"pip install -qq\"\n",
+ "# f\" ipykernel=={get_distribution('ipykernel').version}\"\n",
+ "# f\" ipython=={get_distribution('ipython').version}\"\n",
+ "# f\" tornado=={get_distribution('tornado').version}\"\n",
+ "# f\" oct2py\"\n",
+ "# )\n",
+ "\n",
+ "# # install packages\n",
+ "# !pip install -qq matpower matpowercaseframes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "5bc86ee4",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "oct2py version: 5.8.0\n",
+ "matpower version: 8.1.0.2.2.3\n"
+ ]
+ }
+ ],
+ "source": [
+ "import matpower\n",
+ "import oct2py\n",
+ "\n",
+ "print(f\"oct2py version: {oct2py.__version__}\")\n",
+ "print(f\"matpower version: {matpower.__version__}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "3116b86b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "\n",
+ "import pandas as pd\n",
+ "from matpower import path_matpower, start_instance\n",
+ "\n",
+ "from matpowercaseframes import CaseFrames"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "10fd2d91",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "path_most_ex_cases = os.path.join(path_matpower, \"most/examples\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "7e230eb0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = start_instance()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "6d93dd06",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'version': '2',\n",
+ " 'baseMVA': 100.0,\n",
+ " 'bus': array([[ 1. , 3. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95],\n",
+ " [ 2. , 2. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95],\n",
+ " [ 3. , 2. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95]]),\n",
+ " 'gen': array([[ 1., 125., 0., 25., -25., 1., 100., 1., 200.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 250.,\n",
+ " 250., 0., 0.],\n",
+ " [ 1., 125., 0., 25., -25., 1., 100., 1., 200.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 250.,\n",
+ " 250., 0., 0.],\n",
+ " [ 2., 200., 0., 50., -50., 1., 100., 1., 500.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 600.,\n",
+ " 600., 0., 0.],\n",
+ " [ 3., -450., 0., 0., 0., 1., 100., 1., 0.,\n",
+ " -450., 0., 0., 0., 0., 0., 0., 0., 500.,\n",
+ " 500., 0., 0.]]),\n",
+ " 'branch': array([[ 1.0e+00, 2.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 3.0e+02,\n",
+ " 3.0e+02, 3.0e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+00, 3.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 2.4e+02,\n",
+ " 2.4e+02, 2.4e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.0e+00, 3.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 3.0e+02,\n",
+ " 3.0e+02, 3.0e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02]]),\n",
+ " 'gencost': array([[2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 0.e+00, 1.e+03, 0.e+00]]),\n",
+ " 'reserves': {'zones': array([[1., 1., 1., 0.]]),\n",
+ " 'req': 150.0,\n",
+ " 'cost': array([[1.],\n",
+ " [3.],\n",
+ " [5.]]),\n",
+ " 'qty': array([[100.],\n",
+ " [100.],\n",
+ " [200.]])}}"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# load single most example case\n",
+ "mpc = m.loadcase(os.path.join(path_most_ex_cases, \"ex_case3a.m\"))\n",
+ "mpc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "b6bbbce4",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys(['version', 'baseMVA', 'bus', 'gen', 'branch', 'gencost', 'reserves'])"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpc.keys()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "ea66211a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from matpowercaseframes.constants import COLUMNS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "a911808f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys(['bus', 'gen', 'branch', 'dcline', 'if', 'gencost', 'dclinecost', 'bus_name', 'branch_name', 'gen_name', 'case'])"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "COLUMNS.keys()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "f63470e2",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'baseMVA', 'reserves', 'version'}"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpc_keys = set(mpc.keys())\n",
+ "columns_keys = set(COLUMNS.keys())\n",
+ "missing_keys = mpc_keys - columns_keys\n",
+ "missing_keys"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "8577fe89",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'zones': array([[1., 1., 1., 0.]]),\n",
+ " 'req': 150.0,\n",
+ " 'cost': array([[1.],\n",
+ " [3.],\n",
+ " [5.]]),\n",
+ " 'qty': array([[100.],\n",
+ " [100.],\n",
+ " [200.]])}"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpc.reserves"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f46abaea",
+ "metadata": {},
+ "source": [
+ "Reserve Data\n",
+ "\n",
+ "reserve zones, element i, j is 1 if gen j is in zone i, 0 otherwise.\n",
+ "dimension (zone, gen)\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.zones = [\n",
+ "\t1\t1\t1\t0;\n",
+ "];\n",
+ "```\n",
+ "\n",
+ "Mapped to `DataFrame` with index follows zone index (from 1), and columns follows\n",
+ "generator index (cf.gen.index)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "aaf701d3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n_zones, n_gens = mpc.reserves.zones.shape"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "370d5e7c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | gen | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ "gen 1 2 3 4\n",
+ "zone \n",
+ "1 1.0 1.0 1.0 0.0"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_zone = pd.DataFrame(\n",
+ " mpc.reserves.zones,\n",
+ " index=pd.RangeIndex(start=1, stop=n_zones + 1, name=\"zone\"),\n",
+ " columns=pd.RangeIndex(start=1, stop=n_gens + 1, name=\"gen\"),\n",
+ ")\n",
+ "df_reserves_zone"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ded7b892",
+ "metadata": {},
+ "source": [
+ "reserve requirements for each zone in MW\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.req = [60; 20];\n",
+ "```\n",
+ "\n",
+ "or\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.req = 150;\n",
+ "```\n",
+ "\n",
+ "Mapped to `DataFrame` with index follows zone index (from 1), and single column 'PREQ'."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "b817c54f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PREQ | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 150.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PREQ\n",
+ "zone \n",
+ "1 150.0"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_req = pd.DataFrame(\n",
+ " mpc.reserves.req,\n",
+ " index=pd.RangeIndex(start=1, stop=n_zones + 1, name=\"zone\"),\n",
+ " columns=[\"PREQ\"],\n",
+ ")\n",
+ "df_reserves_req"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "82107817",
+ "metadata": {},
+ "source": [
+ "reserve costs in $/MW for each gen that belongs to at least 1 zone. (same order as gens,\n",
+ "but skipping any gen that does not belong to any zone)\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.cost = [\t1.9;\t2;\t3;\t4;\t5;\t5.5\t];\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "fb21239e",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "RangeIndex(start=1, stop=4, step=1, name='gen')"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_zone_sum = df_reserves_zone.sum(axis=0)\n",
+ "idx_gen_with_reserves = df_reserves_zone_sum[df_reserves_zone_sum > 0].index\n",
+ "idx_gen_with_reserves"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "ebe8a6de",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " C1 | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 3.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " C1\n",
+ "gen \n",
+ "1 1.0\n",
+ "2 3.0\n",
+ "3 5.0"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_cost = pd.DataFrame(\n",
+ " mpc.reserves.cost, index=idx_gen_with_reserves, columns=[\"C1\"]\n",
+ ")\n",
+ "df_reserves_cost"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a2b1e889",
+ "metadata": {},
+ "source": [
+ "max reserve quantities for each gen that belongs to at least 1 zone. (same order as\n",
+ "gens, but skipping any gen that does not belong to any zone)\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.qty = [\t25;\t25;\t25;\t25;\t25;\t25\t];\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "4e486ee1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PQTY | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 100.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 100.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 200.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PQTY\n",
+ "gen \n",
+ "1 100.0\n",
+ "2 100.0\n",
+ "3 200.0"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_qty = pd.DataFrame(\n",
+ " mpc.reserves.qty, index=idx_gen_with_reserves, columns=[\"PQTY\"]\n",
+ ")\n",
+ "df_reserves_qty"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5389d132",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def reserves_data_to_dataframes(reserves):\n",
+ " \"\"\"\n",
+ " Convert all mpc.reserves data to DataFrames.\n",
+ "\n",
+ " Args:\n",
+ " reserves: mpc.reserves object from MATPOWER\n",
+ "\n",
+ " Returns:\n",
+ " Dictionary containing:\n",
+ " - 'zones': Reserve zones DataFrame\n",
+ " - 'req': Reserve requirements DataFrame\n",
+ " - 'cost': Reserve costs DataFrame (if exists)\n",
+ " - 'qty': Reserve quantities DataFrame (if exists)\n",
+ " \"\"\"\n",
+ " dfs = {}\n",
+ " n_zones, n_gens = reserves.zones.shape\n",
+ " dfs[\"zones\"] = pd.DataFrame(\n",
+ " reserves.zones,\n",
+ " index=pd.RangeIndex(start=1, stop=n_zones + 1, name=\"zone\"),\n",
+ " columns=pd.RangeIndex(start=1, stop=n_gens + 1, name=\"gen\"),\n",
+ " )\n",
+ " zone_sum = dfs[\"zones\"].sum(axis=0)\n",
+ " idx_gen_with_reserves = zone_sum[zone_sum > 0].index\n",
+ " dfs[\"req\"] = pd.DataFrame(\n",
+ " reserves.req,\n",
+ " index=pd.RangeIndex(start=1, stop=n_zones + 1, name=\"zone\"),\n",
+ " columns=[\"PREQ\"],\n",
+ " )\n",
+ " if hasattr(reserves, \"cost\"):\n",
+ " dfs[\"cost\"] = pd.DataFrame(\n",
+ " reserves.cost, index=idx_gen_with_reserves, columns=[\"C1\"]\n",
+ " )\n",
+ " if hasattr(reserves, \"qty\"):\n",
+ " dfs[\"qty\"] = pd.DataFrame(\n",
+ " reserves.qty, index=idx_gen_with_reserves, columns=[\"PQTY\"]\n",
+ " )\n",
+ "\n",
+ " return dfs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a686e0ab",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "zones\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | gen | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 6 | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ "gen 1 2 3 4 5 6\n",
+ "zone \n",
+ "1 1.0 1.0 1.0 0.0 0.0 0.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "req\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PREQ | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 150.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PREQ\n",
+ "zone \n",
+ "1 150.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cost\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " C1 | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 3.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " C1\n",
+ "gen \n",
+ "1 1.0\n",
+ "2 3.0\n",
+ "3 5.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "qty\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PQTY | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 100.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 100.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 200.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PQTY\n",
+ "gen \n",
+ "1 100.0\n",
+ "2 100.0\n",
+ "3 200.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "dfs = reserves_data_to_dataframes(mpc.reserves)\n",
+ "for key, value in dfs.items():\n",
+ " print(key)\n",
+ " display(value)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "87bc9631",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "zones\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | gen | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ "gen 1 2 3 4\n",
+ "zone \n",
+ "1 1.0 1.0 1.0 0.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "req\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PREQ | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 150.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PREQ\n",
+ "zone \n",
+ "1 150.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cost\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " C1 | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 3.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 5.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " C1\n",
+ "gen \n",
+ "1 1.0\n",
+ "2 3.0\n",
+ "3 5.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "qty\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PQTY | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 100.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 100.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 200.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PQTY\n",
+ "gen \n",
+ "1 100.0\n",
+ "2 100.0\n",
+ "3 200.0"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "cf = CaseFrames(os.path.join(path_most_ex_cases, \"ex_case3a.m\"), load_case_engine=m)\n",
+ "for attribute in cf.reserves._attributes:\n",
+ " print(attribute)\n",
+ " display(getattr(cf.reserves, attribute))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "71fd2c3b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | gen | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 0.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ "gen 1 2 3 4\n",
+ "zone \n",
+ "1 1.0 1.0 1.0 0.0"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "cf.reserves.zones"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8789a89c",
+ "metadata": {},
+ "source": [
+ "> [!NOTE] \n",
+ "> Currently, `loadgenericdata` didn't support absolute path. This impacts various `most`\n",
+ "> functions. See: ."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "65bf6c72",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'CommitSched': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]]),\n",
+ " 'InitialPg': array([[ 125.],\n",
+ " [ 125.],\n",
+ " [ 200.],\n",
+ " [-450.]]),\n",
+ " 'RampWearCostCoeff': array([[0.],\n",
+ " [0.],\n",
+ " [0.],\n",
+ " [0.]]),\n",
+ " 'PositiveActiveReservePrice': array([[5.0e+00],\n",
+ " [1.0e-08],\n",
+ " [1.5e+00],\n",
+ " [1.0e-08]]),\n",
+ " 'PositiveActiveReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [600.],\n",
+ " [800.]]),\n",
+ " 'NegativeActiveReservePrice': array([[1.e+01],\n",
+ " [2.e-08],\n",
+ " [3.e+00],\n",
+ " [2.e-08]]),\n",
+ " 'NegativeActiveReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [600.],\n",
+ " [800.]]),\n",
+ " 'PositiveActiveDeltaPrice': array([[1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09]]),\n",
+ " 'NegativeActiveDeltaPrice': array([[1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09]]),\n",
+ " 'PositiveLoadFollowReservePrice': array([[1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e+01],\n",
+ " [1.e-06]]),\n",
+ " 'PositiveLoadFollowReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [100.],\n",
+ " [800.]]),\n",
+ " 'NegativeLoadFollowReservePrice': array([[1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e+01],\n",
+ " [1.e-06]]),\n",
+ " 'NegativeLoadFollowReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [250.],\n",
+ " [800.]]),\n",
+ " 'CommitKey': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [2.]]),\n",
+ " 'InitialState': array([[inf],\n",
+ " [inf],\n",
+ " [inf],\n",
+ " [inf]]),\n",
+ " 'MinUp': array([[1.],\n",
+ " [3.],\n",
+ " [1.],\n",
+ " [1.]]),\n",
+ " 'MinDown': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]])}"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "xgd = m.loadxgendata(\"ex_xgd_uc.m\", mpc)\n",
+ "xgd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "9688f94d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[5.0,\n",
+ " {'version': '2',\n",
+ " 'baseMVA': 100.0,\n",
+ " 'bus': array([[ 1. , 3. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95],\n",
+ " [ 2. , 2. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95],\n",
+ " [ 3. , 2. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95]]),\n",
+ " 'gen': array([[ 1., 125., 0., 25., -25., 1., 100., 1., 200.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 250.,\n",
+ " 250., 0., 0.],\n",
+ " [ 1., 125., 0., 25., -25., 1., 100., 1., 200.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 250.,\n",
+ " 250., 0., 0.],\n",
+ " [ 2., 200., 0., 50., -50., 1., 100., 1., 500.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 600.,\n",
+ " 600., 0., 0.],\n",
+ " [ 3., -450., 0., 0., 0., 1., 100., 1., 0.,\n",
+ " -450., 0., 0., 0., 0., 0., 0., 0., 500.,\n",
+ " 500., 0., 0.],\n",
+ " [ 2., 0., 0., 50., -50., 1., 100., 1., 100.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 200.,\n",
+ " 200., 0., 0.]]),\n",
+ " 'branch': array([[ 1.0e+00, 2.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 3.0e+02,\n",
+ " 3.0e+02, 3.0e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+00, 3.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 2.4e+02,\n",
+ " 2.4e+02, 2.4e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.0e+00, 3.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 3.0e+02,\n",
+ " 3.0e+02, 3.0e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02]]),\n",
+ " 'gencost': array([[2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 0.e+00, 1.e+03, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 2.e+00, 0.e+00, 0.e+00, 0.e+00]]),\n",
+ " 'reserves': {'zones': array([[1., 1., 1., 0., 0.]]),\n",
+ " 'req': 150.0,\n",
+ " 'cost': array([[1.],\n",
+ " [3.],\n",
+ " [5.]]),\n",
+ " 'qty': array([[100.],\n",
+ " [100.],\n",
+ " [200.]])},\n",
+ " 'genfuel': Cell([['unknown'],\n",
+ " ['unknown'],\n",
+ " ['unknown'],\n",
+ " ['unknown'],\n",
+ " ['wind']]),\n",
+ " 'iwind': 5.0},\n",
+ " {'CommitSched': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]]),\n",
+ " 'InitialPg': array([[ 125.],\n",
+ " [ 125.],\n",
+ " [ 200.],\n",
+ " [-450.],\n",
+ " [ 0.]]),\n",
+ " 'RampWearCostCoeff': array([[0.],\n",
+ " [0.],\n",
+ " [0.],\n",
+ " [0.],\n",
+ " [0.]]),\n",
+ " 'PositiveActiveReservePrice': array([[5.0e+00],\n",
+ " [1.0e-08],\n",
+ " [1.5e+00],\n",
+ " [1.0e-08],\n",
+ " [1.0e-08]]),\n",
+ " 'PositiveActiveReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [600.],\n",
+ " [800.],\n",
+ " [200.]]),\n",
+ " 'NegativeActiveReservePrice': array([[1.e+01],\n",
+ " [2.e-08],\n",
+ " [3.e+00],\n",
+ " [2.e-08],\n",
+ " [2.e-08]]),\n",
+ " 'NegativeActiveReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [600.],\n",
+ " [800.],\n",
+ " [200.]]),\n",
+ " 'PositiveActiveDeltaPrice': array([[1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09]]),\n",
+ " 'NegativeActiveDeltaPrice': array([[1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09]]),\n",
+ " 'PositiveLoadFollowReservePrice': array([[1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e+01],\n",
+ " [1.e-06],\n",
+ " [1.e-06]]),\n",
+ " 'PositiveLoadFollowReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [100.],\n",
+ " [800.],\n",
+ " [200.]]),\n",
+ " 'NegativeLoadFollowReservePrice': array([[1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e+01],\n",
+ " [1.e-06],\n",
+ " [1.e-06]]),\n",
+ " 'NegativeLoadFollowReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [250.],\n",
+ " [800.],\n",
+ " [200.]]),\n",
+ " 'CommitKey': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [2.],\n",
+ " [2.]]),\n",
+ " 'InitialState': array([[inf],\n",
+ " [inf],\n",
+ " [inf],\n",
+ " [inf],\n",
+ " [inf]]),\n",
+ " 'MinUp': array([[1.],\n",
+ " [3.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]]),\n",
+ " 'MinDown': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]])}]"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "[iwind, mpc, xgd] = m.addwind(\"ex_wind_uc\", mpc, xgd, nout=3)\n",
+ "[iwind, mpc, xgd]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "676057c0",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'type': 'mpcData',\n",
+ " 'table': 2.0,\n",
+ " 'rows': 5.0,\n",
+ " 'col': 9.0,\n",
+ " 'chgtype': 2.0,\n",
+ " 'values': array([[0.8 ],\n",
+ " [0.65],\n",
+ " [0.6 ],\n",
+ " [0.82],\n",
+ " [1. ],\n",
+ " [0.7 ],\n",
+ " [0.5 ],\n",
+ " [0.85],\n",
+ " [1. ],\n",
+ " [1.1 ],\n",
+ " [1.06],\n",
+ " [0.95]])}"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "profiles = m.getprofiles(\"ex_wind_profile_d\", iwind)\n",
+ "profiles"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "2bcf5d64",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2x1 StructArray containing the fields:\n",
+ " type\n",
+ " table\n",
+ " rows\n",
+ " col\n",
+ " chgtype\n",
+ " values"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "profiles = m.getprofiles(\"ex_load_profile\", profiles)\n",
+ "profiles"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "ee0cec81",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# TODO: example on `mdi = loadmd(mpc, transmat, xgd, [], 'ex_contab', profiles);`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "c9726cc1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[6.0,\n",
+ " {'version': '2',\n",
+ " 'baseMVA': 100.0,\n",
+ " 'bus': array([[ 1. , 3. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95],\n",
+ " [ 2. , 2. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95],\n",
+ " [ 3. , 2. , 0. , 0. , 0. , 0. , 1. , 1. ,\n",
+ " 0. , 135. , 1. , 1.05, 0.95]]),\n",
+ " 'gen': array([[ 1., 125., 0., 25., -25., 1., 100., 1., 200.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 250.,\n",
+ " 250., 0., 0.],\n",
+ " [ 1., 125., 0., 25., -25., 1., 100., 1., 200.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 250.,\n",
+ " 250., 0., 0.],\n",
+ " [ 2., 200., 0., 50., -50., 1., 100., 1., 500.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 600.,\n",
+ " 600., 0., 0.],\n",
+ " [ 3., -450., 0., 0., 0., 1., 100., 1., 0.,\n",
+ " -450., 0., 0., 0., 0., 0., 0., 0., 500.,\n",
+ " 500., 0., 0.],\n",
+ " [ 2., 0., 0., 50., -50., 1., 100., 1., 100.,\n",
+ " 0., 0., 0., 0., 0., 0., 0., 0., 200.,\n",
+ " 200., 0., 0.],\n",
+ " [ 3., 0., 0., 0., 0., 1., 100., 1., 80.,\n",
+ " -80., 0., 0., 0., 0., 0., 0., 0., 20.,\n",
+ " 20., 0., 0.]]),\n",
+ " 'branch': array([[ 1.0e+00, 2.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 3.0e+02,\n",
+ " 3.0e+02, 3.0e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+00, 3.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 2.4e+02,\n",
+ " 2.4e+02, 2.4e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.0e+00, 3.0e+00, 5.0e-03, 1.0e-02, 0.0e+00, 3.0e+02,\n",
+ " 3.0e+02, 3.0e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02]]),\n",
+ " 'gencost': array([[2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 1.e-01, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 3.e+00, 0.e+00, 1.e+03, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 2.e+00, 0.e+00, 0.e+00, 0.e+00],\n",
+ " [2.e+00, 0.e+00, 0.e+00, 2.e+00, 0.e+00, 0.e+00, 0.e+00]]),\n",
+ " 'reserves': {'zones': array([[1., 1., 1., 0., 0., 0.]]),\n",
+ " 'req': 150.0,\n",
+ " 'cost': array([[1.],\n",
+ " [3.],\n",
+ " [5.]]),\n",
+ " 'qty': array([[100.],\n",
+ " [100.],\n",
+ " [200.]])},\n",
+ " 'genfuel': Cell([['unknown'],\n",
+ " ['unknown'],\n",
+ " ['unknown'],\n",
+ " ['unknown'],\n",
+ " ['wind'],\n",
+ " ['ess']]),\n",
+ " 'iwind': 5.0,\n",
+ " 'iess': 6.0},\n",
+ " {'CommitSched': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]]),\n",
+ " 'InitialPg': array([[ 125.],\n",
+ " [ 125.],\n",
+ " [ 200.],\n",
+ " [-450.],\n",
+ " [ 0.],\n",
+ " [ 0.]]),\n",
+ " 'RampWearCostCoeff': array([[0.],\n",
+ " [0.],\n",
+ " [0.],\n",
+ " [0.],\n",
+ " [0.],\n",
+ " [0.]]),\n",
+ " 'PositiveActiveReservePrice': array([[5.0e+00],\n",
+ " [1.0e-08],\n",
+ " [1.5e+00],\n",
+ " [1.0e-08],\n",
+ " [1.0e-08],\n",
+ " [1.0e-08]]),\n",
+ " 'PositiveActiveReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [600.],\n",
+ " [800.],\n",
+ " [200.],\n",
+ " [160.]]),\n",
+ " 'NegativeActiveReservePrice': array([[1.e+01],\n",
+ " [2.e-08],\n",
+ " [3.e+00],\n",
+ " [2.e-08],\n",
+ " [2.e-08],\n",
+ " [2.e-08]]),\n",
+ " 'NegativeActiveReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [600.],\n",
+ " [800.],\n",
+ " [200.],\n",
+ " [160.]]),\n",
+ " 'PositiveActiveDeltaPrice': array([[1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09]]),\n",
+ " 'NegativeActiveDeltaPrice': array([[1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09],\n",
+ " [1.e-09]]),\n",
+ " 'PositiveLoadFollowReservePrice': array([[1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e+01],\n",
+ " [1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e-06]]),\n",
+ " 'PositiveLoadFollowReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [100.],\n",
+ " [800.],\n",
+ " [200.],\n",
+ " [160.]]),\n",
+ " 'NegativeLoadFollowReservePrice': array([[1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e+01],\n",
+ " [1.e-06],\n",
+ " [1.e-06],\n",
+ " [1.e-06]]),\n",
+ " 'NegativeLoadFollowReserveQuantity': array([[250.],\n",
+ " [250.],\n",
+ " [250.],\n",
+ " [800.],\n",
+ " [200.],\n",
+ " [160.]]),\n",
+ " 'CommitKey': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [2.],\n",
+ " [2.],\n",
+ " [2.]]),\n",
+ " 'InitialState': array([[inf],\n",
+ " [inf],\n",
+ " [inf],\n",
+ " [inf],\n",
+ " [inf],\n",
+ " [inf]]),\n",
+ " 'MinUp': array([[1.],\n",
+ " [3.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]]),\n",
+ " 'MinDown': array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]])},\n",
+ " {'UnitIdx': 6.0,\n",
+ " 'ExpectedTerminalStorageAim': [],\n",
+ " 'ExpectedTerminalStorageMin': [],\n",
+ " 'ExpectedTerminalStorageMax': [],\n",
+ " 'rho': 0.0,\n",
+ " 'TerminalChargingPrice0': [],\n",
+ " 'TerminalDischargingPrice0': [],\n",
+ " 'TerminalChargingPriceK': [],\n",
+ " 'TerminalDischargingPriceK': [],\n",
+ " 'OutEff': 1.0,\n",
+ " 'InEff': 1.0,\n",
+ " 'LossFactor': 1e-05,\n",
+ " 'InitialStorage': 0.0,\n",
+ " 'InitialStorageLowerBound': 0.0,\n",
+ " 'InitialStorageUpperBound': 200.0,\n",
+ " 'InitialStorageCost': 45.166667,\n",
+ " 'TerminalStoragePrice': 45.166667,\n",
+ " 'MinStorageLevel': 0.0,\n",
+ " 'MaxStorageLevel': 200.0}]"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "[iess, mpc, xgd, sd] = m.addstorage(\"ex_storage\", mpc, xgd, nout=4)\n",
+ "[iess, mpc, xgd, sd]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "159b9137",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m.exit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35fe9966",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "env",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.14.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/load_t_case30_userfcns.ipynb b/notebooks/load_t_case30_userfcns.ipynb
new file mode 100644
index 0000000..39d9b92
--- /dev/null
+++ b/notebooks/load_t_case30_userfcns.ipynb
@@ -0,0 +1,976 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "eae79aa2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# # install octave\n",
+ "# !sudo apt-get -qq update\n",
+ "# !sudo apt-get -qq install octave octave-signal liboctave-dev\n",
+ "\n",
+ "# # install oct2py that compatible with colab\n",
+ "# import os\n",
+ "\n",
+ "# from pkg_resources import get_distribution\n",
+ "\n",
+ "# os.system(\n",
+ "# f\"pip install -qq\"\n",
+ "# f\" ipykernel=={get_distribution('ipykernel').version}\"\n",
+ "# f\" ipython=={get_distribution('ipython').version}\"\n",
+ "# f\" tornado=={get_distribution('tornado').version}\"\n",
+ "# f\" oct2py\"\n",
+ "# )\n",
+ "\n",
+ "# # install packages\n",
+ "# !pip install -qq matpower matpowercaseframes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "5bc86ee4",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "oct2py version: 5.8.0\n",
+ "matpower version: 8.1.0.2.2.3\n"
+ ]
+ }
+ ],
+ "source": [
+ "import matpower\n",
+ "import oct2py\n",
+ "\n",
+ "print(f\"oct2py version: {oct2py.__version__}\")\n",
+ "print(f\"matpower version: {matpower.__version__}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "3116b86b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "\n",
+ "import pandas as pd\n",
+ "from matpower import path_matpower, start_instance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "10fd2d91",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "path_t_cases = os.path.join(path_matpower, \"lib/t\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "7e230eb0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = start_instance()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "6d93dd06",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'version': '2',\n",
+ " 'baseMVA': 100.0,\n",
+ " 'bus': array([[1.00e+00, 3.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.00e+00, 2.00e+00, 2.17e+01, 1.27e+01, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.10e+00,\n",
+ " 9.50e-01],\n",
+ " [3.00e+02, 1.00e+00, 2.40e+00, 1.20e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [4.00e+00, 1.00e+00, 7.60e+00, 1.60e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [5.00e+00, 1.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 1.90e-01,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [6.00e+00, 1.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [7.00e+00, 1.00e+00, 2.28e+01, 1.09e+01, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [8.00e+00, 1.00e+00, 3.00e+01, 3.00e+01, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [9.00e+00, 1.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.00e+01, 1.00e+00, 5.80e+00, 2.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.10e+01, 1.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.20e+01, 1.00e+00, 1.12e+01, 7.50e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.30e+01, 2.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.10e+00,\n",
+ " 9.50e-01],\n",
+ " [1.40e+01, 1.00e+00, 6.20e+00, 1.60e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.50e+01, 1.00e+00, 8.20e+00, 2.50e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.60e+01, 1.00e+00, 3.50e+00, 1.80e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.70e+01, 1.00e+00, 9.00e+00, 5.80e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.80e+01, 1.00e+00, 3.20e+00, 9.00e-01, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [1.90e+01, 1.00e+00, 9.50e+00, 3.40e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.00e+01, 1.00e+00, 2.20e+00, 7.00e-01, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.10e+01, 1.00e+00, 1.75e+01, 1.12e+01, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.20e+01, 2.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.10e+00,\n",
+ " 9.50e-01],\n",
+ " [2.30e+01, 2.00e+00, 3.20e+00, 1.60e+00, 0.00e+00, 0.00e+00,\n",
+ " 2.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.10e+00,\n",
+ " 9.50e-01],\n",
+ " [2.40e+01, 1.00e+00, 8.70e+00, 6.70e+00, 0.00e+00, 4.00e-02,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.50e+01, 1.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.60e+01, 1.00e+00, 3.50e+00, 2.30e+00, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.70e+01, 2.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.10e+00,\n",
+ " 9.50e-01],\n",
+ " [2.80e+01, 1.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 0.00e+00,\n",
+ " 1.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [2.90e+01, 1.00e+00, 2.40e+00, 9.00e-01, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01],\n",
+ " [3.00e+01, 1.00e+00, 1.06e+01, 1.90e+00, 0.00e+00, 0.00e+00,\n",
+ " 3.00e+00, 1.00e+00, 0.00e+00, 1.35e+02, 1.00e+00, 1.05e+00,\n",
+ " 9.50e-01]]),\n",
+ " 'gen': array([[ 1. , 23.54, 0. , 150. , -20. , 1. , 100. , 1. ,\n",
+ " 80. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,\n",
+ " 0. , 0. , 0. , 0. , 0. ],\n",
+ " [ 2. , 60.97, 0. , 60. , -20. , 1. , 100. , 1. ,\n",
+ " 80. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,\n",
+ " 0. , 0. , 0. , 0. , 0. ],\n",
+ " [ 22. , 21.59, 0. , 62.5 , -15. , 1. , 100. , 1. ,\n",
+ " 50. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,\n",
+ " 0. , 0. , 0. , 0. , 0. ],\n",
+ " [ 27. , 26.91, 0. , 48.7 , -15. , 1. , 100. , 1. ,\n",
+ " 55. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,\n",
+ " 0. , 0. , 0. , 0. , 0. ],\n",
+ " [ 23. , 19.2 , 0. , 40. , -10. , 1. , 100. , 1. ,\n",
+ " 30. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,\n",
+ " 0. , 0. , 0. , 0. , 0. ],\n",
+ " [ 13. , 37. , 0. , 44.7 , -15. , 1. , 100. , 1. ,\n",
+ " 40. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ,\n",
+ " 0. , 0. , 0. , 0. , 0. ]]),\n",
+ " 'branch': array([[ 1.0e+00, 2.0e+00, 2.0e-02, 6.0e-02, 3.0e-02, 1.3e+02,\n",
+ " 1.3e+02, 1.3e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+00, 3.0e+02, 5.0e-02, 1.9e-01, 2.0e-02, 1.3e+02,\n",
+ " 1.3e+02, 1.3e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.0e+00, 4.0e+00, 6.0e-02, 1.7e-01, 2.0e-02, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 3.0e+02, 4.0e+00, 1.0e-02, 4.0e-02, 0.0e+00, 1.3e+02,\n",
+ " 1.3e+02, 1.3e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.0e+00, 5.0e+00, 5.0e-02, 2.0e-01, 2.0e-02, 1.3e+02,\n",
+ " 1.3e+02, 1.3e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.0e+00, 6.0e+00, 6.0e-02, 1.8e-01, 2.0e-02, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 4.0e+00, 6.0e+00, 1.0e-02, 4.0e-02, 0.0e+00, 9.0e+01,\n",
+ " 9.0e+01, 9.0e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 5.0e+00, 7.0e+00, 5.0e-02, 1.2e-01, 1.0e-02, 7.0e+01,\n",
+ " 7.0e+01, 7.0e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 6.0e+00, 7.0e+00, 3.0e-02, 8.0e-02, 1.0e-02, 1.3e+02,\n",
+ " 1.3e+02, 1.3e+02, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 6.0e+00, 8.0e+00, 1.0e-02, 4.0e-02, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 6.0e+00, 9.0e+00, 0.0e+00, 2.1e-01, 0.0e+00, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 6.0e+00, 1.0e+01, 0.0e+00, 5.6e-01, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 9.0e+00, 1.1e+01, 0.0e+00, 2.1e-01, 0.0e+00, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 9.0e+00, 1.0e+01, 0.0e+00, 1.1e-01, 0.0e+00, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 4.0e+00, 1.2e+01, 0.0e+00, 2.6e-01, 0.0e+00, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.2e+01, 1.3e+01, 0.0e+00, 1.4e-01, 0.0e+00, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.2e+01, 1.4e+01, 1.2e-01, 2.6e-01, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.2e+01, 1.5e+01, 7.0e-02, 1.3e-01, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.2e+01, 1.6e+01, 9.0e-02, 2.0e-01, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.4e+01, 1.5e+01, 2.2e-01, 2.0e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.6e+01, 1.7e+01, 8.0e-02, 1.9e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.5e+01, 1.8e+01, 1.1e-01, 2.2e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.8e+01, 1.9e+01, 6.0e-02, 1.3e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.9e+01, 2.0e+01, 3.0e-02, 7.0e-02, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+01, 2.0e+01, 9.0e-02, 2.1e-01, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+01, 1.7e+01, 3.0e-02, 8.0e-02, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+01, 2.1e+01, 3.0e-02, 7.0e-02, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.0e+01, 2.2e+01, 7.0e-02, 1.5e-01, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.1e+01, 2.2e+01, 1.0e-02, 2.0e-02, 0.0e+00, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 1.5e+01, 2.3e+01, 1.0e-01, 2.0e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.2e+01, 2.4e+01, 1.2e-01, 1.8e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.3e+01, 2.4e+01, 1.3e-01, 2.7e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.4e+01, 2.5e+01, 1.9e-01, 3.3e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.5e+01, 2.6e+01, 2.5e-01, 3.8e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.5e+01, 2.7e+01, 1.1e-01, 2.1e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.8e+01, 2.7e+01, 0.0e+00, 4.0e-01, 0.0e+00, 6.5e+01,\n",
+ " 6.5e+01, 6.5e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.7e+01, 2.9e+01, 2.2e-01, 4.2e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.7e+01, 3.0e+01, 3.2e-01, 6.0e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 2.9e+01, 3.0e+01, 2.4e-01, 4.5e-01, 0.0e+00, 1.6e+01,\n",
+ " 1.6e+01, 1.6e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 8.0e+00, 2.8e+01, 6.0e-02, 2.0e-01, 2.0e-02, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02],\n",
+ " [ 6.0e+00, 2.8e+01, 2.0e-02, 6.0e-02, 1.0e-02, 3.2e+01,\n",
+ " 3.2e+01, 3.2e+01, 0.0e+00, 0.0e+00, 1.0e+00, -3.6e+02,\n",
+ " 3.6e+02]]),\n",
+ " 'gencost': array([[2. , 0. , 0. , 3. , 0.02 , 2. , 0. ],\n",
+ " [2. , 0. , 0. , 3. , 0.0175 , 1.75 , 0. ],\n",
+ " [2. , 0. , 0. , 3. , 0.0625 , 1. , 0. ],\n",
+ " [2. , 0. , 0. , 3. , 0.00834, 3.25 , 0. ],\n",
+ " [2. , 0. , 0. , 3. , 0.025 , 3. , 0. ],\n",
+ " [2. , 0. , 0. , 3. , 0.025 , 3. , 0. ]]),\n",
+ " 'reserves': {'zones': array([[1., 1., 1., 1., 1., 1.],\n",
+ " [0., 0., 0., 0., 1., 1.]]),\n",
+ " 'req': array([[60.],\n",
+ " [20.]]),\n",
+ " 'cost': array([[1.9],\n",
+ " [2. ],\n",
+ " [3. ],\n",
+ " [4. ],\n",
+ " [5. ],\n",
+ " [5.5]]),\n",
+ " 'qty': array([[25.],\n",
+ " [25.],\n",
+ " [25.],\n",
+ " [25.],\n",
+ " [25.],\n",
+ " [25.]])},\n",
+ " 'if': {'map': array([[ 1., -12.],\n",
+ " [ 1., -14.],\n",
+ " [ 1., -15.],\n",
+ " [ 1., -36.],\n",
+ " [ 2., 15.],\n",
+ " [ 2., 25.],\n",
+ " [ 2., 26.],\n",
+ " [ 2., -32.],\n",
+ " [ 3., 12.],\n",
+ " [ 3., 14.],\n",
+ " [ 3., -25.],\n",
+ " [ 3., -26.],\n",
+ " [ 3., 32.],\n",
+ " [ 3., 36.]]),\n",
+ " 'lims': array([[ 1., -15., 25.],\n",
+ " [ 2., -10., 20.]])}}"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# load single most example case\n",
+ "mpc = m.loadcase(os.path.join(path_t_cases, \"t_case30_userfcns.m\"))\n",
+ "mpc"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "b6bbbce4",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys(['version', 'baseMVA', 'bus', 'gen', 'branch', 'gencost', 'reserves', 'if'])"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpc.keys()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "ea66211a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from matpowercaseframes.constants import COLUMNS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "a911808f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys(['bus', 'gen', 'branch', 'dcline', 'if', 'gencost', 'dclinecost', 'bus_name', 'branch_name', 'gen_name', 'case'])"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "COLUMNS.keys()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "f63470e2",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'baseMVA', 'reserves', 'version'}"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpc_keys = set(mpc.keys())\n",
+ "columns_keys = set(COLUMNS.keys())\n",
+ "missing_keys = mpc_keys - columns_keys\n",
+ "missing_keys"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "8577fe89",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'zones': array([[1., 1., 1., 1., 1., 1.],\n",
+ " [0., 0., 0., 0., 1., 1.]]),\n",
+ " 'req': array([[60.],\n",
+ " [20.]]),\n",
+ " 'cost': array([[1.9],\n",
+ " [2. ],\n",
+ " [3. ],\n",
+ " [4. ],\n",
+ " [5. ],\n",
+ " [5.5]]),\n",
+ " 'qty': array([[25.],\n",
+ " [25.],\n",
+ " [25.],\n",
+ " [25.],\n",
+ " [25.],\n",
+ " [25.]])}"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpc.reserves"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f46abaea",
+ "metadata": {},
+ "source": [
+ "Reserve Data\n",
+ "reserve zones, element i, j is 1 if gen j is in zone i, 0 otherwise.\n",
+ "dimension (zone, gen)\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.zones = [\n",
+ "\t1\t1\t1\t0;\n",
+ "];\n",
+ "```\n",
+ "\n",
+ "Mapped to `DataFrame` with index follows zone index (from 1), and columns follows\n",
+ "generator index (cf.gen.index)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "370d5e7c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | gen | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 6 | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 0.0 | \n",
+ " 1.0 | \n",
+ " 1.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ "gen 1 2 3 4 5 6\n",
+ "zone \n",
+ "1 1.0 1.0 1.0 1.0 1.0 1.0\n",
+ "2 0.0 0.0 0.0 0.0 1.0 1.0"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "reserves_zone = mpc.reserves.zones\n",
+ "n_zones, n_gens = reserves_zone.shape\n",
+ "df_reserves_zone = pd.DataFrame(\n",
+ " reserves_zone,\n",
+ " index=pd.RangeIndex(start=1, stop=n_zones + 1, name=\"zone\"),\n",
+ " columns=pd.RangeIndex(start=1, stop=n_gens + 1, name=\"gen\"),\n",
+ ")\n",
+ "df_reserves_zone"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "765a409f",
+ "metadata": {},
+ "source": [
+ "reserve requirements for each zone in MW\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.req = [60; 20];\n",
+ "```\n",
+ "\n",
+ "or\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.req = 150;\n",
+ "```\n",
+ "\n",
+ "Mapped to `DataFrame` with index follows zone index (from 1), and single column 'PREQ'."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "b817c54f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PREQ | \n",
+ "
\n",
+ " \n",
+ " | zone | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 60.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 20.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PREQ\n",
+ "zone \n",
+ "1 60.0\n",
+ "2 20.0"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "reserves_req = mpc.reserves.req\n",
+ "df_reserves_req = pd.DataFrame(\n",
+ " reserves_req,\n",
+ " index=pd.RangeIndex(start=1, stop=n_zones + 1, name=\"zone\"),\n",
+ " columns=[\"PREQ\"],\n",
+ ")\n",
+ "df_reserves_req"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "227155ed",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "RangeIndex(start=1, stop=7, step=1, name='gen')"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_zone_sum = df_reserves_zone.sum(axis=0)\n",
+ "idx_gen_with_reserves = df_reserves_zone_sum[df_reserves_zone_sum > 0].index\n",
+ "idx_gen_with_reserves"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "8c5f69a2",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " C1 | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 1.9 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 2.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 3.0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 4.0 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
+ " 5.0 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " 5.5 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " C1\n",
+ "gen \n",
+ "1 1.9\n",
+ "2 2.0\n",
+ "3 3.0\n",
+ "4 4.0\n",
+ "5 5.0\n",
+ "6 5.5"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "reserves_cost = mpc.reserves.cost\n",
+ "df_reserves_cost = pd.DataFrame(\n",
+ " reserves_cost, index=idx_gen_with_reserves, columns=[\"C1\"]\n",
+ ")\n",
+ "df_reserves_cost"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8be24e2e",
+ "metadata": {},
+ "source": [
+ "max reserve quantities for each gen that belongs to at least 1 zone. (same order as\n",
+ "gens, but skipping any gen that does not belong to any zone)\n",
+ "\n",
+ "```octave\n",
+ "mpc.reserves.qty = [\t25;\t25;\t25;\t25;\t25;\t25\t];\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "bd64557b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " PQTY | \n",
+ "
\n",
+ " \n",
+ " | gen | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 1 | \n",
+ " 25.0 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 25.0 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 25.0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 25.0 | \n",
+ "
\n",
+ " \n",
+ " | 5 | \n",
+ " 25.0 | \n",
+ "
\n",
+ " \n",
+ " | 6 | \n",
+ " 25.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " PQTY\n",
+ "gen \n",
+ "1 25.0\n",
+ "2 25.0\n",
+ "3 25.0\n",
+ "4 25.0\n",
+ "5 25.0\n",
+ "6 25.0"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df_reserves_qty = pd.DataFrame(\n",
+ " mpc.reserves.qty, index=idx_gen_with_reserves, columns=[\"PQTY\"]\n",
+ ")\n",
+ "df_reserves_qty"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "6bda4dbb",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'map': array([[ 1., -12.],\n",
+ " [ 1., -14.],\n",
+ " [ 1., -15.],\n",
+ " [ 1., -36.],\n",
+ " [ 2., 15.],\n",
+ " [ 2., 25.],\n",
+ " [ 2., 26.],\n",
+ " [ 2., -32.],\n",
+ " [ 3., 12.],\n",
+ " [ 3., 14.],\n",
+ " [ 3., -25.],\n",
+ " [ 3., -26.],\n",
+ " [ 3., 32.],\n",
+ " [ 3., 36.]]),\n",
+ " 'lims': array([[ 1., -15., 25.],\n",
+ " [ 2., -10., 20.]])}"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# TODO: mpc.if (need to use mpc['if'])\n",
+ "mpc[\"if\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "159b9137",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m.exit()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35fe9966",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "env",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.14.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/pyproject.toml b/pyproject.toml
index 1cb39d7..428e823 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -46,11 +46,11 @@ dev = [
"oct2py>=5.5.1", # latest support for 3.7
"openpyxl>=3.1.2",
"pandas>=1.2.0",
- "pre-commit>=2.21.0",
- "pytest>=7.2.0",
- "pytest-cov>=4.0.0",
- "pytest-xdist>=3.1.0",
- "ruff>=0.6.4",
+ "pre-commit>=3.8.0",
+ "pytest>=9.0.2",
+ "pytest-cov>=7.0.0",
+ "pytest-xdist>=3.8.0",
+ "ruff>=0.14.10",
]
[project.urls]
diff --git a/requirements-all.txt b/requirements-all.txt
index 4513486..2950b7a 100644
--- a/requirements-all.txt
+++ b/requirements-all.txt
@@ -1,13 +1,13 @@
-pandas==2.3.3
-numpy==2.4.0
+pandas==3.0.0rc1
+numpy==2.4.1
openpyxl==3.1.5
oct2py==5.8.0
matpower==8.1.0.2.2.3
-pre-commit==3.8.0
-ruff==0.14.10
+pre-commit==4.5.1
+ruff==0.14.13
setuptools==80.9.0
pytest==9.0.2