import atexit
import os
import sys
import tempfile
import time
from pathlib import Path
import pypowsybl.loadflow as lf
import pypowsybl.network as pn
import scipy.io as sio
from matpower_to_pgm import load_mpc
case_name = sys.argv[1] if len(sys.argv) > 1 else "case14"
input_path = Path(sys.argv[2] if len(sys.argv) > 2 else f"{case_name}.m")
if input_path.suffix == ".m":
mpc = load_mpc(input_path)
mpc.setdefault("version", "2")
tmp_mat = tempfile.NamedTemporaryFile(suffix=".mat", delete=False)
sio.savemat(tmp_mat.name, {"mpc": mpc})
m_path = tmp_mat.name
atexit.register(os.unlink, m_path)
else:
m_path = str(input_path)
t0 = time.perf_counter()
network = pn.load(m_path)
t1 = time.perf_counter()
print(f"model construction: {(t1 - t0) * 1e3:.3f} ms", file=sys.stderr)
n_bus = len(network.get_buses())
params = lf.Parameters(
voltage_init_mode=lf.VoltageInitMode.UNIFORM_VALUES,
distributed_slack=False,
use_reactive_limits=False,
phase_shifter_regulation_on=False,
transformer_voltage_control_on=False,
connected_component_mode=lf.ConnectedComponentMode.MAIN,
)
def run_ac() -> None:
result = lf.run_ac(network, parameters=params)
if result[0].status != lf.ComponentStatus.CONVERGED:
raise RuntimeError(f"pypowsybl load flow did not converge for {case_name}: {result[0].status_text}")
run_ac()
times = []
for _ in range(5):
t0 = time.perf_counter()
run_ac()
t1 = time.perf_counter()
times.append(t1 - t0)
print(f"nodes={n_bus}")
print(f"run_ac (warm, 5 runs, ms): {[f'{t * 1e3:.3f}' for t in times]}")
print(f"min={min(times) * 1e3:.3f}ms mean={sum(times) / len(times) * 1e3:.3f}ms")
voltages = network.get_buses()["v_mag"]
print(f"vm min/max = {voltages.min():.6f} / {voltages.max():.6f}")
t0 = time.perf_counter()
network2 = pn.load(m_path)
lf.run_ac(network2, parameters=params)
t1 = time.perf_counter()
print(f"cold (construct+calc): {(t1 - t0) * 1e3:.3f} ms")