Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lightsim2grid: changed checks for lightsim2grid #1455

Merged
merged 33 commits into from
Feb 3, 2022

Conversation

rbolgaryn
Copy link
Member

added default "auto" option for lightsim2grid that decides whether to use it silently, added lightsim2grid to the GitHub CI for Python 3.9

… option for lightsim2grid that decides whether to use it silently, added lightsim2grid to the GitHub CI for Python 3.9
@codecov
Copy link

codecov bot commented Jan 20, 2022

Codecov Report

Merging #1455 (85f91d6) into develop (7f5db2d) will decrease coverage by 0.12%.
The diff coverage is 60.00%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #1455      +/-   ##
===========================================
- Coverage    87.28%   87.15%   -0.13%     
===========================================
  Files          168      168              
  Lines        17225    17231       +6     
===========================================
- Hits         15034    15017      -17     
- Misses        2191     2214      +23     
Impacted Files Coverage Δ
pandapower/pf/create_jacobian_numba.py 100.00% <ø> (ø)
pandapower/pf/runpp_3ph.py 96.80% <ø> (ø)
pandapower/run.py 96.82% <ø> (ø)
setup.py 0.00% <ø> (ø)
pandapower/auxiliary.py 87.85% <36.00%> (-0.33%) ⬇️
pandapower/pf/run_newton_raphson_pf.py 92.24% <75.00%> (+0.77%) ⬆️
pandapower/pf/create_jacobian.py 95.00% <100.00%> (ø)
pandapower/pf/makeYbus_numba.py 100.00% <100.00%> (ø)
pandapower/pypower/makeYbus.py 100.00% <100.00%> (ø)
pandapower/pypower/newtonpf.py 93.47% <100.00%> (-0.08%) ⬇️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7f5db2d...85f91d6. Read the comment docs.

…pf for distributed_slack only. this reduced the number of failing tests but still WIP
@rbolgaryn
Copy link
Member Author

# first
net = example_simple()
pp.runpp(net, distributed_slack=True)  # works
pp.runpp(net, distributed_slack=True, numba=False)  # LoadFlowNotConverged

#second
pp.runpp(net, distributed_slack=True)  # works
pp.runpp(net, distributed_slack=True, numba=False, init="results")  # works

#third
net2 = example_simple()
pp.runpp(net, distributed_slack=True)  # works
pp.runpp(net2, distributed_slack=True, lightsim2grid=False)  # works
assert_res_equal(net, net2)  # works

Some observations about the failing tests:

For comparison, and because of the implementation of newtonpf_new, here we set the parameter distributeed_slack to True.

The load flow fails (solver does not converge in lightsim2grid) in many instances.
It seems to have something to do with numba. I could not identify any differences in slack_weights, ref, pv, pq, Ybus, V0, Sbus, max_it, tol. After just one iteration, the values in J are the same. However, after 10 iterations, the values of the Jacobian are different (for with and without numba). I do not understand why this is relevant, because numba is only used in the pandapower part of the code. lightsim2grid has its own code to generate the Jacobian.

First: the example demonstrates how the calculation works for numba=True and fails for numba=False. lightsim2grid is used in both instances.

Second: the example demonstrates that with init="results" solver in lightsim2grid converges even with numba=False. Must be because the algorithm doesn't even enter the loop and just exits with a valid solution right away.

Third: results match with lightsim2grid and without lightsim2grid.

@BDonnot can you please help with debugging?

Can you reproduce this behavior? Do you have an idea, what could cause this error? can it be something related to types etc.?

Roman

@BDonnot
Copy link
Contributor

BDonnot commented Jan 24, 2022

Hello,

Can I have a way to import the "example_simple()" function ? I cannot reproduce the bug here without this function :-/

@rbolgaryn
Copy link
Member Author

rbolgaryn commented Jan 24, 2022

Hi @BDonnot ,

the example_simple function is in pandapower.networks (should be imported extra):

import pandapower as pp
import pandapower.networks
net = pp.networks.example_simple()

Roman

@BDonnot
Copy link
Contributor

BDonnot commented Jan 24, 2022

Hello,

I cannot reproduce the problem on my dev machine (ubuntu 20.04, python3.8)

Can you launch:

print("now with example provided")
import pandapower as pp
import lightsim2grid
import pdb
import pandas as pd
from pandapower.networks import example_simple
import numpy as np
import pandas as pd
print(f"{np.__version__ = }")
print(f"{pd.__version__ = }")
print(f"{lightsim2grid.__version__ = }")
print(f"{pp.__version__ = }")
net = example_simple()
pp.runpp(net, distributed_slack=True)  # works
pp.runpp(net, distributed_slack=True, numba=False)  # LoadFlowNotConverged
assert net.converged

#second
pp.runpp(net, distributed_slack=True)  # works
pp.runpp(net, distributed_slack=True, numba=False, init="results")  # works
assert net.converged

#third
net2 = example_simple()
pp.runpp(net, distributed_slack=True)  # works
pp.runpp(net2, distributed_slack=True, lightsim2grid=False)  # works
assert net2.converged
# assert_res_equal(net, net2)  # works  # -> not imported so skipping it
assert net.res_gen.equals(net2.res_gen)
assert net.res_load.equals(net2.res_load)
assert net.res_line.equals(net2.res_line)
print("everything match !")

And give me the output ?

Also, can you give me your setup (os and python version please)

FYI for me the above script gives:

now with example provided
np.__version__ = '1.21.5'
pd.__version__ = '1.4.0'
lightsim2grid.__version__ = '0.6.0'
pp.__version__ = '2.7.0'
/home/benjamin/Documents/pp_test/venv/lib/python3.8/site-packages/pandapower/create.py:509: FutureWarning: pandas.Int64Index is deprecated and will be removed from pandas in a future version. Use pandas.Index with the appropriate dtype instead.
  net[s] = pd.DataFrame(zeros(0, dtype=net[s]), index=pd.Int64Index([]))
...
[Above warning at least 50 times !]
everything match !

Also it's unclear for me what you want to test exactly.

Your are totally correct, lightsim2grid does not rely on numba at all. If the flag "numba=True" changes something, then it's probably something given as input of lightsim2grid, for example the init voltages.

@rbolgaryn
Copy link
Member Author

I have this output:

now with example provided
np.__version__ = '1.21.5'
pd.__version__ = '1.3.5'
lightsim2grid.__version__ = '0.6.0'
pp.__version__ = '2.7.1.dev1'
Traceback (most recent call last):
  File "C:\ProgramData\Miniconda3\envs\pandapower\lib\site-packages\IPython\core\interactiveshell.py", line 3251, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-12c50577f436>", line 15, in <module>
    pp.runpp(net, distributed_slack=True, numba=False)  # LoadFlowNotConverged
  File "C:\Users\rbolgaryn\repos\pandapower\pandapower\run.py", line 231, in runpp
    _powerflow(net, **kwargs)
  File "C:\Users\rbolgaryn\repos\pandapower\pandapower\powerflow.py", line 86, in _powerflow
    _ppci_to_net(result, net)
  File "C:\Users\rbolgaryn\repos\pandapower\pandapower\powerflow.py", line 188, in _ppci_to_net
    raise LoadflowNotConverged("Power Flow {0} did not converge after "
pandapower.powerflow.LoadflowNotConverged: Power Flow nr did not converge after 10 iterations!

@rbolgaryn
Copy link
Member Author

My Python version is 3.9 on Windows 10.
Also, the tests fail on the GitHub Actions servers, which must be linux.

The difference in behavior is very confusing.

@BDonnot
Copy link
Contributor

BDonnot commented Jan 24, 2022

Oh ok it was my mistake, I did not installed your pandapower version by the default one and now i'm able to reproduce it and I get the error:

  File "bug_pp.py", line 12, in <module>
    pp.runpp(net, distributed_slack=True, numba=False)  # LoadFlowNotConverged
  File "pp_test/pandapower/run.py", line 233, in runpp
    _powerflow(net, **kwargs)
  File "pp_test/pandapower/powerflow.py", line 86, in _powerflow
    _ppci_to_net(result, net)
  File "pp_test/pandapower/powerflow.py", line 188, in _ppci_to_net
    raise LoadflowNotConverged("Power Flow {0} did not converge after "
pandapower.powerflow.LoadflowNotConverged: Power Flow nr did not converge after 10 iterations!

I'll try to see what is the cause of it

@rbolgaryn
Copy link
Member Author

I also see the same behavior in linux, with Python 3.9.9:

now with example provided
np.version = '1.21.5'
pd.version = '1.4.0'
lightsim2grid.version = '0.6.0'
pp.version = '2.7.1.dev1'

@BDonnot
Copy link
Contributor

BDonnot commented Jan 24, 2022

As i thought, the difference is in pandapower and not in lightsim2grid.

The Ybus that is initialized (given as input in the newton functions) is not exactly the same if you pass numba=True or numba=False

When it is initialized with numba=False it appears the Ybus is not correct and has some issues.

For example, just by printing it:

def _run_ac_pf_without_qlims_enforced(ppci, options):
    makeYbus, pfsoln = _get_numba_functions(ppci, options)

    baseMVA, bus, gen, branch, ref, pv, pq, _, _, V0, ref_gens = _get_pf_variables_from_ppci(ppci)

    ppci, Ybus, Yf, Yt = _get_Y_bus(ppci, options, makeYbus, baseMVA, bus, branch)

    # compute complex bus power injections [generation - load]
    Sbus = _get_Sbus(ppci, options["recycle"])


    # run the newton power flow
    import numpy as np
    print(f"{np.sum(np.abs(Ybus)) = }")  # the line I added

    [rest of the function that i do not copy !]

And this simple snippet works:

import pandapower as pp
from pandapower.networks import example_simple
pp.runpp(net, distributed_slack=True, numba=False, lightsim2grid=True)  # works only with the "print" case
pp.runpp(net, distributed_slack=True, numba=True, lightsim2grid=True)  # works in both cases

I have absolutely no idea why printing something changes the behaviour...

@BDonnot
Copy link
Contributor

BDonnot commented Jan 24, 2022

I just tried with (so it does not print anything):

def _run_ac_pf_without_qlims_enforced(ppci, options):
    makeYbus, pfsoln = _get_numba_functions(ppci, options)

    baseMVA, bus, gen, branch, ref, pv, pq, _, _, V0, ref_gens = _get_pf_variables_from_ppci(ppci)

    ppci, Ybus, Yf, Yt = _get_Y_bus(ppci, options, makeYbus, baseMVA, bus, branch)

    # compute complex bus power injections [generation - load]
    Sbus = _get_Sbus(ppci, options["recycle"])


    # run the newton power flow
    import numpy as np
    my_sum = np.sum(np.abs(Ybus))
    if options["lightsim2grid"] and not options["distributed_slack"]:
        V, success, iterations, J, Vm_it, Va_it = newton_ls_old(Ybus, Sbus, V0, pv, pq, ppci, options)
    elif options["lightsim2grid"]:
        V, success, iterations, J, Vm_it, Va_it = newton_ls(Ybus, Sbus, V0, ref, pv, pq, ppci, options)
    else:
        V, success, iterations, J, Vm_it, Va_it = newtonpf(Ybus, Sbus, V0, ref, pv, pq, ppci, options)
    [etc.]

And it works too, I don't know what happens when the Ybus matrix is filled with python and not with numba :-/ Code seems to work, but data is somehow not correct...

Can you try if your tests pass with that ? (so that we can maybe further look at the issue when it's not done...)

@rbolgaryn
Copy link
Member Author

I can confirm that the snippet also works for me

@BDonnot
Copy link
Contributor

BDonnot commented Jan 26, 2022

It's still super weird, but I guess keeping it this way won't hurt pandapower too much.

I don't have any clue on what this does under the hood to solve the issue...

@rbolgaryn
Copy link
Member Author

There are still some failing tests, especially in the distributed slack functionality. I will take a look further

@BDonnot
Copy link
Contributor

BDonnot commented Jan 26, 2022

Let me know if I can be of further assistance

@BDonnot
Copy link
Contributor

BDonnot commented Feb 1, 2022

Can you send me a log or something on why it fails?

@rbolgaryn
Copy link
Member Author

you should be able to see in the test details below in a moment

@BDonnot
Copy link
Contributor

BDonnot commented Feb 1, 2022

Hummm this appear to be an issue with 3.7 and the f string in lightsim2grid.

Can you remove 3.7 to see if other tests break?

I'll have a look tomorrow

@rbolgaryn
Copy link
Member Author

It seems to work for 3.8 and 3.9!

@BDonnot
Copy link
Contributor

BDonnot commented Feb 1, 2022

Great news. We're almost there!

It's super weird it does nor work with 3.7 because... Well I compiled the package on python 3.7...

Anyway, I'll have a look to confirm that tomorrow and fix it if there's issue.

Thanks for all the efforts and patience

@rbolgaryn
Copy link
Member Author

Thank you too!

I will rollback the python versions for now, and skip lightsim2grid for python 3.6.

… (to avoid it being installed in GitHub Actions). After dropping 3.6 we will include it in all but then uninstall for the tests for some environments
@BDonnot
Copy link
Contributor

BDonnot commented Feb 2, 2022

I found out what the bug was in python3.7.

I fixed it and added a test that the package can be loaded in the CI (somehow I did not do this test...)

I'll release a new version (0.6.1.post1) this morning.

I confirm that I will not add python 3.6 support for lightsim2grid :

Note: The release you are looking at is Python 3.6.15, the final security bugfix release for the legacy 3.6 series which has now reached end-of-life and is no longer supported. See the downloads page for currently supported versions of Python. The final bugfix release for 3.6 was 3.6.8.

(from https://www.python.org/downloads/release/python-3615/ )

@BDonnot
Copy link
Contributor

BDonnot commented Feb 2, 2022

@rbolgaryn It should work with 3.7 now :-) (release done)

@rbolgaryn
Copy link
Member Author

Thank you very much, @BDonnot !

@rbolgaryn
Copy link
Member Author

rbolgaryn commented Feb 2, 2022

Here some timings (on a Win10 laptop, Python 3.9, lightsim2grid built with cmake according to the guide from the documentation):

import pandapower as pp
import pandapower.networks

# case9241pegase:
net = pp.networks.case9241pegase()
pp.runpp(net, numba=True, lightsim2grid=False)

# without lightsim2grid
%timeit pp.runpp(net, numba=True, lightsim2grid=False)
340 ms ± 13.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

net._ppc["et"]
0.313649500021711


# with lightsim2grid
%timeit pp.runpp(net, numba=True, lightsim2grid=True)
127 ms ± 2.66 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
net._ppc["et"]
0.10265469993464649


# case39:
net = pp.networks.case39()

# without lightsim2grid:
%timeit pp.runpp(net, numba=True, lightsim2grid=False)
9.02 ms ± 60.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
net._ppc["et"]
0.0033928999910131097

# with lightsim2grid:
%timeit pp.runpp(net, numba=True, lightsim2grid=True)
8.26 ms ± 236 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
net._ppc["et"]
0.0023731000255793333


# case 118:
net = pp.networks.case118()

# without lightsim2grid:
%timeit pp.runpp(net, init="flat", numba=True, lightsim2grid=False)
8.2 ms ± 413 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

net._ppc["et"]
0.0032513999613001943

# with lightsim2grid:
%timeit pp.runpp(net, init="flat", numba=True, lightsim2grid=True)
6.54 ms ± 166 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

net._ppc["et"]
0.002079599886201322

Seems that the benefit in the performance is there, but not in the same magnitude as shown in benchmarks of lightsim2grid.

The explanation is probably that the overhead in pandapower is still quite seizable, and it weighs on the total execution time (the performance boost for a small grid is not very high, but with a large grid is twice as fast - supports this point).
The "et" time (power flow time as returned by the newtonpf function) without lightsim2grid is ~3 times longer for the large grid, and not very much different for the small grid.

The larger the grid, the higher the benefit will be that a pandapower user will notice.

Dear @BDonnot , do the timings look reasonable to you?

EDIT: when using snakeviz for profiling, the timings look different: with pegase grid, the difference in newton is 196 ms vs. 41 ms, (4,8 times) and the overall time difference is 272 ms vs. 91 ms (3 times).

@rbolgaryn
Copy link
Member Author

Here a snakeviz vizualization for case9241pegase:

without lightsim2grid:

grafik

With ligtsim2grid:

grafik

@BDonnot
Copy link
Contributor

BDonnot commented Feb 2, 2022

What you showed above is that it takes lightsim2grid 0.04s instead of 0.22 (so the speed up for the solver part is more than 5x)

And probably some speed can be gained if the solver isn't initialized each time on lightsim2grid.

I'll run some benchmarks on my machine with this branch to see if there's some things to win still.

Apparently though a big amount of time is spent not in the solver but in the elsewhere in the code (at least in this very large example you provided)

I'm also curious where the time is spent in newton_pf_new. But I'm not surprised that 40 ms is taken to run an ac powerflow on a system with approx 10k buses

@BDonnot
Copy link
Contributor

BDonnot commented Feb 2, 2022

There are still huge penalty in the timings there.

For example if I launch this code:

import pandapower as pp
import pandapower.networks
import time
import sys

nb_repeat = 10
# case9241pegase:
for nm_ in ["case39", "case118", "case9241pegase"]:
    net = getattr(pp.networks, nm_) () #.case9241pegase()

    # "compile" it with numba (first call always slower)
    pp.runpp(net, init="flat", numba=True, lightsim2grid=False)
    print(f"for {nm_}")
    beg_ = time.process_time()
    for _ in range(nb_repeat):
        pp.runpp(net, init="flat", numba=True, lightsim2grid=False)
    end_ = time.process_time()
    print(f"\t without ls: {1000. * (end_- beg_) / nb_repeat :.2f} ms")
    # without lightsim2grid

    beg_ = time.process_time()
    for _ in range(nb_repeat):
        pp.runpp(net, init="flat", numba=True, lightsim2grid=True)
    end_ = time.process_time()
    print(f"\t with ls: {1000. * (end_- beg_) / nb_repeat:.2f} ms")

And I modify the "newton_pf" function just print the time spent in "solver.solve" like this:

def newtonpf_new(Ybus, Sbus, V0, ref, pv, pq, ppci, options):
    import time
    super_beg = time.perf_counter()
    max_iteration = options["max_iteration"]
    tolerance_pu = options['tolerance_mva']  # / ppci["baseMVA"]

    try:
        # lazy import for earlier pandapower version (without distributed slack):
        from pandapower.pypower.idx_bus import SL_FAC
        # contribution factors for distributed slack:
        slack_weights = ppci['bus'][:, SL_FAC].astype(np.float64)
    except ImportError:
        # earlier version of pandapower
        warnings.warn("You are using a pandapower version that does not support distributed slack. We will attempt to "
                      "replicate this with lightsim2grid.")
        ref, slack_weights = _isolate_slack_ids(Sbus, pv, pq)
    
    # initialize the solver and perform some sanity checks
    solver = _get_valid_solver(options, Ybus)
    
    # do the newton raphson algorithm
    beg_ = time.perf_counter()
    solver.solve(Ybus, V0, Sbus, ref, slack_weights, pv, pq, max_iteration, tolerance_pu)
    end_ = time.perf_counter()
    
    # extract the results
    Va = solver.get_Va()
    Vm = solver.get_Vm()
    V = Vm * np.exp(1j * Va)
    J = solver.get_J()
    converged = solver.converged()
    iterations = solver.get_nb_iter()
    print(f"\t\tsolver.solve : {1000. * (end_ - beg_) :.2f} ms")

    Vm_it = None
    Va_it = None
    super_end = time.perf_counter()
    print(f"\t\ttotal time : {1000. * (super_end - super_beg) :.2f} ms")
    
    return V, converged, iterations, J, Vm_it, Va_it

I get the following results:

for case39
	 without ls: 17.74 ms
		solver.solve : 0.30 ms
		total time : 0.56 ms
		solver.solve : 0.22 ms
		total time : 0.45 ms
		solver.solve : 0.32 ms
		total time : 0.62 ms
		solver.solve : 0.30 ms
		total time : 0.55 ms
		solver.solve : 0.24 ms
		total time : 0.50 ms
		solver.solve : 0.31 ms
		total time : 0.64 ms
		solver.solve : 0.37 ms
		total time : 0.75 ms
		solver.solve : 0.37 ms
		total time : 0.72 ms
		solver.solve : 0.36 ms
		total time : 0.70 ms
		solver.solve : 0.29 ms
		total time : 0.51 ms
	 with ls: 14.99 ms
for case118
	 without ls: 15.85 ms
		solver.solve : 0.67 ms
		total time : 0.95 ms
		solver.solve : 0.51 ms
		total time : 0.74 ms
		solver.solve : 0.49 ms
		total time : 0.76 ms
		solver.solve : 0.49 ms
		total time : 0.71 ms
		solver.solve : 0.59 ms
		total time : 0.88 ms
		solver.solve : 0.49 ms
		total time : 0.72 ms
		solver.solve : 0.51 ms
		total time : 0.73 ms
		solver.solve : 0.53 ms
		total time : 0.80 ms
		solver.solve : 0.50 ms
		total time : 0.72 ms
		solver.solve : 0.50 ms
		total time : 0.78 ms
	 with ls: 14.55 ms
for case9241pegase
	 without ls: 405.55 ms
		solver.solve : 66.47 ms
		total time : 68.62 ms
		solver.solve : 63.70 ms
		total time : 65.49 ms
		solver.solve : 63.05 ms
		total time : 64.88 ms
		solver.solve : 63.55 ms
		total time : 65.35 ms
		solver.solve : 63.31 ms
		total time : 65.12 ms
		solver.solve : 64.02 ms
		total time : 65.80 ms
		solver.solve : 62.92 ms
		total time : 64.68 ms
		solver.solve : 63.29 ms
		total time : 65.09 ms
		solver.solve : 64.51 ms
		total time : 66.31 ms
		solver.solve : 64.99 ms
		total time : 66.75 ms
	 with ls: 115.95 ms

So basically, the time spent to perform the powerflow (for case39 for example) is around 0.2ms (eg 0.0002456940710544586 s) while the total time seen from pandapower is 15ms.

The time I measure in newton_pf_new is around 0.56 ms

This means that pandapower is taking 14.5ms to do other things that I don't really know. This is really suprising

Also, what is exactly measured by net._ppc["et"] ? I'm confused to see such difference between measures in the function and by the net._ppc["et"]

@BDonnot
Copy link
Contributor

BDonnot commented Feb 2, 2022

I "snakewized" the code above (only for the part that runs the powerflow:

import pandapower as pp
import pandapower.networks
import time
import sys
import cProfile

def run_without_ls(net, nb_repeat):
    for _ in range(nb_repeat):
        pp.runpp(net, init="flat", numba=True, lightsim2grid=False)


def run_with_ls(net, nb_repeat):
    for _ in range(nb_repeat):
        pp.runpp(net, init="flat", numba=True, lightsim2grid=True)

nb_repeat = 10
# case9241pegase:
for nm_ in ["case39", "case118", "case9241pegase"]:
    net = getattr(pp.networks, nm_) () #.case9241pegase()

    # "compile" it with numba (first call always slower)
    pp.runpp(net, init="flat", numba=True, lightsim2grid=False)
    print(f"for {nm_}")

    # with numba only
    cp = cProfile.Profile()
    cp.enable()
    beg_ = time.process_time()
    run_without_ls(net, nb_repeat)
    end_ = time.process_time()
    cp.disable()
    nm_out = f"{nm_}_pure_pp.prof"
    cp.dump_stats(nm_out)
    print(f"\t without ls: {1000. * (end_- beg_) / nb_repeat :.2f} ms")

    # with lighsim2grid
    cp = cProfile.Profile()
    cp.enable()
    beg_ = time.process_time()
    run_with_ls(net, nb_repeat)
    end_ = time.process_time()
    cp.disable()
    nm_out = f"{nm_}_pp_ls.prof"
    cp.dump_stats(nm_out)
    print(f"\t with ls: {1000. * (end_- beg_) / nb_repeat:.2f} ms")

sys.exit()

And for pandapower / numba i got (for case39) :
perf_without_ls

And for pandapower / lightsim2grid i get (for case39 again) :
perf_with_ls

As you can clearly see above, the vast majority of times is spent in utility functions and not in performing the actual computation.

The "newton_pf_new" in this case takes 0.3 ms out of the 111ms in total (for this case) so less than 3% of the time (with pure numba it's 14% of the time -> speed up of approximately 5x-6x). But as it concerns only 20% of the total time, overall speed up is ridiculous.

If you want to speed up your computation, you might either want to optimize the remaining 97% of the code or use lightsim2grid (or if you want to keep python, use grid2op) to achieve better speed ups.

@rbolgaryn
Copy link
Member Author

rbolgaryn commented Feb 2, 2022

Indeed, pandapower spends a lot of time with utility functions.

For a small grid, the "productive time" constitutes about 2-2.5 % (over 10 % without lightsim2grid).

For the pegase grid, lightsim2grid constitutes about 38 % of the total time. For comparison, without lightsim2grid it is over 76 %.

If you want to speed up your computation, you might either want to optimize the remaining 97% of the code or use lightsim2grid (or if you want to keep python, use grid2op) to achieve better speed ups.

Absolutely

…tion); added a test for lightsim2grid option; raise NotImplementedError if lightsim2grid == True but is not supported (set to False silently if "auto")
@rbolgaryn
Copy link
Member Author

we decided for now to not include lightsim2grid, it makes it easier to test with/without in GitHubActions. Also we will accumulate more practical testing over time.

@BDonnot
Copy link
Contributor

BDonnot commented Feb 2, 2022

Up to you :-)

@rbolgaryn rbolgaryn merged commit 12f9620 into e2nIEE:develop Feb 3, 2022
@rbolgaryn rbolgaryn deleted the lightsim2grid branch February 3, 2022 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants