Comparison with pypowsybl default load-flow
In this section of the documentation we attempt to compare lightsim2grid and the default implementation of pypowsybl (which is OLF - Open Load Flow <https://github.com/powsybl/powsybl-open-loadflow>__)
All the tests were conducted on the same laptop and on publically available grid:
ieee 9 bus
ieee 14 bus
ieee 30 bus
ieee 57 bus
ieee 118 bus
ieee 300 bus
In all cases, the lightsim2grid gridmodel (lightsim2grid internal representation of a powergrid) were initialized from the pypowsybl grid.
Disclaimer
Compared to pypowsybl, lightsim2grid has only a very (very) limited number of possible behaviour.
Pypowsybl is likely to be more accurate (if parametrized properly) for industrial grid as it can emulate the behaviour of much more elements in much more detail than lightsim2grid.
For example, lighsim2grid does not look at the “reactive power limits” of generators, pypowsybl (open load-flow) can. LightSim2Grid does not change the tap ratio of any transformers during computation, pypowsybl is perfectly able to do that, when the slack bus is distributed in lightsim2grid, lightsim2grid does not check whether or not the generators can produce / absorb the the active power they are supposed to, pypowsybl is able to dynamically meet this criteria etc. etc.
Also, we want to note that the comparison here will limit to computations that both lightsim2grid and pypowsybl are able to perform. At time of writing, pypowsybl could do many more things than lightsim2grid.
Important
The overall message of this page is not to show that lightsim2grid should be prefered to pypowsybl.
Its goal is rather to explain how to get consistent results between pypowsybl and lightsim2grid.
Methodology
The results will show the difference between pypowsybl and lightsim2grid when running the same simulation (an AC powerflow) on the same grid.
It will expose:
the parameters used to initialize the lightsim2grid gridmodel
the parameters used to run the powerflow computation with pypowsybl
the time it takes to perform these powerflows in different settings
the mismatch of the voltage angle (in radian) and the voltage angle (in per unit) at each bus of the grid (average and max value)
Reproduce the results
You can run the example by running the script:
For example:
Load-flow parameters
The parameters used to compute the powerflow in these examples are:
import pypowsybl.loadflow as pypow_lf
params = pypow_lf.Parameters(
voltage_init_mode=pypow._pypowsybl.VoltageInitMode.UNIFORM_VALUES,
transformer_voltage_control_on=False,
use_reactive_limits=False,
phase_shifter_regulation_on=False,
twt_split_shunt_admittance=True,
shunt_compensator_voltage_control_on=False,
read_slack_bus=False,
write_slack_bus=True,
distributed_slack=False,
dc_use_transformer_ratio=True,
hvdc_ac_emulation=False,
dc_power_factor=1.,
provider_parameters={
"useActiveLimits": "false",
"useReactiveLimits": "false",
"svcVoltageMonitoring": "false",
"voltageRemoteControl": "false",
"writeReferenceTerminals": "false",
"slackBusSelectionMode" : "NAME",
"slackBusesIds" : "VL69_0", # DEPENDS ON CASE_NAME: for case 118
"voltagePerReactivePowerControl": "false",
"generatorReactivePowerRemoteControl": "false",
"secondaryVoltageControl": "false",
}
)
Important
As you notice from these parameters, a lot of the simulation capacity of pypowsybl are switched off when using lightsim2grid.
Note
If you are interested in an “abalation study” on the impact of certain parameters above, let us know, for example with a github issue or by reaching out on discord.
Results
The benchmarks were run on:
date: 2025-12-08 14:24 CET
system: Linux 6.8.0-60-generic
OS: ubuntu 22.04
processor: 13th Gen Intel(R) Core(TM) i7-13700H
python version: 3.12.8.final.0 (64 bit)
numpy version: 2.3.5
pandas version: 2.3.3
pypowsybl version: 1.13.0
lightsim2grid version: 0.11.0
lightsim2grid extra information:
klu_solver_available: True
nicslu_solver_available: False
cktso_solver_available: False
compiled_march_native: True
compiled_o3_optim: True
The results were obtained by launching:
And formatting the results in the table below.
Precision of lightsim2grid
On average (across all buses) the errors were:
case name |
angle (rad) |
magnitude (pu) |
|---|---|---|
ieee9 |
1.82e-08 |
1.15e-08 |
ieee14 |
9.70e-10 |
1.27e-09 |
ieee57 |
1.63e-07 |
2.71e-07 |
ieee118 |
1.06e-07 |
3.15e-09 |
ieee300 |
3.10e-07 |
1.75e-08 |
Maximum error, for all buses:
case name |
angle (rad) |
magnitude (pu) |
|---|---|---|
ieee9 |
3.35e-08 |
2.65e-08 |
ieee14 |
2.35e-09 |
2.92e-09 |
ieee57 |
9.54e-07 |
1.20e-06 |
ieee118 |
2.54e-07 |
6.92e-08 |
ieee300 |
3.80e-07 |
1.59e-07 |
As we can notice in the tables above, the results match up to the solver precisions (set to 1e-6 for lightsim2grid).
On these grids, lightsim2grid and pypowsybl give the same exact results.
Computation times (1 powerflow)
In this part, we report the time to compute the initial powerflow, right after the initialization of the grid for both lightsim2grid and pypowsybl.
The timings reported here are measured from python using “time.perf_counter()” before and after the computation are performed.
Only the time to perform the powerflow is measured. In particular, the time to read back the data is excluded.
Times are expressed in ms.
case name |
lightsim2grid |
pypowsybl |
|---|---|---|
ieee9 |
1.32e-01 |
4.80e+00 |
ieee14 |
1.35e-01 |
3.74e+00 |
ieee57 |
4.18e-01 |
4.14e+00 |
ieee118 |
6.89e-01 |
5.77e+00 |
ieee300 |
2.27e+00 |
1.78e+01 |
For this initial computation, lightsim2grid seems to be between 30 and 5x faster than pypowsybl.
Warning
This is not fair for pypowsybl.
Pypowsybl is not optimized only for speed and can simulate much more complex grids with an higher fidelity, which is not reported here.
Computation times (100 powerflows)
In this section, we compare the capacity of lightsim2grid and pypowsybl to perform successive powerflow computation when only the loads are modified.
This comparison is done when using “raw” lightsim2grid / pypowsybl code, without trying to achieve the “best performance”. Some performance gain could be achieved with different optimizations, for example by recycling previous results (avoiding to allocate memory, preventing copy, re use of some matrix strucure, taking advantage of the linear solver and avoid costly call when performing some factorization etc.)
The results in the table bellow are given in ms and report the average time it took to perform the 100 powerflows.
case name |
lightsim2grid |
pypowsybl |
|---|---|---|
ieee9 |
1.72e-02 |
6.75e-01 |
ieee14 |
2.77e-02 |
8.38e-01 |
ieee57 |
1.38e-01 |
1.50e+00 |
ieee118 |
2.90e-01 |
2.53e+00 |
ieee300 |
1.74e+00 |
5.70e+00 |
Computation times security analysis
In this setting, we compare the time it takes to run a “contingency analysis” by simulating, in turn, the disconnection of every lines or transformer on the grid.
The table here is obtained by using contingencyAnalysis module of lightsim2grid and the pypowsybl.security module from pypowsybl.
The table below provides the average time it takes to simulate the effect of 1 contingency in ms. We don’t measure the time taken to compute the flows from the resulting voltages.
case name |
lightsim2grid |
pypowsybl |
|---|---|---|
ieee9 |
1.55e-02 |
6.35e-01 |
ieee14 |
2.28e-02 |
1.74e-01 |
ieee57 |
1.36e-01 |
1.86e-01 |
ieee118 |
2.04e-01 |
3.41e-01 |
ieee300 |
9.99e-01 |
1.30e+00 |