AC Power Flow Validation
Script: scripts/validate_ac_model_against_pandapower.py
Validates the potpourri AC power flow solver against
pandapower's Newton-Raphson power flow
on six standard SimBench benchmark networks.
Purpose
The AC class in potpourri formulates AC power flow as a Pyomo
optimisation problem and solves it with an NLP solver (IPOPT or NEOS).
This script provides a quantitative comparison of the results against
pandapower's reference solver.
Workflow
for each network in NETS
┌─ load simbench network
├─ solve with potpourri AC (NEOS / IPOPT)
├─ solve with pandapower pp.runpp()
├─ compute error metrics on res_bus and res_line
└─ collect results
print pivot tables and error ranking
- Load the network via
simbench.get_simbench_net(). - Build and solve the
ACmodel — the constructor runspp.runpp()internally to initialise voltages and angles; the NLP solver then finds the feasible AC power flow solution. - Run the reference power flow with
pp.runpp()on the original network using voltage-independent loads. - Compare the following fields:
| Table | Fields |
|---|---|
res_bus |
vm_pu, va_degree |
res_line |
pl_mw, ql_mvar |
- Report mean absolute error (MAE), maximum absolute error, RMSE, and standard deviation per field; identify the bus or line with the largest deviation.
Networks tested
| Network ID | Voltage level | Notes |
|---|---|---|
1-HV-mixed--0-sw |
HV | mixed urban/rural, switches |
1-HV-urban--0-sw |
HV | urban, switches |
1-MV-rural--0-sw |
MV | rural |
1-MV-urban--0-sw |
MV | urban |
1-LV-urban6--0-sw |
LV | urban |
1-LV-rural1--0-sw |
LV | rural |
Usage
Requires IPOPT (included in environment.yaml):
conda activate potpourri_env
python scripts/validate_ac_model_against_pandapower.py
To use the NEOS cloud solver instead (no local solver required), uncomment
the corresponding ac.solve(solver="neos") line in the script and set:
export NEOS_EMAIL="your@email.address"
Example output
Detailed comparison:
net element variable mean_abs max_abs rmse std_abs worst_index solver_converged vm_pu_close
0 1-HV-mixed--0-sw res_bus vm_pu 0.023850 0.042419 0.026011 0.010122 5 True False
1 1-HV-mixed--0-sw res_bus va_degree 0.234032 0.739218 0.289415 0.173017 12 True False
...
Compact pivot table (mean absolute error):
variable pl_mw ql_mvar va_degree vm_pu
net
1-HV-mixed--0-sw 0.012336 0.051528 0.234032 0.023850
1-LV-rural1--0-sw 0.002670 0.001040 7.052760 0.280162
1-MV-rural--0-sw 0.050133 0.027593 2.634818 0.035633
Networks ranked by total mean absolute error:
net
1-HV-mixed--0-sw 0.321746
1-MV-rural--0-sw 2.748177
1-LV-rural1--0-sw 7.336632
Interpreting the results
The AC model treats static generator reactive power (qsG) as a free
optimisation variable, whereas pandapower fixes it to the value specified in
net.sgen.q_mvar. This structural difference means the NLP solver finds a
different (but equally valid) AC power flow solution in terms of reactive
power dispatch, leading to measurable voltage angle and magnitude differences
relative to pandapower.
Key observations:
- HV networks (larger impedances, stronger voltage coupling) show smaller relative errors than LV networks.
vm_pu_close(within 1×10⁻³ p.u. of pandapower) isFalsefor all networks due to the free reactive dispatch — this is expected behaviour.- For pure power flow validation (fixed reactive dispatch), initialise the
qsGvariables from a priorpp.runpp()result usinginit_pyo_from_pp_res.
Key functions
calculate_error_metrics(reference, candidate)
mean_abs, max_abs, rmse, std_abs for a pair of
pd.Series.
compare_results(pp_net, ac_net, delta_keys)
delta_keys = {result_table: [column, ...]}, calls
calculate_error_metrics, and records the index of the worst-case element.