Repository: e2nIEE/pandapower

Issue:
NaN results in branch current
Running a powerflow with oos buses  (BUS_TYPE=NONE) in the ppc results in warnings when calculating the branch results because theses buses have no voltage results:

```
RuntimeWarning: invalid value encountered in reduce
    return umr_maximum(a, axis, None, out, keepdims)
```

A possible fix is in https://github.com/WinfriedL/pandapower/commit/0f09276c3f2bb1544acb8bd2d42c9980b15902e5

Not sure if this is the best solution...


Discussion:
I also remember there was some inconsistency in the branch results . I think out_of_service lines have a loading of zero percent, while disconnected lines have nan or something like that? Is this issue related?
> I think out_of_service lines have a loading of zero percent, while disconnected lines have nan or something like that? Is this issue related?

Yes I think this exactly the issue.

Islolated Lines have no voltage result (nan) at the from/to bus, so dividing s_ft (which is zero) by u_ft gives nan results for i_ft and loading_percent.

The question is if nan is a valid powerflow result for isolated buses/lines. If not, maybe there should be no nan result for the bus voltage in the first place. However, a 'correct' voltage result for isolated buses would be zero, but this would also lead to nan results for lines.

Maybe a better defined approach would be 
`i_ft = np.where(s_ft==0., 0., s_ft * 1e-3 / u_ft / np.sqrt(3))`
 instead of brute force filling all nan and inf values...

If nan results are valid, maybe the warning should be suppressed with np.seterr()?
After talking to @SteffenMeinecke , the issue that I remembered was that lines with two open switches at both sides have a loading of zero, while all other disconnected/out of service lines have nan. This is a different issue that comes from the fact that we explicitely deal with the "open switches at both sides of the line" case as a special case. So its not exactly the same issue, but related.

> The question is if nan is a valid powerflow result for isolated buses/lines. If not, maybe there should be no nan result for the bus voltage in the first place. However, a 'correct' voltage result for isolated buses would be zero, but this would also lead to nan results for lines.

Its true that it would be physically correct to say a disconnected bus has zero voltage, but one could also argue that the power flow doesn't calculate a voltage value for that bus, therefore no number is assigned. From a practical perspective, I like the clear differentiation between "result" (a number) and "no result" (not a number). It wouldn't be very practical always having to filter out the 0 values when calculating for example the minimum voltage or medium line loading in a grid. 

> If nan results are valid, maybe the warning should be suppressed with np.seterr()?

That however changes the behaviour numpy-wide even outside pandapower. What version of numpy are using btw, because I can't reproduce the warning with numpy 1.14.5. Does this:
```
np.array([1,np.nan,3]) / np.array([3,4,np.nan])
```
give a warning for you? Or am looking at the wrong case here?
> Does this:
np.array([1,np.nan,3]) / np.array([3,4,np.nan])
give a warning for you? Or am looking at the wrong case here?

No, the line giving the warning is in fact this one:
https://github.com/e2nIEE/pandapower/blob/5516e064f6e807ab38e4bc2f28f5239ea4627341/pandapower/results_branch.py#L66

I should have mentioned that before, sorry. 

> I like the clear differentiation between "result" (a number) and "no result" (not a number)

So the issue would be how to get np.max()  to return nan, but not issue a warning about that...
Of course this is not high priority, since in principle everything works, but always having a RuntimeWarning when everything works as intended seems kind of awkward.



>  Of course this is not high priority, since in principle everything works, but always having a RuntimeWarning when everything works as intended seems kind of awkward.

Definetly. Seems like this warning was recently introduced, at least with numpy 1.11 I don't get that warning.

Instead of using np.seterr, I suggest using np.errstate to supress the warning only in this line:

```
with  np.errstate(invalid='ignore'):
    i_ka = np.max(i_ft[f:t], axis=1) 
```
I pushed the fix as suggested above. I also checked on the two-open switches at one line issue as descibed above, and it seems like that has since been fixed and now also returns nan results, so everything seems to be consistent. So if the fix works for you, this issue can be closed?
Yes this can be closed, thanks!
I closed too early. Not surprisingly the same happens now for transformer branches. np.max() is not used for impedances, so there should be no problem. But switches use it, I guess only if switches have a resistance?

The fix should be straightforward, should I do it and make a pull request or do you want to add that yourself?

Resolving patch:
diff --git a/pandapower/results_branch.py b/pandapower/results_branch.py
--- a/pandapower/results_branch.py
+++ b/pandapower/results_branch.py
@@ -112,7 +112,8 @@ def _get_trafo_results(net, ppc, s_ft, i_ft):
         vns = np.vstack([trafo_df["vn_hv_kv"].values, trafo_df["vn_lv_kv"].values]).T
         lds_trafo = i_ft[f:t] * vns * 1000. * np.sqrt(3) \
                     / trafo_df["sn_kva"].values[:, np.newaxis] * 100.
-        ld_trafo = np.max(lds_trafo, axis=1)
+        with np.errstate(invalid='ignore'):
+            ld_trafo = np.max(lds_trafo, axis=1)
     elif trafo_loading == "power":
         ld_trafo = np.max(s_ft[f:t] / net["trafo"]["sn_kva"].values[:, np.newaxis] * 100., axis=1)
     else:
@@ -182,7 +183,8 @@ def _get_trafo3w_results(net, ppc, s_ft, i_ft):
         ld_h = i_h * t3["vn_hv_kv"].values * 1000. * np.sqrt(3) / t3["sn_hv_kva"].values * 100
         ld_m = i_m * t3["vn_mv_kv"].values * 1000. * np.sqrt(3) / t3["sn_mv_kva"].values * 100
         ld_l = i_l * t3["vn_lv_kv"].values * 1000. * np.sqrt(3) / t3["sn_lv_kva"].values * 100
-        ld_trafo = np.max(np.vstack([ld_h, ld_m, ld_l]), axis=0)
+        with np.errstate(invalid='ignore'):
+            ld_trafo = np.max(np.vstack([ld_h, ld_m, ld_l]), axis=0)
     elif trafo_loading == "power":
         ld_h = s_ft[:, 0][f:hv] / t3["sn_hv_kva"] * 100.
         ld_m = s_ft[:, 1][hv:mv] / t3["sn_mv_kva"] * 100.
@@ -274,5 +276,7 @@ def _get_switch_results(net, i_ft):
     if not "switch" in net._pd2ppc_lookups["branch"]:
         return
     f, t = net._pd2ppc_lookups["branch"]["switch"]
-    net["res_switch"] = pd.DataFrame(data=np.max(i_ft[f:t], axis=1), columns=["i_ka"],
+    with np.errstate(invalid='ignore'):
+        i_ka = np.max(i_ft[f:t], axis=1)
+    net["res_switch"] = pd.DataFrame(data=i_ka, columns=["i_ka"],
                                      index=net.switch[net._closed_bb_switches].index)


Test patch: