e2nIEE / pandapower

Convenient Power System Modelling and Analysis based on PYPOWER and pandas
https://www.pandapower.org
Other
866 stars 482 forks source link

LoadflowNotConverged using a individually designed distribution grid #130

Open Poldi1912 opened 6 years ago

Poldi1912 commented 6 years ago

Hello,

I have on major problem in my code to conduct a powerflow calculation in pandapower. Apparently, my problem has an issue that it does not converge. Hence, i would like to ask you for any possible help.

FYI: I already tried to set my transformer values fo pfe_kw and vscr_percent to zero, but unfortunately this did not help. I further used the internal diagnostic function in order to identify the issue but apparently non of these served as a solution to let the solver converge.

I deeply appreciate any help from your side and I am sorry for the long code but I thought this might help to follow up on my issue.

Here is the code that i implemented so far and the additional fault report: `
import pandapower as pp import openpyxl as ox

#Load input file as workbook
wb = ox.load_workbook("C://Users//...//03_Analyse//03_Use cases//Use case A//Raw Data//Gridassetinformation.xlsx")
#print (wb.sheetnames)
net = pp.create_empty_network()

#Create medium and low voltage Buses
buses = wb['node']
for m in range(3,buses.max_row+1):
    buses.name = buses.cell(row=m, column=1).value
    if (buses.cell(row=m, column=2).value == 22):
        pp.create_bus(net, name=buses.name, vn_kv=22, type='b')

    elif (buses.cell(row=m, column=2).value == 132):
        pp.create_bus(net, name=buses.name, vn_kv=120, type='b')
    else:
        pp.create_bus(net, name=buses.name, vn_kv=.42, type='b')

#Create an external grid
feeder = wb['network feeder']
feeder.bus = feeder.cell(row=3, column=9).value
feeder.s_sc_max_mva = feeder.cell(row=3, column=4).value
feeder.s_sc_min_mva = feeder.cell(row=3, column=3).value
feeder.rx_max = feeder.cell(row=3, column=8).value
feeder.rx_min = feeder.cell(row=3, column=7).value
feeder.bus = feeder.cell(row=3, column=9).value
feeder.bus = feeder.cell(row=3, column=9).value
bus = pp.get_element_index(net, "bus", feeder.bus)

ext_grid = pp.create_ext_grid(net, bus, vm_pu=1.02, va_degree=0, name='External grid', 
                              s_sc_max_mva=feeder.s_sc_max_mva, s_sc_min_mva=feeder.s_sc_min_mva,
                              rx_max=feeder.rx_max, rx_min=feeder.rx_min)

#Create Lines connected to the MV Buses
mv_lines = wb['line']
for i in range(3,mv_lines.max_row+1):
    mv_lines.from_bus = mv_lines.cell(row=i, column=14).value
    mv_lines.to_bus = mv_lines.cell(row=i, column=16).value
    mv_lines.length = mv_lines.cell(row=i, column=3).value
    mv_lines.r_ohm_per_km = mv_lines.cell(row=i, column=6).value
    mv_lines.x_ohm_per_km = mv_lines.cell(row=i, column=7).value
    mv_lines.c_nf_per_km = mv_lines.cell(row=i, column=8).value
    mv_lines.max_i_ka = mv_lines.cell(row=i, column=12).value
    from_bus = pp.get_element_index(net, "bus", mv_lines.from_bus)
    to_bus = pp.get_element_index(net, "bus", mv_lines.to_bus)    

    if (mv_lines.cell(row=i, column=4).value == 1):
        pp.create_line_from_parameters(net, from_bus, to_bus, length_km=mv_lines.length,
                                       r_ohm_per_km=mv_lines.r_ohm_per_km, 
                                       x_ohm_per_km=mv_lines.x_ohm_per_km, 
                                       c_nf_per_km=mv_lines.c_nf_per_km, 
                                       max_i_ka= mv_lines.max_i_ka,
                                       name='Cable-Line MV%s 22kV' % i, index=None, 
                                       type=None, geodata=None, 
                                       in_service=True, df=1., 
                                       parallel=1, g_us_per_km=0.)
    else:
        pp.create_line_from_parameters(net, from_bus, to_bus, length_km=mv_lines.length,
                                       r_ohm_per_km=mv_lines.r_ohm_per_km, 
                                       x_ohm_per_km=mv_lines.x_ohm_per_km, 
                                       c_nf_per_km=mv_lines.c_nf_per_km, 
                                       max_i_ka= mv_lines.max_i_ka,
                                       name='OH-Line MV%s 22kV' % i, index=None, 
                                       type=None, geodata=None, 
                                       in_service=True, df=1., 
                                       parallel=1, g_us_per_km=0.)

#Create MV/LV Transformers connected to the MV Buses
mv_lv_transformers = wb['tr']
for j in range(3,mv_lv_transformers.max_row+1):
    mv_lv_transformers.hv_bus = mv_lv_transformers.cell(row=j, column=13).value
    mv_lv_transformers.lv_bus = mv_lv_transformers.cell(row=j, column=16).value
    mv_lv_transformers.sn_kva = mv_lv_transformers.cell(row=j, column=5).value
    mv_lv_transformers.vn_hv_kv = mv_lv_transformers.cell(row=j, column=6).value
    mv_lv_transformers.vn_lv_kv = mv_lv_transformers.cell(row=j, column=7).value
    mv_lv_transformers.vscr_percent = mv_lv_transformers.cell(row=j, column=9).value
    mv_lv_transformers.vsc_percent = mv_lv_transformers.cell(row=j, column=8).value
    mv_lv_transformers.pfe_kw = mv_lv_transformers.cell(row=j, column=12).value
    hv_bus = pp.get_element_index(net, "bus", mv_lv_transformers.hv_bus)
    lv_bus = pp.get_element_index(net, "bus", mv_lv_transformers.lv_bus)

    if (mv_lv_transformers.cell(row=j, column=5).value <= 250):
        mv_lv_transformers.i0_percent = 0.32
    elif (250 < mv_lv_transformers.cell(row=j, column=5).value <= 400):
        mv_lv_transformers.i0_percent = 0.3375
    elif (400 < mv_lv_transformers.cell(row=j, column=5).value <= 630):
        mv_lv_transformers.i0_percent = 0.2619
    elif (1000 < mv_lv_transformers.cell(row=j, column=5).value <= 25000):
        mv_lv_transformers.i0_percent = 0.071
    else:
       mv_lv_transformers.i0_percent = 0.2619
    pp.create_transformer_from_parameters(net, hv_bus, lv_bus,
                                          sn_kva=mv_lv_transformers.sn_kva, 
                                          vn_hv_kv=mv_lv_transformers.vn_hv_kv,
                                          vn_lv_kv=mv_lv_transformers.vn_lv_kv, 
                                          vscr_percent=mv_lv_transformers.vscr_percent,
                                          vsc_percent=mv_lv_transformers.vsc_percent, 
                                          pfe_kw=mv_lv_transformers.pfe_kw,
                                          i0_percent=mv_lv_transformers.i0_percent, 
                                          shift_degree=150, in_service=True, 
                                          name='MV/LV Trafo%s' % j, index=None, parallel=1)

#Create Switches
bb_switches = wb['load-switch']
for k in range(3, bb_switches.max_row+1):
    bb_switches.from_bus = bb_switches.cell(row=k, column=2).value
    bb_switches.to_bus = bb_switches.cell(row=k, column=4).value
    bb_switches.name = bb_switches.cell(row=k, column=1).value
    from_bus = pp.get_element_index(net, "bus", bb_switches.from_bus)
    to_bus = pp.get_element_index(net, "bus", bb_switches.to_bus)
    pp.create_switch(net, from_bus, to_bus, et='b', closed=True, type="LS", name=bb_switches.name)     

#Create Loads connected to the LV Buses
lv_loads = wb['load']
for l in range(3, lv_loads.max_row+1):
    lv_loads.bus = lv_loads.cell(row=l, column=4).value
    lv_loads.p_kw = lv_loads.cell(row=l, column=2).value
    lv_loads.q_kvar = lv_loads.cell(row=l, column=3).value

    bus_idx = pp.get_element_index(net, "bus", lv_loads.bus)
    if (lv_loads.cell(row=l, column=7).value == 'telemetered'):
        lv_loads.controllable = True

    else:
        lv_loads.controllable = False

    pp.create_load(net, bus_idx, p_kw=lv_loads.p_kw, q_kvar=lv_loads.q_kvar, 
                   controllable=lv_loads.controllable, index=None, name='LV Load%s' % l)

pp.diagnostic(net, report_style='detailed')
pp.runpp(net, calculate_voltage_angles=True, algorithm='nr', check_connectivity=True, 
max_iteration=10, init="dc")`

