grid-gent / gridgent /tools.py
James Afful
Add Grid-Gent Space code and Dockerfile (no binary assets)
458fa79
from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, Any, List
@dataclass
class PowerFlowResult:
feeder: str
peak_loading_pct: float
min_voltage_pu: float
max_voltage_pu: float
overload_elements: List[str]
notes: str
def to_dict(self) -> Dict[str, Any]:
return {
"feeder": self.feeder,
"peak_loading_pct": round(self.peak_loading_pct, 1),
"min_voltage_pu": round(self.min_voltage_pu, 3),
"max_voltage_pu": round(self.max_voltage_pu, 3),
"overload_elements": self.overload_elements,
"notes": self.notes,
}
def get_feeder_summary(feeder: str) -> Dict[str, Any]:
feeder = feeder.upper().strip()
data = {
"F1": {
"name": "Feeder F1 - Downtown Core",
"base_kv": 13.8,
"num_customers": 4200,
"peak_mw": 18.5,
"pv_mw": 3.2,
},
"F2": {
"name": "Feeder F2 - Residential West",
"base_kv": 13.8,
"num_customers": 5100,
"peak_mw": 14.3,
"pv_mw": 4.7,
},
"F3": {
"name": "Feeder F3 - Industrial Park",
"base_kv": 13.8,
"num_customers": 830,
"peak_mw": 22.1,
"pv_mw": 0.8,
},
}
return data.get(
feeder,
{
"name": f"Feeder {feeder} (demo placeholder)",
"base_kv": 13.8,
"num_customers": 3000,
"peak_mw": 10.0,
"pv_mw": 1.0,
},
)
def run_power_flow_scenario(
feeder: str,
added_pv_mw: float = 0.0,
added_load_mw: float = 0.0,
) -> PowerFlowResult:
meta = get_feeder_summary(feeder)
base_peak = float(meta.get("peak_mw", 10.0))
base_pv = float(meta.get("pv_mw", 1.0))
new_peak = base_peak + added_load_mw - 0.5 * added_pv_mw
if new_peak < 0:
new_peak = 0.0
rating_mva = base_peak * 1.2 if base_peak > 0 else 12.0
peak_loading_pct = 100.0 * (new_peak / rating_mva)
min_voltage = 0.97 - 0.01 * (added_load_mw / max(base_peak, 1.0))
max_voltage = 1.03 + 0.01 * (added_pv_mw / max(base_pv, 0.5))
min_voltage = max(min_voltage, 0.9)
max_voltage = min(max_voltage, 1.10)
overload_elements: List[str] = []
if peak_loading_pct > 100.0:
overload_elements.append("Main transformer overloaded")
if peak_loading_pct > 95.0:
overload_elements.append("One or more line segments near thermal limit")
if min_voltage < 0.95:
overload_elements.append("Low voltage at end-of-line customers")
if max_voltage > 1.05:
overload_elements.append("Risk of over-voltage near PV clusters")
if overload_elements:
notes = "Potential issues detected; further detailed study recommended."
else:
notes = "Scenario appears within normal operating limits in this simplified model."
return PowerFlowResult(
feeder=feeder,
peak_loading_pct=peak_loading_pct,
min_voltage_pu=min_voltage,
max_voltage_pu=max_voltage,
overload_elements=overload_elements,
notes=notes,
)