PowerCase data model and column index constants.
The constants follow MATPOWER's case format (version 2) - see
case_ACTIVSg10kCopy2.m headers and test_9bus_case.m for the
canonical column orderings:
bus: bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin
(+ lam_P lam_Q mu_Vmax mu_Vmin if present)
gen: bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min
Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf
(+ mu_Pmax mu_Pmin mu_Qmax mu_Qmin if present)
branch: fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax
(+ Pf Qf Pt Qt mu_Sf mu_St mu_angmin mu_angmax if present)
PowerCase
dataclass
PowerCase(base_mva: float = 100.0, bus: NDArray[floating] = (lambda: np.zeros((0, BUS_COLUMNS)))(), gen: NDArray[floating] = (lambda: np.zeros((0, GEN_COLUMNS)))(), branch: NDArray[floating] = (lambda: np.zeros((0, BRANCH_COLUMNS)))(), gencost: NDArray[floating] | None = None, gentype: list[str] | None = None, genfuel: list[str] | None = None, bus_name: list[str] | None = None, dcline: NDArray[floating] | None = None, version: str = '2')
In-memory MATPOWER case (version 2).
Matrices use numpy float arrays, 0-indexed. base_mva matches
MATPOWER's mpc.baseMVA. Optional fields are None when absent.
copy
Return a deep copy that is safe to mutate.
Source code in src/simplenet/case.py
| def copy(self) -> PowerCase:
"""Return a deep copy that is safe to mutate."""
return replace(
self,
bus=self.bus.copy(),
gen=self.gen.copy(),
branch=self.branch.copy(),
gencost=None if self.gencost is None else self.gencost.copy(),
gentype=None if self.gentype is None else list(self.gentype),
genfuel=None if self.genfuel is None else list(self.genfuel),
bus_name=None if self.bus_name is None else list(self.bus_name),
dcline=None if self.dcline is None else self.dcline.copy(),
)
|
from_pypower
classmethod
from_pypower(mpc: dict[str, Any]) -> PowerCase
Build a PowerCase from a pypower-style dict.
Accepts either pypower's baseMVA (camelCase) or
base_mva (snake_case). Missing optional fields are left
unset.
Source code in src/simplenet/case.py
| @classmethod
def from_pypower(cls, mpc: dict[str, Any]) -> PowerCase:
"""Build a ``PowerCase`` from a pypower-style dict.
Accepts either pypower's ``baseMVA`` (camelCase) or
``base_mva`` (snake_case). Missing optional fields are left
unset.
"""
base = mpc.get("baseMVA", mpc.get("base_mva", 100.0))
bus = _to_2d_float(mpc["bus"])
gen = _to_2d_float(mpc["gen"])
branch = _to_2d_float(mpc["branch"])
gencost = _to_2d_float(mpc["gencost"]) if "gencost" in mpc and mpc["gencost"] is not None else None
dcline = _to_2d_float(mpc["dcline"]) if "dcline" in mpc and mpc["dcline"] is not None else None
gentype = list(mpc["gentype"]) if "gentype" in mpc and mpc["gentype"] is not None else None
genfuel = list(mpc["genfuel"]) if "genfuel" in mpc and mpc["genfuel"] is not None else None
bus_name = list(mpc["bus_name"]) if "bus_name" in mpc and mpc["bus_name"] is not None else None
return cls(
base_mva=float(base),
bus=bus,
gen=gen,
branch=branch,
gencost=gencost,
dcline=dcline,
gentype=gentype,
genfuel=genfuel,
bus_name=bus_name,
version=str(mpc.get("version", "2")),
)
|
to_pypower
to_pypower() -> dict[str, Any]
Export to a pypower-style dict.
Source code in src/simplenet/case.py
| def to_pypower(self) -> dict[str, Any]:
"""Export to a pypower-style dict."""
out: dict[str, Any] = {
"version": self.version,
"baseMVA": float(self.base_mva),
"bus": self.bus.copy(),
"gen": self.gen.copy(),
"branch": self.branch.copy(),
}
if self.gencost is not None:
out["gencost"] = self.gencost.copy()
if self.gentype is not None:
out["gentype"] = list(self.gentype)
if self.genfuel is not None:
out["genfuel"] = list(self.genfuel)
if self.bus_name is not None:
out["bus_name"] = list(self.bus_name)
if self.dcline is not None:
out["dcline"] = self.dcline.copy()
return out
|
pad_to_columns
pad_to_columns(arr: ndarray, ncols: int) -> np.ndarray
Right-pad a 2-D numeric array with zero columns up to ncols.
Source code in src/simplenet/case.py
| def pad_to_columns(arr: np.ndarray, ncols: int) -> np.ndarray:
"""Right-pad a 2-D numeric array with zero columns up to ``ncols``."""
if arr.size == 0:
return np.zeros((arr.shape[0], ncols))
if arr.shape[1] >= ncols:
return arr
pad = np.zeros((arr.shape[0], ncols - arr.shape[1]))
return np.hstack([arr, pad])
|