Which generates the following fault report in the python console: C:\ProgramData\Anaconda3\lib\site-packages\pandapower\build_branch.py:392: RuntimeWarning: invalid value encountered in sqrt x_sc = np.sign(z_sc) np.sqrt(z_sc 2 - r_sc 2) C:\ProgramData\Anaconda3\lib\site-packages\pandapower\build_branch.py:271: RuntimeWarning: invalid value encountered in true_divide zbc_triangle = zSum_triangle / za_star C:\ProgramData\Anaconda3\lib\site-packages\pandapower\build_branch.py:274: RuntimeWarning: invalid value encountered in true_divide y[tidx] = -2j / zbc_triangle C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\makeYbus_pypower.py:79: RuntimeWarning: invalid value encountered in true_divide Ysf = stat / (branch[:, BR_R] + 1j branch[:, BR_X]) ## series admittance C:\ProgramData\Anaconda3\lib\site-packages\numpy\core_methods.py:26: RuntimeWarning: invalid value encountered in reduce return umr_maximum(a, axis, None, out, keepdims) C:\ProgramData\Anaconda3\lib\site-packages\scipy\sparse\linalg\dsolve\linsolve.py:192: MatrixRankWarning: Matrix is exactly singular warn("Matrix is exactly singular", MatrixRankWarning) C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\newtonpf.py:137: RuntimeWarning: invalid value encountered in true_divide dVm_x, dVa_x = dSbus_dV_numba_sparse(Ybus.data, Ybus.indptr, Ybus.indices, V, V / abs(V), Ibus)

PANDAPOWER DIAGNOSTIC TOOL

Checking for overload...

Overload check failed: Power flow still does not converge with load scaled down to 0.1 percent. Overload check failed: Power flow still does not converge with generation scaled down to 0.1 percent.


Checking switch configuration...

Power flow still does not converge with all switches closed.


END OF PANDAPOWER DIAGNOSTIC C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\makeBdc.py:61: RuntimeWarning: invalid value encountered in true_divide b = stat / branch[:, BR_X] ## series susceptance Traceback (most recent call last):

File "", line 1, in runfile('C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes/GridmodelA.py', wdir='C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes')

File "C:\ProgramData\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile execfile(filename, namespace)

File "C:\ProgramData\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes/GridmodelA.py", line 144, in pp.runpp(net, calculate_voltage_angles=True, algorithm='nr', check_connectivity=True, max_iteration=10, init="dc")

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\run.py", line 252, in runpp _powerflow(net, **kwargs)

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\powerflow.py", line 79, in _powerflow "{1} iterations!".format(algorithm, max_iteration))

LoadflowNotConverged: Power Flow nr did not converge after 10 iterations!

jhmenke commented 6 years ago

C:\ProgramData\Anaconda3\lib\site-packages\pandapower\build_branch.py:392: RuntimeWarning: invalid value encountered in sqrt x_sc = np.sign(z_sc) * np.sqrt(z_sc 2 - r_sc 2)

so r_sc is alrger than z_sc in this case. it may be a line, but likely a transformer parameter is at fault. maybe use the debug mode to figure out which element exactly and then try to work your way backwards where r_sc and z_sc are calculated.

C:\ProgramData\Anaconda3\lib\site-packages\pandapower\build_branch.py:271: RuntimeWarning: invalid value encountered in true_divide zbc_triangle = zSum_triangle / za_star

za_star is zero. this also points to a transformer parameter value

C:\ProgramData\Anaconda3\lib\site-packages\pandapower\build_branch.py:274: RuntimeWarning: invalid value encountered in true_divide y[tidx] = -2j / zbc_triangle

same here

C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\makeYbus_pypower.py:79: RuntimeWarning: invalid value encountered in true_divide Ysf = stat / (branch[:, BR_R] + 1j * branch[:, BR_X]) ## series admittance

both admittances are zero in this case. again, find out with debugging whether it's a line or transformer at fault (i suspect transformer) and work your way backwards. you can also create additional checks in the code before pandapower elements are created, e.g., using assert mv_lines.r_ohm_per_km > 0 to make sure the input parameters are what you expect.

FYI: I already tried to set my transformer values fo pfe_kw and vscr_percent to zero, but unfortunately this did not help.

this will likely cause issues. instead try with different/higher values.

lthurner commented 6 years ago

The problem seems to be in this line:

x_sc = np.sign(z_sc) * np.sqrt(z_sc 2 - r_sc 2)

and all other warnings are follow up issues of this problem. I would suggest debugging to this line and figuring out why this operation fails. I assume either there is a negative value under the square root or there is an nan somewhere in the transformers. This code is used for transformers, so your problem most definitely is with the transformer parameters.

Poldi1912 commented 6 years ago

Thank you, lthurner and jhmenke, I was able to identify the transformer parameter that was inducing the issue. Unfortunately, the powerflow still does not converge.

The console detects the following: """ PANDAPOWER DIAGNOSTIC TOOL

Checking for overload...

Overload check failed: Power flow still does not converge with load scaled down to 0.1 percent. Overload check failed: Power flow still does not converge with generation scaled down to 0.1 percent.


Checking switch configuration...

Power flow still does not converge with all switches closed.


END OF PANDAPOWER DIAGNOSTIC Traceback (most recent call last):

File "", line 1, in runfile('C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes/GridmodelA.py', wdir='C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes')

File "C:\ProgramData\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile execfile(filename, namespace)

File "C:\ProgramData\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes/GridmodelA.py", line 144, in pp.runpp(net, calculate_voltage_angles=True, algorithm='nr', check_connectivity=True, max_iteration=20, init="dc")

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\run.py", line 252, in runpp _powerflow(net, **kwargs)

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\powerflow.py", line 79, in _powerflow "{1} iterations!".format(algorithm, max_iteration))

LoadflowNotConverged: Power Flow nr did not converge after 20 iterations! """

I tried to play with the number of iteration steps but this does not have any impact as well. Are there any other options you can think of that make my powerflow not converge?

Thank you for your help so far!!!

lthurner commented 6 years ago

Do you have unsupplied buses in the grid? You can check that with the function:

pandapower.topology.unsupplied_buses(net)
Poldi1912 commented 6 years ago

Hi lthurner, apparently yes, i identified 3 unsupplied buses while my data input file seems to consider them. Thank you for this new hint!

I will try to figure out what is issuing that the buses aren't recognised to be supplied.

Poldi1912 commented 6 years ago

Hello again, apparentlyit the issue was not imposed by the buses. However, I tried to run the powerflow with a different algorithm (bfsw) and got a new error message saying:

File "C:\ProgramData\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile execfile(filename, namespace)

File "C:\ProgramData\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/Paul Kessler/Documents/Studium/Master/Masterarbeit/E.ON Masterarbeit/03_Analyse/03_Use cases/Use case A/SimulationToolA/Classes/GridmodelA.py", line 172, in pp.runpp(net, calculate_voltage_angles=True, algorithm='bfsw', check_connectivity=True, max_iteration=100, init="flat")

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\run.py", line 252, in runpp _powerflow(net, **kwargs)

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\powerflow.py", line 70, in _powerflow result = _run_pf_algorithm(ppci, net["_options"], **kwargs)

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\powerflow.py", line 95, in _run_pf_algorithm result = _run_bfswpf(ppci, options, **kwargs)[0]

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\run_bfswpf.py", line 409, in _run_bfswpf ppci, DLF, buses_ordered_bfs_nets = _get_bibc_bcbv(ppci, options, bus, branch, G)

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\run_bfswpf.py", line 177, in _get_bibc_bcbv DLF, buses_ordered_bfs_nets = _make_bibc_bcbv(bus, branch, graph)

File "C:\ProgramData\Anaconda3\lib\site-packages\pandapower\pf\run_bfswpf.py", line 148, in _make_bibc_bcbv shape=(nobranch, nobranch))

File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\sparse\compressed.py", line 51, in init other = self.class(coo_matrix(arg1, shape=shape))

File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\sparse\coo.py", line 191, in init self._check()

File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\sparse\coo.py", line 243, in _check raise ValueError('negative column index found')

ValueError: negative column index found

Do you have any hint, what could be the issue for this negative index?

lthurner commented 6 years ago

Do you have any hint, what could be the issue for this negative index?

Not really, but the backward-forward sweep is not as well tested as the Newton-Raphson, so i would really stick with the NR instead of alternate solvers.

You are using very peculiar parameters for runpp:

pp.runpp(net, calculate_voltage_angles=True, algorithm='bfsw', check_connectivity=True, max_iteration=100, init="flat")

typically if voltage angles are calculated you would want to initialize with a dc power flow instead of a flat start, which also the default. If you have convergence issues, i would advice to not calculate voltage angles and see if you can get the power flow to converge like that.

Poldi1912 commented 6 years ago

While debugging I noticed that pandapower apparently confuses my the switches between several buses. Therefore, I always receive "isolated_nodes" and "bus_not_reachable" when the connection between two "nodes"/ "buses" is realized with a switch. Is this a common problem?

As a help, I initiated all my switches as "lines" within pandapower and set very small values for "r_ohm_per_km","x_ohm_per_km" and "length_km" etc... In the end, my powerflow is still not converging but pandapower is at least recognizing the buses as reachable and not isolated.

As I am a bloody beginner in programming, I would be happy if anyone has an idea for the problem.

lthurner commented 6 years ago

While debugging I noticed that pandapower apparently confuses my the switches between several buses. Therefore, I always receive "isolated_nodes" and "bus_not_reachable" when the connection between two "nodes"/ "buses" is realized with a switch. Is this a common problem?

If you can make a small reproducable example of the problem we can look into it. But I doubt pandapower is confusing any buses, because the switch model is actually pretty well tested. I am pretty sure this is a problem with how you input the data. Are you aware of the difference between bus-bus and bus-line switches?

As I am a bloody beginner in programming, I would be happy if anyone has an idea for the problem.

It is really not possible for anyone to debug your code for you. Even if we had the time to do that, its not possible without having the data base you are working off. You will have to provide small reproducable examples of the problem, otherwise there is no way for us to know what is wrong with your code or network.

Poldi1912 commented 6 years ago

First of all, thank you for your effort and fast replies regarding my questions and the overall issue!

I identified the issue of my problem. For the sake of completeness and future newcomers to pandapower, I want to describe the cause of my issue a bit further:

After a bit of debugging, I descried that whenever a switch connected two buses or a bus and a node the connected node/ bus was isolated. I checked my input file and could not locate why this was the case, as the topology is directly drawn from a SCADA system of a DSO.

In the end, it was the input data that was loaded into the pandapower inducing the powerflow to not converge. The DSO handed over the load data including large reactive power values. Setting these values to zero made the powerflow converge and yield in reasonable results.

I still can not explain why these values caused the issue that some buses were isolated tho.

rbolgaryn commented 2 years ago

The issue seems to be still unsolved - the calculation is working as expected in the example shown here, but in a different example the following unexpected behavior can be observed:

The recycle feature must be investigated to find the root cause of this issue.