e2nIEE / pandapower
Showing 15 of 31 files from the diff.

@@ -721,8 +721,7 @@
Loading
721 721
        if not section & set(net.ext_grid.bus[net.ext_grid.in_service]).union(
722 722
                net.gen.bus[net.gen.slack & net.gen.in_service]) and any(
723 723
                net.bus.in_service.loc[list(section)]):
724 -
            section_buses = list(net.bus[net.bus.index.isin(section)
725 -
                                         & (net.bus.in_service == True)].index)
724 +
            section_buses = list(net.bus[net.bus.index.isin(section) & net.bus.in_service].index)
726 725
            section_switches = list(net.switch[net.switch.bus.isin(section_buses)].index)
727 726
            section_lines = list(get_connected_elements(net, 'line', section_buses,
728 727
                                                        respect_switches=True,
@@ -734,12 +733,9 @@
Loading
734 733
            section_trafos3w = list(get_connected_elements(net, 'trafo3w', section_buses,
735 734
                                                           respect_switches=True,
736 735
                                                           respect_in_service=True))
737 -
            section_gens = list(net.gen[net.gen.bus.isin(section)
738 -
                                        & (net.gen.in_service == True)].index)
739 -
            section_sgens = list(net.sgen[net.sgen.bus.isin(section)
740 -
                                          & (net.sgen.in_service == True)].index)
741 -
            section_loads = list(net.load[net.load.bus.isin(section)
742 -
                                          & (net.load.in_service == True)].index)
736 +
            section_gens = list(net.gen[net.gen.bus.isin(section) & net.gen.in_service].index)
737 +
            section_sgens = list(net.sgen[net.sgen.bus.isin(section) & net.sgen.in_service].index)
738 +
            section_loads = list(net.load[net.load.bus.isin(section) & net.load.in_service].index)
743 739
744 740
            if section_buses:
745 741
                section_dict['buses'] = section_buses
@@ -764,15 +760,12 @@
Loading
764 760
    open_trafo_switches = net.switch[(net.switch.et == 't') & (net.switch.closed == 0)]
765 761
    isolated_trafos = set(
766 762
        (open_trafo_switches.groupby("element").count().query("bus > 1").index))
767 -
    isolated_trafos_is = isolated_trafos.intersection((set(net.trafo[net.trafo.in_service == True]
768 -
                                                           .index)))
763 +
    isolated_trafos_is = isolated_trafos.intersection((set(net.trafo[net.trafo.in_service].index)))
769 764
    if isolated_trafos_is:
770 765
        disc_elements.append({'isolated_trafos': list(isolated_trafos_is)})
771 766
772 -
    isolated_trafos3w = set(
773 -
        (open_trafo_switches.groupby("element").count().query("bus > 2").index))
774 -
    isolated_trafos3w_is = isolated_trafos3w.intersection((
775 -
        set(net.trafo[net.trafo.in_service == True].index)))
767 +
    isolated_trafos3w = set(open_trafo_switches.groupby("element").count().query("bus > 2").index)
768 +
    isolated_trafos3w_is = isolated_trafos3w.intersection(set(net.trafo[net.trafo.in_service].index))
776 769
    if isolated_trafos3w_is:
777 770
        disc_elements.append({'isolated_trafos3w': list(isolated_trafos3w_is)})
778 771

@@ -52,19 +52,20 @@
Loading
52 52
    output_writer.init_all(net)
53 53
54 54
55 -
def print_progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=100, fill='█'):
56 -
    """
57 -
    Call in a loop to create terminal progress bar.
58 -
    the code is mentioned in : https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console
59 -
    """
60 -
    percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
61 -
    filled_length = int(length * iteration // total)
62 -
    bar = fill * filled_length + '-' * (length - filled_length)
63 -
    # logger.info('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix))
64 -
    print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end="")
65 -
    # Print New Line on Complete
66 -
    if iteration == total:
67 -
        print("\n")
55 +
#
56 +
# def print_progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=100, fill='█'):
57 +
#     """
58 +
#     Call in a loop to create terminal progress bar.
59 +
#     the code is mentioned in : https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console
60 +
#     """
61 +
#     percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
62 +
#     filled_length = int(length * iteration // total)
63 +
#     bar = fill * filled_length + '-' * (length - filled_length)
64 +
#     # logger.info('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix))
65 +
#     print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end="")
66 +
#     # Print New Line on Complete
67 +
#     if iteration == total:
68 +
#         print("\n")
68 69
69 70
70 71
def controller_not_converged(time_step, ts_variables):
@@ -84,6 +85,7 @@
Loading
84 85
        for ctrl, net in levelorder:
85 86
            ctrl.time_step(net, time_step)
86 87
88 +
87 89
def finalize_step(controller_order, time_step):
88 90
    for levelorder in controller_order:
89 91
        for ctrl, net in levelorder:

@@ -16,10 +16,7 @@
Loading
16 16
from pandapower.create import create_empty_network, create_buses, create_ext_grid, create_loads, \
17 17
    create_sgens, create_gens, create_lines_from_parameters, create_transformers_from_parameters, \
18 18
    create_shunts, create_ext_grid, create_pwl_costs, create_poly_costs
19 -
from pandapower.run import rundcpp, runpp, runopp
20 -
from pandapower.powerflow import LoadflowNotConverged
21 -
from pandapower.optimal_powerflow import OPFNotConverged
22 -
from pandapower.toolbox import get_element_index
19 +
from pandapower.run import runpp
23 20
24 21
try:
25 22
    import pandaplan.core.pplog as logging
@@ -27,13 +24,6 @@
Loading
27 24
    import logging
28 25
logger = logging.getLogger(__name__)
29 26
30 -
try:
31 -
    from pypower import ppoption, runpf, runopf, rundcpf, rundcopf
32 -
    ppopt = ppoption.ppoption(VERBOSE=0, OUT_ALL=0)
33 -
    pypower_import = True
34 -
except ImportError:
35 -
    pypower_import = False
36 -
37 27
ppc_elms = ["bus", "branch", "gen"]
38 28
39 29
@@ -41,19 +31,18 @@
Loading
41 31
    """
42 32
    This function converts pypower case files to pandapower net structure.
43 33
44 -
    INPUT:
45 -
46 -
        **ppc** : The pypower case file.
47 -
48 -
    OPTIONAL:
49 -
50 -
        **f_hz** (float, 50) - The frequency of the network.
51 -
52 -
        **validate_conversion** (bool, False) - If True, validate_from_ppc is run after conversion.
53 -
            For running the validation, the ppc must already contain the pypower
54 -
            powerflow results or pypower must be installed.
55 -
56 -
        ****kwargs** keyword arguments for
34 +
    Parameters
35 +
    ----------
36 +
    ppc : dict
37 +
        The pypower case file.
38 +
    f_hz : int, optional
39 +
        The frequency of the network, by default 50
40 +
    validate_conversion : bool, optional
41 +
        If True, validate_from_ppc is run after conversion.
42 +
        For running the validation, the ppc must already contain the pypower
43 +
        powerflow results or pypower must be installed, by default False
44 +
    kwargs: dict
45 +
        keyword arguments for
57 46
58 47
            - validate_from_ppc if validate_conversion is True
59 48
@@ -61,32 +50,30 @@
Loading
61 50
62 51
            - check_costs is passed as "check" to create_pwl_costs() and create_poly_costs()
63 52
64 -
    OUTPUT:
65 -
66 -
        **net** : pandapower net.
67 -
68 -
    EXAMPLE:
69 -
70 -
        import pandapower.converter as pc
71 -
72 -
        from pypower import case4gs
73 -
74 -
        ppc_net = case4gs.case4gs()
75 -
76 -
        net = pc.from_ppc(ppc_net, f_hz=60)
77 -
53 +
    Returns
54 +
    -------
55 +
    pandapower.pandapowerNet
56 +
        ppc converted to pandapower net structure
57 +
58 +
    Examples
59 +
    -------
60 +
    >>> import pandapower
61 +
    >>> from pandapower.test.converter.test_from_ppc import get_testgrids
62 +
    >>> ppc = get_testgrids('pypower_cases', 'case4gs.json')
63 +
    >>> net = pandapower.converter.from_ppc(ppc, f_hz=60)
78 64
    """
65 +
79 66
    # --- catch common failures
80 67
    if pd.Series(ppc['bus'][:, BASE_KV] <= 0).any():
81 68
        logger.info('There are false baseKV given in the pypower case file.')
82 69
83 70
    net = create_empty_network(f_hz=f_hz, sn_mva=ppc["baseMVA"])
84 -
71 +
    net._from_ppc_lookups = {}
85 72
86 73
    _from_ppc_bus(net, ppc)
87 -
    gen_lookup = _from_ppc_gen(net, ppc)
88 -
    _from_ppc_branch(net, ppc, f_hz, **kwargs)
89 -
    _from_ppc_gencost(net, ppc, gen_lookup, check=kwargs.get("check_costs", True))
74 +
    net._from_ppc_lookups["gen"] = _from_ppc_gen(net, ppc)
75 +
    net._from_ppc_lookups["branch"] = _from_ppc_branch(net, ppc, f_hz, **kwargs)
76 +
    _from_ppc_gencost(net, ppc, net._from_ppc_lookups["gen"], check=kwargs.get("check_costs", True))
90 77
91 78
    # areas are unconverted
92 79
@@ -95,9 +82,6 @@
Loading
95 82
        if not validate_from_ppc(ppc, net, **kwargs):
96 83
            logger.error("Validation failed.")
97 84
98 -
    net._options = {}
99 -
    net._options["gen_lookup"] = gen_lookup
100 -
101 85
    return net
102 86
103 87
@@ -106,10 +90,11 @@
Loading
106 90
107 91
    # create buses
108 92
    idx_buses = create_buses(
109 -
        net, ppc['bus'].shape[0], name=ppc['bus'][:, BUS_I].astype(int),
93 +
        net, ppc['bus'].shape[0], name=ppc.get("bus_name", None),
110 94
        vn_kv=ppc['bus'][:, BASE_KV], type="b", zone=ppc['bus'][:, ZONE],
111 95
        in_service=(ppc['bus'][:, BUS_TYPE] != 4).astype(bool),
112 -
        max_vm_pu=ppc['bus'][:, VMAX], min_vm_pu=ppc['bus'][:, VMIN])
96 +
        max_vm_pu=ppc['bus'][:, VMAX], min_vm_pu=ppc['bus'][:, VMIN],
97 +
        index=ppc['bus'][:, BUS_I].astype(int))
113 98
114 99
    # create loads
115 100
    is_load = (ppc['bus'][:, PD] > 0) | ((ppc['bus'][:, PD] == 0) & (ppc['bus'][:, QD] != 0))
@@ -126,7 +111,7 @@
Loading
126 111
    create_shunts(net, idx_buses[is_shunt], p_mw=ppc['bus'][is_shunt, GS],
127 112
                     q_mvar=-ppc['bus'][is_shunt, BS])
128 113
129 -
    # unused data of ppc: Vm, Va (partwise: in ext_grid), zone
114 +
    # unused data from ppc: VM, VA (partwise: in ext_grid), BUS_AREA
130 115
131 116
132 117
def _from_ppc_gen(net, ppc):
@@ -147,32 +132,36 @@
Loading
147 132
    # vg_bus_lookup = vg_bus_lookup.drop_duplicates(subset=["bus"], keep="last").set_index("bus")["vg"]
148 133
    vg_bus_lookup = vg_bus_lookup.drop_duplicates(subset=["bus"]).set_index("bus")["vg"]
149 134
135 +
    gen_name = ppc.get("gen_name", np.array([None]*n_gen))
136 +
150 137
    # create ext_grid
151 138
    idx_eg = list()
152 139
    for i in np.arange(n_gen, dtype=int)[is_ext_grid]:
153 140
        idx_eg.append(create_ext_grid(
154 -
            net, bus=bus_pos[i], vm_pu=vg_bus_lookup.at[bus_pos[i]],
141 +
            net, bus=net.bus.index[bus_pos[i]], vm_pu=vg_bus_lookup.at[bus_pos[i]],
155 142
            va_degree=ppc['bus'][bus_pos[i], VA],
156 143
            in_service=(ppc['gen'][i, GEN_STATUS] > 0).astype(bool),
157 144
            max_p_mw=ppc['gen'][i, PMAX], min_p_mw=ppc['gen'][i, PMIN],
158 -
            max_q_mvar=ppc['gen'][i, QMAX], min_q_mvar=ppc['gen'][i, QMIN]))
145 +
            max_q_mvar=ppc['gen'][i, QMAX], min_q_mvar=ppc['gen'][i, QMIN],
146 +
            name=gen_name[i]))
159 147
160 148
    # create gen
161 149
    idx_gen = create_gens(
162 -
        net, buses=bus_pos[is_gen], vm_pu=vg_bus_lookup.loc[bus_pos[is_gen]].values,
150 +
        net, buses=net.bus.index[bus_pos[is_gen]], vm_pu=vg_bus_lookup.loc[bus_pos[is_gen]].values,
163 151
        p_mw=ppc['gen'][is_gen, PG], sn_mva=ppc['gen'][is_gen, MBASE],
164 152
        in_service=(ppc['gen'][is_gen, GEN_STATUS] > 0), controllable=True,
165 153
        max_p_mw=ppc['gen'][is_gen, PMAX], min_p_mw=ppc['gen'][is_gen, PMIN],
166 -
        max_q_mvar=ppc['gen'][is_gen, QMAX], min_q_mvar=ppc['gen'][is_gen, QMIN])
154 +
        max_q_mvar=ppc['gen'][is_gen, QMAX], min_q_mvar=ppc['gen'][is_gen, QMIN],
155 +
        name=gen_name[is_gen])
167 156
168 157
    # create sgen
169 158
    idx_sgen = create_sgens(
170 -
        net, buses=bus_pos[is_sgen], p_mw=ppc['gen'][is_sgen, PG],
159 +
        net, buses=net.bus.index[bus_pos[is_sgen]], p_mw=ppc['gen'][is_sgen, PG],
171 160
        q_mvar=ppc['gen'][is_sgen, QG], sn_mva=ppc['gen'][is_sgen, MBASE], type="",
172 161
        in_service=(ppc['gen'][is_sgen, GEN_STATUS] > 0),
173 162
        max_p_mw=ppc['gen'][is_sgen, PMAX], min_p_mw=ppc['gen'][is_sgen, PMIN],
174 163
        max_q_mvar=ppc['gen'][is_sgen, QMAX], min_q_mvar=ppc['gen'][is_sgen, QMIN],
175 -
        controllable=True)
164 +
        controllable=True, name=gen_name[is_sgen])
176 165
177 166
    neg_p_gens = np.arange(n_gen, dtype=int)[(ppc['gen'][:, PG] < 0) & (is_gen | is_sgen)]
178 167
    neg_p_lim_false = np.arange(n_gen, dtype=int)[ppc['gen'][:, PMIN] > ppc['gen'][:, PMAX]]
@@ -184,19 +173,22 @@
Loading
184 173
    if len(neg_q_lim_false):
185 174
        logger.info(f'These gen have QMIN > QMAX: {neg_q_lim_false}.')
186 175
187 -
    # unused data of ppc: Vg (partwise: in ext_grid and gen), mBase, Pc1, Pc2, Qc1min, Qc1max,
176 +
    # unused data from ppc: Vg (partwise: in ext_grid and gen), mBase, Pc1, Pc2, Qc1min, Qc1max,
188 177
    # Qc2min, Qc2max, ramp_agc, ramp_10, ramp_30,ramp_q, apf
189 178
190 179
    # gen_lookup
191 -
    gen_lookup = pd.DataFrame({
192 -
        'element': np.r_[idx_eg, idx_gen, idx_sgen],
193 -
        'element_type': ["ext_grid"]*sum(is_ext_grid) + ["gen"]*sum(is_gen) + ["sgen"]*sum(is_sgen)
194 -
        })
180 +
    gen_lookup = pd.DataFrame({"element": [-1]*n_gen, "element_type": [""]*n_gen})
181 +
    for is_, idx, et in zip([is_ext_grid, is_gen, is_sgen],
182 +
                            [idx_eg, idx_gen, idx_sgen],
183 +
                            ["ext_grid", "gen", "sgen"]):
184 +
        gen_lookup["element"].loc[is_] = idx
185 +
        gen_lookup["element_type"].loc[is_] = et
195 186
    return gen_lookup
196 187
197 188
198 189
def _from_ppc_branch(net, ppc, f_hz, **kwargs):
199 190
    """ branch data -> create line, trafo """
191 +
    n_bra = ppc["branch"].shape[0]
200 192
201 193
    # --- general_parameters
202 194
    baseMVA = ppc['baseMVA']  # MVA
@@ -210,6 +202,8 @@
Loading
210 202
211 203
    is_line, to_vn_is_leq = _branch_to_which(ppc, from_vn_kv=from_vn_kv, to_vn_kv=to_vn_kv)
212 204
205 +
    bra_name = ppc.get("branch_name", ppc.get("bra_name", np.array([None]*n_bra)))
206 +
213 207
    # --- create line
214 208
    Zni = ppc['bus'][to_bus, BASE_KV]**2/baseMVA  # ohm
215 209
    max_i_ka = ppc['branch'][:, 5]/ppc['bus'][to_bus, BASE_KV]/np.sqrt(3)
@@ -218,8 +212,9 @@
Loading
218 212
        max_i_ka[i_is_zero] = MAX_VAL
219 213
        logger.debug("ppc branch rateA is zero -> Using MAX_VAL instead to calculate " +
220 214
                     "maximum branch flow")
221 -
    create_lines_from_parameters(
222 -
        net, from_buses=from_bus[is_line], to_buses=to_bus[is_line], length_km=1,
215 +
    idx_line = create_lines_from_parameters(
216 +
        net, from_buses=net.bus.index[from_bus[is_line]], to_buses=net.bus.index[to_bus[is_line]],
217 +
        length_km=1, name=bra_name[is_line],
223 218
        r_ohm_per_km=(ppc['branch'][is_line, BR_R]*Zni[is_line]).real,
224 219
        x_ohm_per_km=(ppc['branch'][is_line, BR_X]*Zni[is_line]).real,
225 220
        c_nf_per_km=(ppc['branch'][is_line, BR_B]/Zni[is_line]/omega*1e9/2).real,
@@ -273,15 +268,25 @@
Loading
273 268
        vkr_percent = rk * sn * 100 / baseMVA
274 269
        vkr_percent[~tap_side_is_hv] /= (1+ratio_1[~tap_side_is_hv])**2
275 270
276 -
        create_transformers_from_parameters(
277 -
            net, hv_buses=hv_bus, lv_buses=lv_bus, sn_mva=sn,
278 -
            vn_hv_kv=vn_hv_kv, vn_lv_kv=vn_lv_kv,
271 +
        idx_trafo = create_transformers_from_parameters(
272 +
            net, hv_buses=net.bus.index[hv_bus], lv_buses=net.bus.index[lv_bus], sn_mva=sn,
273 +
            vn_hv_kv=vn_hv_kv, vn_lv_kv=vn_lv_kv, name=bra_name[~is_line],
279 274
            vk_percent=vk_percent, vkr_percent=vkr_percent,
280 275
            max_loading_percent=100, pfe_kw=0, i0_percent=i0_percent,
281 276
            shift_degree=ppc['branch'][~is_line, SHIFT].real,
282 277
            tap_step_percent=np.abs(ratio_1)*100, tap_pos=np.sign(ratio_1),
283 278
            tap_side=tap_side, tap_neutral=0)
284 -
    # unused data of ppc: rateB, rateC
279 +
    else:
280 +
        idx_trafo = []
281 +
    # unused data from ppc: rateB, rateC
282 +
283 +
    # branch_lookup: which branches are lines, and which ones are transformers
284 +
    branch_lookup = pd.DataFrame({"element": [-1] * n_bra, "element_type": [""] * n_bra})
285 +
    branch_lookup["element"].loc[is_line] = idx_line
286 +
    branch_lookup["element_type"].loc[is_line] = "line"
287 +
    branch_lookup["element"].loc[~is_line] = idx_trafo
288 +
    branch_lookup["element_type"].loc[~is_line] = "trafo"
289 +
    return branch_lookup
285 290
286 291
287 292
def _get_bus_pos(ppc, bus_names):
@@ -368,7 +373,7 @@
Loading
368 373
def _from_ppc_gencost(net, ppc, gen_lookup, check=True):
369 374
    # --- gencost -> create polynomial_cost, piecewise_cost
370 375
371 -
    if not 'gencost' in ppc:
376 +
    if 'gencost' not in ppc:
372 377
        return
373 378
374 379
    if len(ppc['gencost'].shape) == 1:
@@ -446,328 +451,159 @@
Loading
446 451
447 452
448 453
def _validate_diff_res(diff_res, max_diff_values):
449 -
    to_iterate = set(max_diff_values.keys()) & {'gen_q_mvar', 'branch_p_mw', 'branch_q_mvar',
450 -
                                                'gen_p_mw', 'bus_va_degree', 'bus_vm_pu'}
451 -
    if not len(to_iterate):
452 -
        logger.warning("There are no keys to validate.")
453 454
    val = True
454 -
    for i in to_iterate:
455 -
        elm = i.split("_")[0]
456 -
        sought = ["p", "q"] if elm != "bus" else ["vm", "va"]
457 -
        col = int(np.array([0, 1])[[j in i for j in sought]][0]) if elm != "branch" else \
458 -
            list(np.array([[0, 2], [1, 3]])[[j in i for j in sought]][0])
459 -
        val &= bool(np.max(abs(diff_res[elm][:, col])) < max_diff_values[i])
455 +
    for et_val in ['gen_q_mvar', 'branch_p_mw', 'branch_q_mvar', 'gen_p_mw', 'bus_va_degree',
456 +
                   'bus_vm_pu']:
457 +
        if max_diff_values[et_val] is not None:
458 +
            et = et_val.split("_")[0]
459 +
            log_key = et if et != "gen" else "gen_p" if "p" in et_val else "gen_q_sum_per_bus"
460 +
            i_col = _log_dict(log_key)[0]
461 +
            val &= bool(np.max(abs(diff_res[log_key][:, i_col])) < max_diff_values[et_val])
460 462
    return val
461 463
462 464
463 -
def _gen_bus_info(ppc, idx_gen):
464 -
    bus_name = int(ppc["gen"][idx_gen, GEN_BUS])
465 -
    # assumption: there is only one bus with this bus_name:
466 -
    idx_bus = int(np.where(ppc["bus"][:, BUS_I] == bus_name)[0][0])
467 -
    current_bus_type = int(ppc["bus"][idx_bus, 1])
465 +
def _gen_q_per_bus_sum(q_array, ppc):
466 +
    return pd.DataFrame(
467 +
        np.c_[q_array, ppc["gen"][:, GEN_BUS].astype(int)],
468 +
        columns=["q_mvar", "bus"]).groupby("bus").sum()
468 469
469 -
    same_bus_gen = np.where(ppc["gen"][:, GEN_BUS] == ppc["gen"][idx_gen, GEN_BUS])[0].astype(int)
470 -
    same_bus_gen = same_bus_gen[np.where(ppc["gen"][same_bus_gen, GEN_STATUS] > 0)]
471 -
    first_same_bus = same_bus_gen[0] if len(same_bus_gen) else None
472 470
473 -
    return current_bus_type, idx_bus, first_same_bus
471 +
def _log_dict(key=None):
472 +
    log_dict = {
473 +
        "bus": [[0, 1], ["voltage magnitude", "voltage angle"], ["pu", "degree"]],
474 +
        "branch": [[[0, 2], [1, 3]], ["branch flow active power", "branch flow reactive power"],
475 +
                   ["MW", "Mvar"]],
476 +
        "gen_p": [[0], ["active power generation"], ["MW"]],
477 +
        "gen_q_sum_per_bus": [[0], ["reactive power generation sum per bus"], ["Mvar"]]}
478 +
    if key is None:
479 +
        return log_dict
480 +
    else:
481 +
        return log_dict[key]
474 482
475 483
476 -
def validate_from_ppc(ppc_net, net, pf_type="runpp", max_diff_values={
477 -
    "bus_vm_pu": 1e-6, "bus_va_degree": 1e-5, "branch_p_mw": 1e-6, "branch_q_mvar": 1e-6,
478 -
        "gen_p_mw": 1e-6, "gen_q_mvar": 1e-6}, run=True):
484 +
def validate_from_ppc(ppc, net, max_diff_values={
485 +
        "bus_vm_pu": 1e-6, "bus_va_degree": 1e-5, "branch_p_mw": 1e-6, "branch_q_mvar": 1e-6,
486 +
        "gen_p_mw": 1e-6, "gen_q_mvar": 1e-6}):
479 487
    """
480 -
    This function validates the pypower case files to pandapower net structure conversion via a \
481 -
    comparison of loadflow calculation results. (Hence the opf cost conversion is not validated.)
482 -
483 -
    INPUT:
484 -
485 -
        **ppc_net** - The pypower case file, which must already contain the pypower powerflow
486 -
            results or pypower must be importable.
487 -
488 -
        **net** - The pandapower network.
489 -
490 -
    OPTIONAL:
491 -
492 -
        **pf_type** ("runpp", string) - Type of validated power flow. Possible are ("runpp",
493 -
            "rundcpp", "runopp", "rundcopp")
494 -
495 -
        **max_diff_values** - Dict of maximal allowed difference values. The keys must be
496 -
        'vm_pu', 'va_degree', 'p_branch_mw', 'q_branch_mvar', 'p_gen_mw' and 'q_gen_mvar' and
497 -
        the values floats.
498 -
499 -
        **run** (True, bool or list of two bools) - changing the value to False avoids trying to run
500 -
            (optimal) loadflows. Giving a list of two bools addresses first pypower and second
501 -
            pandapower.
502 -
503 -
    OUTPUT:
504 -
505 -
        **conversion_success** - conversion_success is returned as False if pypower or pandapower
506 -
        cannot calculate a powerflow or if the maximum difference values (max_diff_values )
507 -
        cannot be hold.
508 -
509 -
    EXAMPLE:
510 -
511 -
        import pandapower.converter as pc
512 -
513 -
        net = cv.from_ppc(ppc_net, f_hz=50)
514 -
515 -
        conversion_success = cv.validate_from_ppc(ppc_net, net)
516 -
517 -
    NOTE:
518 -
519 -
        The user has to take care that the loadflow results already are included in the provided \
520 -
        ppc_net or pypower is importable.
488 +
    This function validates the conversion of a pypower case file (ppc) to a pandapower net.
489 +
    It compares the power flow calculation results which must be provided within the ppc and the net.
490 +
491 +
    Parameters
492 +
    ----------
493 +
    ppc : dict
494 +
        _description_
495 +
    net : pandapower.pandapowerNet
496 +
        _description_
497 +
    max_diff_values : dict, optional
498 +
        _description_, by default { "bus_vm_pu": 1e-6, "bus_va_degree": 1e-5, "branch_p_mw": 1e-6,
499 +
        "branch_q_mvar": 1e-6, "gen_p_mw": 1e-6, "gen_q_mvar": 1e-6}
500 +
501 +
    Returns
502 +
    -------
503 +
    bool
504 +
        Whether the power flow results matches.
505 +
506 +
    Examples
507 +
    ------
508 +
    >>> import pandapower
509 +
    >>> from pandapower.test.converter.test_from_ppc import get_testgrids
510 +
    >>> ppc = get_testgrids('pypower_cases', 'case4gs.json')
511 +
    >>> net = pandapower.converter.from_ppc(ppc, f_hz=50)
512 +
    >>> pandapower.runpp(net)
513 +
    >>> pf_match = pandapower.converter.validate_from_ppc(ppc, net)
521 514
    """
515 +
    if "_from_ppc_lookups" not in net.keys() or \
516 +
            ("gen" not in net._from_ppc_lookups.keys() and len(ppc["gen"]) > 0) or \
517 +
            ("branch" not in net._from_ppc_lookups.keys() and len(ppc["branch"]) > 0):
518 +
        raise ValueError(
519 +
            "net._from_ppc_lookups must contain a lookup (dict of keys 'branch' and 'gen')")
522 520
523 -
    # check in case of optimal powerflow comparison whether cost information exist
524 -
    if "opp" in pf_type:
525 -
        if not (len(net.polynomial_cost) | len(net.piecewise_linear_cost)):
526 -
            if "gencost" in ppc_net:
527 -
                if not len(ppc_net["gencost"]):
528 -
                    logger.debug('ppc and pandapower net do not include cost information.')
529 -
                    return True
530 -
                else:
531 -
                    logger.error('The pandapower net does not include cost information.')
532 -
                    return False
533 -
            else:
534 -
                logger.debug('ppc and pandapower net do not include cost information.')
535 -
                return True
536 -
537 -
    # guarantee run parameter as list, for pypower and pandapower (optimal) powerflow run
538 -
    run = [run, run] if isinstance(run, bool) else run
539 -
540 -
    # --- check pypower powerflow success, if possible
541 -
    if pypower_import and run[0]:
542 -
        try:
543 -
            if pf_type == "runpp":
544 -
                ppc_net = runpf.runpf(ppc_net, ppopt)[0]
545 -
            elif pf_type == "rundcpp":
546 -
                ppc_net = rundcpf.rundcpf(ppc_net, ppopt)[0]
547 -
            elif pf_type == "runopp":
548 -
                ppc_net = runopf.runopf(ppc_net, ppopt)
549 -
            elif pf_type == "rundcopp":
550 -
                ppc_net = rundcopf.rundcopf(ppc_net, ppopt)
551 -
            else:
552 -
                raise ValueError(f"The pf_type {pf_type} is unknown")
553 -
        except:
554 -
            logger.debug("The pypower run did not work.")
555 -
    ppc_success = True
556 -
    if 'success' in ppc_net.keys():
557 -
        if ppc_net['success'] != 1:
558 -
            ppc_success = False
559 -
            logger.error("The given ppc data indicates an unsuccessful pypower powerflow: " +
560 -
                         "'ppc_net['success'] != 1'")
561 -
    if (ppc_net['branch'].shape[1] < 17):
562 -
        ppc_success = False
563 -
        logger.error("The shape of given ppc data indicates missing pypower powerflow results.")
564 -
565 -
    # --- try to run a pandapower powerflow
566 -
    if run[1]:
567 -
        if pf_type == "runpp":
568 -
            try:
569 -
                runpp(net, init="dc", calculate_voltage_angles=True, trafo_model="pi")
570 -
            except LoadflowNotConverged:
571 -
                try:
572 -
                    runpp(net, calculate_voltage_angles=True, init="flat", trafo_model="pi")
573 -
                except LoadflowNotConverged:
574 -
                    try:
575 -
                        runpp(net, trafo_model="pi", calculate_voltage_angles=False)
576 -
                        if "bus_va_degree" in max_diff_values.keys():
577 -
                            max_diff_values["bus_va_degree"] = 1e2 if max_diff_values[
578 -
                                "bus_va_degree"] < 1e2 else max_diff_values["bus_va_degree"]
579 -
                        logger.info("voltage_angles could be calculated.")
580 -
                    except LoadflowNotConverged:
581 -
                        logger.error('The pandapower powerflow does not converge.')
582 -
        elif pf_type == "rundcpp":
583 -
            try:
584 -
                rundcpp(net, trafo_model="pi")
585 -
            except LoadflowNotConverged:
586 -
                logger.error('The pandapower dc powerflow does not converge.')
587 -
        elif pf_type == "runopp":
588 -
                try:
589 -
                    runopp(net, init="flat", calculate_voltage_angles=True)
590 -
                except OPFNotConverged:
591 -
                    try:
592 -
                        runopp(net, init="pf", calculate_voltage_angles=True)
593 -
                    except (OPFNotConverged, LoadflowNotConverged, KeyError):
594 -
                        try:
595 -
                            runopp(net, init="flat", calculate_voltage_angles=False)
596 -
                            logger.info("voltage_angles could be calculated.")
597 -
                            if "bus_va_degree" in max_diff_values.keys():
598 -
                                max_diff_values["bus_va_degree"] = 1e2 if max_diff_values[
599 -
                                    "bus_va_degree"] < 1e2 else max_diff_values["bus_va_degree"]
600 -
                        except OPFNotConverged:
601 -
                            try:
602 -
                                runopp(net, init="pf", calculate_voltage_angles=False)
603 -
                                if "bus_va_degree" in max_diff_values.keys():
604 -
                                    max_diff_values["bus_va_degree"] = 1e2 if max_diff_values[
605 -
                                        "bus_va_degree"] < 1e2 else max_diff_values["bus_va_degree"]
606 -
                                logger.info("voltage_angles could be calculated.")
607 -
                            except (OPFNotConverged, LoadflowNotConverged, KeyError):
608 -
                                logger.error('The pandapower optimal powerflow does not converge.')
609 -
        elif pf_type == "rundcopp":
610 -
            try:
611 -
                rundcopp(net)
612 -
            except LoadflowNotConverged:
613 -
                logger.error('The pandapower dc optimal powerflow does not converge.')
614 -
        else:
615 -
            raise ValueError("The pf_type %s is unknown" % pf_type)
616 -
617 -
    # --- prepare powerflow result comparison by reordering pp results as they are in ppc results
618 -
    if not ppc_success:
619 -
        return False
620 -
    if "opp" in pf_type:
621 -
        if not net.OPF_converged:
622 -
            return
623 -
    elif not net.converged:
624 -
        return False
625 -
626 -
    # --- store pypower powerflow results
521 +
    if net.res_bus.shape[0] == 0 and net.bus.shape[0] > 0:
522 +
        logger.debug("runpp() is performed by validate_from_ppc() since res_bus is empty.")
523 +
        runpp(net, calculate_voltage_angles=True, trafo_model="pi")
524 +
525 +
    # --- pypower powerflow results -> ppc_res -----------------------------------------------------
627 526
    ppc_res = dict.fromkeys(ppc_elms)
628 -
    ppc_res["branch"] = ppc_net['branch'][:, 13:17]
629 -
    ppc_res["bus"] = ppc_net['bus'][:, 7:9]
630 -
    ppc_res["gen"] = ppc_net['gen'][:, 1:3]
527 +
    ppc_res["bus"] = ppc['bus'][:, 7:9]
528 +
    ppc_res["branch"] = ppc['branch'][:, 13:17]
529 +
    ppc_res["gen"] = ppc['gen'][:, 1:3]
530 +
    ppc_res["gen_p"] = ppc_res["gen"][:, :1]
531 +
    ppc_res["gen_q_sum_per_bus"] = _gen_q_per_bus_sum(ppc_res["gen"][:, -1:], ppc)
631 532
632 -
    # --- pandapower bus result table
533 +
    # --- pandapower powerflow results -> pp_res ---------------------------------------------------
633 534
    pp_res = dict.fromkeys(ppc_elms)
634 -
    pp_res["bus"] = np.array(net.res_bus.sort_index()[['vm_pu', 'va_degree']])
635 535
636 -
    # --- pandapower gen result table
637 -
    pp_res["gen"] = np.zeros([1, 2])
638 -
    # consideration of parallel generators via storing how much generators have been considered
639 -
    # each node
640 -
    # if in ppc is only one gen -> numpy initially uses one dim array -> change to two dim array
641 -
    if len(ppc_net["gen"].shape) == 1:
642 -
        ppc_net["gen"] = np.array(ppc_net["gen"], ndmin=2)
643 -
    GENS = pd.DataFrame(ppc_net['gen'][:, [0]].astype(int))
644 -
    GEN_uniq = GENS.drop_duplicates()
645 -
    already_used_gen = pd.Series(np.zeros(GEN_uniq.shape[0]).astype(int),
646 -
                                 index=[int(v) for v in GEN_uniq.values])
647 -
    change_q_compare = []
648 -
    for i, j in GENS.iterrows():
649 -
        current_bus_type, current_bus_idx, first_same_bus_in_service_gen_idx, = _gen_bus_info(
650 -
            ppc_net, i)
651 -
        if current_bus_type == 3 and i == first_same_bus_in_service_gen_idx:
652 -
            pp_res["gen"] = np.append(pp_res["gen"], np.array(net.res_ext_grid[
653 -
                    net.ext_grid.bus == current_bus_idx][['p_mw', 'q_mvar']]).reshape((1, 2)), 0)
654 -
        elif current_bus_type == 2 and i == first_same_bus_in_service_gen_idx:
655 -
            pp_res["gen"] = np.append(pp_res["gen"], np.array(net.res_gen[
656 -
                    net.gen.bus == current_bus_idx][['p_mw', 'q_mvar']]).reshape((1, 2)), 0)
536 +
    # --- bus
537 +
    pp_res["bus"] = net.res_bus.loc[ppc["bus"][:, BUS_I].astype(int), ['vm_pu', 'va_degree']].values
538 +
539 +
    # --- branch
540 +
    pp_res["branch"] = np.zeros(ppc_res["branch"].shape)
541 +
    from_to_buses = -np.ones((ppc_res["branch"].shape[0], 2), dtype=int)
542 +
    for et in net._from_ppc_lookups["branch"].element_type.unique():
543 +
        if et == "line":
544 +
            from_to_cols = ["from_bus", "to_bus"]
545 +
            res_cols = ['p_from_mw', 'q_from_mvar', 'p_to_mw', 'q_to_mvar']
546 +
        elif et == "trafo":
547 +
            from_to_cols = ["hv_bus", "lv_bus"]
548 +
            res_cols = ['p_hv_mw', 'q_hv_mvar', 'p_lv_mw', 'q_lv_mvar']
657 549
        else:
658 -
            pp_res["gen"] = np.append(pp_res["gen"], np.array(net.res_sgen[
659 -
                net.sgen.bus == current_bus_idx][['p_mw', 'q_mvar']])[
660 -
                already_used_gen.at[int(j)]].reshape((1, 2)), 0)
661 -
            already_used_gen.at[int(j)] += 1
662 -
            change_q_compare += [int(j)]
663 -
    pp_res["gen"] = pp_res["gen"][1:, :]  # delete initial zero row
664 -
665 -
    # --- pandapower branch result table
666 -
    pp_res["branch"] = np.zeros([1, 4])
667 -
    # consideration of parallel branches via storing how often branches were considered
668 -
    # each node-to-node-connection
669 -
    try:
670 -
        init1 = pd.concat([net.line.from_bus, net.line.to_bus], axis=1,
671 -
                          sort=True).drop_duplicates()
672 -
        init2 = pd.concat([net.trafo.hv_bus, net.trafo.lv_bus], axis=1,
673 -
                          sort=True).drop_duplicates()
674 -
    except TypeError:
675 -
        # legacy pandas < 0.21
676 -
        init1 = pd.concat([net.line.from_bus, net.line.to_bus], axis=1).drop_duplicates()
677 -
        init2 = pd.concat([net.trafo.hv_bus, net.trafo.lv_bus], axis=1).drop_duplicates()
678 -
    init1['hv_bus'] = np.nan
679 -
    init1['lv_bus'] = np.nan
680 -
    init2['from_bus'] = np.nan
681 -
    init2['to_bus'] = np.nan
682 -
    try:
683 -
        already_used_branches = pd.concat([init1, init2], axis=0, sort=True)
684 -
    except TypeError:
685 -
        # pandas < 0.21 legacy
686 -
        already_used_branches = pd.concat([init1, init2], axis=0)
687 -
    already_used_branches['number'] = np.zeros([already_used_branches.shape[0], 1]).astype(int)
688 -
    BRANCHES = pd.DataFrame(ppc_net['branch'][:, [0, 1, TAP, SHIFT]])
689 -
    for i in BRANCHES.index:
690 -
        from_bus = get_element_index(net, 'bus', name=int(ppc_net['branch'][i, 0]))
691 -
        to_bus = get_element_index(net, 'bus', name=int(ppc_net['branch'][i, 1]))
692 -
        from_vn_kv = ppc_net['bus'][from_bus, BASE_KV]
693 -
        to_vn_kv = ppc_net['bus'][to_bus, BASE_KV]
694 -
        ratio = BRANCHES[2].at[i]
695 -
        angle = BRANCHES[3].at[i]
696 -
        # from line results
697 -
        if (from_vn_kv == to_vn_kv) & ((ratio == 0) | (ratio == 1)) & (angle == 0):
698 -
            pp_res["branch"] = np.append(pp_res["branch"], np.array(net.res_line[
699 -
                (net.line.from_bus == from_bus) &
700 -
                (net.line.to_bus == to_bus)]
701 -
                [['p_from_mw', 'q_from_mvar', 'p_to_mw', 'q_to_mvar']])[
702 -
                int(already_used_branches.number.loc[
703 -
                   (already_used_branches.from_bus == from_bus) &
704 -
                   (already_used_branches.to_bus == to_bus)].values)].reshape(1, 4), 0)
705 -
            already_used_branches.number.loc[(already_used_branches.from_bus == from_bus) &
706 -
                                             (already_used_branches.to_bus == to_bus)] += 1
707 -
        # from trafo results
708 -
        else:
709 -
            if from_vn_kv >= to_vn_kv:
710 -
                pp_res["branch"] = np.append(pp_res["branch"], np.array(net.res_trafo[
711 -
                    (net.trafo.hv_bus == from_bus) &
712 -
                    (net.trafo.lv_bus == to_bus)]
713 -
                    [['p_hv_mw', 'q_hv_mvar', 'p_lv_mw', 'q_lv_mvar']])[
714 -
                    int(already_used_branches.number.loc[
715 -
                        (already_used_branches.hv_bus == from_bus) &
716 -
                        (already_used_branches.lv_bus == to_bus)].values)].reshape(1, 4), 0)
717 -
                already_used_branches.number.loc[(already_used_branches.hv_bus == from_bus) &
718 -
                                                 (already_used_branches.lv_bus == to_bus)] += 1
719 -
            else:  # switch hv-lv-connection of pypower connection buses
720 -
                pp_res["branch"] = np.append(pp_res["branch"], np.array(net.res_trafo[
721 -
                    (net.trafo.hv_bus == to_bus) &
722 -
                    (net.trafo.lv_bus == from_bus)]
723 -
                    [['p_lv_mw', 'q_lv_mvar', 'p_hv_mw', 'q_hv_mvar']])[
724 -
                    int(already_used_branches.number.loc[
725 -
                        (already_used_branches.hv_bus == to_bus) &
726 -
                        (already_used_branches.lv_bus == from_bus)].values)].reshape(1, 4), 0)
727 -
                already_used_branches.number.loc[
728 -
                    (already_used_branches.hv_bus == to_bus) &
729 -
                    (already_used_branches.lv_bus == from_bus)] += 1
730 -
    pp_res["branch"] = pp_res["branch"][1:, :]  # delete initial zero row
731 -
732 -
    # --- do the powerflow result comparison
733 -
    diff_res = dict.fromkeys(ppc_elms)
734 -
    diff_res["bus"] = ppc_res["bus"] - pp_res["bus"]
735 -
    diff_res["bus"][:, 1] -= diff_res["bus"][0, 1]  # remove va_degree offset
736 -
    diff_res["branch"] = ppc_res["branch"] - pp_res["branch"]
737 -
    diff_res["gen"] = ppc_res["gen"] - pp_res["gen"]
738 -
    # comparison of buses with several generator units only as q sum
739 -
    for i in GEN_uniq.loc[GEN_uniq[0].isin(change_q_compare)].index:
740 -
        next_is = GEN_uniq.index[GEN_uniq.index > i]
741 -
        if len(next_is) > 0:
742 -
            next_i = next_is[0]
743 -
        else:
744 -
            next_i = GENS.index[-1] + 1
745 -
        if (next_i - i) > 1:
746 -
            diff_res["gen"][i:next_i, 1] = sum(diff_res["gen"][i:next_i, 1])
747 -
    # logger info
748 -
    logger.debug("Maximum voltage magnitude difference between pypower and pandapower: "
749 -
                 "%.2e pu" % np.max(abs(diff_res["bus"][:, 0])))
750 -
    logger.debug("Maximum voltage angle difference between pypower and pandapower: "
751 -
                 "%.2e degree" % np.max(abs(diff_res["bus"][:, 1])))
752 -
    logger.debug("Maximum branch flow active power difference between pypower and pandapower: "
753 -
                 "%.2e MW" % np.max(abs(diff_res["branch"][:, [0, 2]])))
754 -
    logger.debug("Maximum branch flow reactive power difference between pypower and "
755 -
                 "pandapower: %.2e MVAr" % np.max(abs(diff_res["branch"][:, [1, 3]])))
756 -
    logger.debug("Maximum active power generation difference between pypower and pandapower: "
757 -
                 "%.2e MW" % np.max(abs(diff_res["gen"][:, 0])))
758 -
    logger.debug("Maximum reactive power generation difference between pypower and pandapower: "
759 -
                 "%.2e MVAr" % np.max(abs(diff_res["gen"][:, 1])))
760 -
    if _validate_diff_res(diff_res, {"bus_vm_pu": 1e-3, "bus_va_degree": 1e-3, "branch_p_mw": 1e-6,
761 -
                                     "branch_q_mvar": 1e-6}) and \
762 -
            (np.max(abs(diff_res["gen"])) > 1e-1).any():
763 -
        logger.debug("The active/reactive power generation difference possibly results "
764 -
                     "because of a pypower error. Please validate "
765 -
                     "the results via pypower loadflow.")  # this occurs e.g. at ppc case9
766 -
    # give a return
767 -
    if isinstance(max_diff_values, dict):
768 -
        return _validate_diff_res(diff_res, max_diff_values)
769 -
    else:
770 -
        logger.debug("'max_diff_values' must be a dict.")
550 +
            raise NotImplementedError(
551 +
                f"result columns for element type {et} are not implemented.")
552 +
        is_et = net._from_ppc_lookups["branch"].element_type == et
553 +
        pp_res["branch"][is_et] += net[f"res_{et}"].loc[
554 +
            net._from_ppc_lookups["branch"].element.loc[is_et], res_cols].values
555 +
        from_to_buses[is_et] = net[et].loc[
556 +
            net._from_ppc_lookups["branch"].element.loc[is_et], from_to_cols].values
557 +
558 +
    # switch direction as in ppc
559 +
    correct_from_to = np.all(from_to_buses == ppc["branch"][:, F_BUS:T_BUS+1].astype(int), axis=1)
560 +
    switch_from_to = np.all(from_to_buses[:, ::-1] == ppc["branch"][:, F_BUS:T_BUS+1].astype(
561 +
        int), axis=1)
562 +
    if not np.all(correct_from_to | switch_from_to):
563 +
        raise ValueError("ppc branch from and to buses don't fit to pandapower from and to + "
564 +
                        "hv and lv buses.")
565 +
    if np.any(switch_from_to):
566 +
        pp_res["branch"][switch_from_to, :] = pp_res["branch"][switch_from_to, :][:, [2, 3, 0, 1]]
567 +
568 +
    # --- gen
569 +
    pp_res["gen"] = np.zeros(ppc_res["gen"].shape)
570 +
    res_cols = ['p_mw', 'q_mvar']
571 +
    for et in net._from_ppc_lookups["gen"].element_type.unique():
572 +
        is_et = net._from_ppc_lookups["gen"].element_type == et
573 +
        pp_res["gen"][is_et] += net[f"res_{et}"].loc[
574 +
            net._from_ppc_lookups["gen"].element.loc[is_et], res_cols].values
575 +
576 +
    pp_res["gen_p"] = ppc_res["gen"][:, :1]
577 +
    pp_res["gen_q_sum_per_bus"] = _gen_q_per_bus_sum(pp_res["gen"][:, -1:], ppc)
578 +
579 +
    # --- log maximal differences the powerflow result comparison
580 +
    diff_res = dict()
581 +
    comp_keys = ["bus", "branch", "gen_p", "gen_q_sum_per_bus"]
582 +
    for comp_key in comp_keys:
583 +
        diff_res[comp_key] = ppc_res[comp_key] - pp_res[comp_key]
584 +
        if isinstance(diff_res[comp_key], pd.DataFrame):
585 +
            diff_res[comp_key] = diff_res[comp_key].values
586 +
        for i_col, var_str, unit in zip(*_log_dict(comp_key)):
587 +
            diff = diff_res[comp_key][:, i_col]
588 +
            logger.debug(f"Maximum {var_str} difference between pandapower and pypower: "
589 +
                         "%.2e %s" % (np.max(abs(diff)), unit))
590 +
591 +
    # --- do the powerflow result comparison -------------------------------------------------------
592 +
    pf_match = _validate_diff_res(diff_res, max_diff_values)
593 +
594 +
    # --- case of missmatch: result comparison with different max_diff (unwanted behaviour of
595 +
    # pypower possible)
596 +
    if not pf_match:
597 +
        other_max_diff = {
598 +
            "bus_vm_pu": 1e-3, "bus_va_degree": 1e-3, "branch_p_mw": 1e-6, "branch_q_mvar": 1e-6,
599 +
            "gen_p_mw": None, "gen_q_mvar": None}
600 +
        if _validate_diff_res(diff_res, other_max_diff) and \
601 +
                (np.max(abs(pp_res["gen"] - ppc_res["gen"])) > 1e-1).any():
602 +
            logger.debug("The active/reactive power generation difference possibly results "
603 +
                        "because of a pypower error. Please validate "
604 +
                        "the results via pypower loadflow.")  # this occurs e.g. at ppc case9
605 +
606 +
    return pf_match
771 607
772 608
773 609
if __name__ == "__main__":

@@ -134,7 +134,7 @@
Loading
134 134
        # Find pq bus with zero p,q and shunt admittance
135 135
        if not np.any(eppci["bus"][:, bus_cols + ZERO_INJ_FLAG]):
136 136
            raise UserWarning("Network has no bus with zero injections! Please use WLS instead!")
137 -
        zero_injection_bus = np.argwhere(eppci["bus"][:, bus_cols + ZERO_INJ_FLAG] == True).ravel()
137 +
        zero_injection_bus = np.argwhere(eppci["bus"][:, bus_cols + ZERO_INJ_FLAG]).ravel()
138 138
        eppci["bus"][np.ix_(zero_injection_bus, [bus_cols + P, bus_cols + P_STD, bus_cols + Q, bus_cols + Q_STD])] = np.NaN
139 139
        # Withn pq buses with zero injection identify those who have also no p or q measurement
140 140
        p_zero_injections = zero_injection_bus

@@ -400,7 +400,7 @@
Loading
400 400
    :param ppc: pypower case file
401 401
    :return:
402 402
    """
403 -
    br_status = ppc['branch'][:, BR_STATUS] == True
403 +
    br_status = ppc['branch'][:, BR_STATUS].astype(bool)
404 404
    nobranch = ppc['branch'][br_status, :].shape[0]
405 405
    nobus = ppc['bus'].shape[0]
406 406
    bus_from = ppc['branch'][br_status, F_BUS].real.astype(int)
@@ -439,7 +439,7 @@
Loading
439 439
    :param ppc: pypower case file
440 440
    :return:
441 441
    """
442 -
    br_status = ppc['branch'][:, BR_STATUS] == True
442 +
    br_status = ppc['branch'][:, BR_STATUS].astype(bool)
443 443
    nobranch = ppc['branch'][br_status, :].shape[0]
444 444
    nobus = ppc['bus'].shape[0]
445 445
    bus_from = ppc['branch'][br_status, F_BUS].real.astype(int)
@@ -470,7 +470,7 @@
Loading
470 470
    :param ppc: pypower case file
471 471
    :return:
472 472
    """
473 -
    br_status = ppc['branch'][:, BR_STATUS] == True
473 +
    br_status = ppc['branch'][:, BR_STATUS].astype(bool)
474 474
    oos_bus = ppc['bus'][:, BUS_TYPE] == NONE
475 475
    nobranch = ppc['branch'][br_status, :].shape[0]
476 476
    nobus = ppc['bus'].shape[0]

@@ -183,9 +183,9 @@
Loading
183 183
184 184
def create_bus_lookup(net, bus_index, bus_is_idx, gen_is_mask, eg_is_mask, numba):
185 185
    switches_with_pos_z_ohm = net["switch"]["z_ohm"].values > 0
186 -
    if switches_with_pos_z_ohm.any() or numba == False:
186 +
    if switches_with_pos_z_ohm.any() or not numba:
187 187
        # if there are any closed bus-bus switches find them
188 -
        closed_bb_switch_mask = ((net["switch"]["closed"].values == True) &
188 +
        closed_bb_switch_mask = (net["switch"]["closed"].values &
189 189
                                 (net["switch"]["et"].values == "b") &
190 190
                                 np.in1d(net["switch"]["bus"].values, bus_is_idx) &
191 191
                                 np.in1d(net["switch"]["element"].values, bus_is_idx))

@@ -1807,8 +1807,9 @@
Loading
1807 1807
            dtypes = net[element].dtypes
1808 1808
            net[element] = pd.concat([net[element], net2[element]], sort=False,
1809 1809
                                     ignore_index=ignore_index)
1810 -
            if retain_original_indices_in_net1 and not elm_with_critical_index:
1811 -
                start = net1.bus.index.max() + 1
1810 +
            if retain_original_indices_in_net1 and not elm_with_critical_index and \
1811 +
                len(net1[element]):
1812 +
                start = int(net1[element].index.max()) + 1
1812 1813
                net[element].index = net1[element].index.tolist() + \
1813 1814
                    list(range(start, len(net2[element]) + start))
1814 1815
            _preserve_dtypes(net[element], dtypes)
@@ -1899,8 +1900,7 @@
Loading
1899 1900
1900 1901
    # check switching state and add line switch if necessary:
1901 1902
    for bus in net.line.at[idx, "to_bus"], net.line.at[idx, "from_bus"]:
1902 -
        if bus in net.switch[(net.switch.closed == False) & (net.switch.element == idx) &
1903 -
                             (net.switch.et == "l")].bus.values:
1903 +
        if bus in net.switch[~net.switch.closed & (net.switch.element == idx) & (net.switch.et == "l")].bus.values:
1904 1904
            create_switch(net, bus=bus, element=new_idx, closed=False, et="l", type="LBS")
1905 1905
1906 1906
    return new_idx

@@ -124,12 +124,12 @@
Loading
124 124
        add_p_constraints(net, "ext_grid", eg_is, ppc, f, t, delta)
125 125
126 126
        if "controllable" in net["ext_grid"]:
127 -
            #     if we do and one of them is false, do this only for the ones, where it is false
128 -
            eg_constrained = net.ext_grid[eg_is][net.ext_grid.controllable == False]
127 +
            # if we do and one of them is false, do this only for the ones, where it is false
128 +
            eg_constrained = net.ext_grid[eg_is][~net.ext_grid.controllable]
129 129
            if len(eg_constrained):
130 -
                eg_constrained_bus = eg_constrained.bus
131 -
                ppc["bus"][eg_constrained_bus, VMAX] = net["ext_grid"]["vm_pu"].values[eg_constrained.index] + delta
132 -
                ppc["bus"][eg_constrained_bus, VMIN] = net["ext_grid"]["vm_pu"].values[eg_constrained.index] - delta
130 +
                eg_constrained_bus_ppc = [bus_lookup[egb] for egb in eg_constrained.bus.values]
131 +
                ppc["bus"][eg_constrained_bus_ppc, VMAX] = net["ext_grid"]["vm_pu"].values[eg_constrained.index] + delta
132 +
                ppc["bus"][eg_constrained_bus_ppc, VMIN] = net["ext_grid"]["vm_pu"].values[eg_constrained.index] - delta
133 133
        else:
134 134
            # if we dont:
135 135
            ppc["bus"][eg_buses, VMAX] = net["ext_grid"]["vm_pu"].values[eg_is] + delta

@@ -157,7 +157,7 @@
Loading
157 157
    eq_power = net_external.res_ext_grid.copy()
158 158
    eq_power["bus"] = net_external.ext_grid.bus.values
159 159
    eq_power["elm"] = "ext_grid"
160 -
    slack_gen = net_external.gen.index[net_external.gen.slack==True]
160 +
    slack_gen = net_external.gen.index[net_external.gen.slack]
161 161
    if len(slack_gen) != 0:
162 162
        for i in slack_gen:
163 163
            new_eq_power = \
@@ -240,7 +240,7 @@
Loading
240 240
    eq_power = net_external.res_ext_grid.copy()
241 241
    eq_power["bus"] = net_external.ext_grid.bus.values
242 242
    eq_power["elm"] = "ext_grid"
243 -
    slack_gen = net_external.gen.index[net_external.gen.slack==True]
243 +
    slack_gen = net_external.gen.index[net_external.gen.slack]
244 244
    if len(slack_gen) != 0:
245 245
        for i in slack_gen:
246 246
            new_eq_power = \

@@ -56,7 +56,7 @@
Loading
56 56
        df = net.res_storage
57 57
        df[["ps", "qs", "se", "qsc"]] = pd.DataFrame([[np.nan, np.nan, np.nan, np.nan]], index=df.index)
58 58
        df[["sc", "sc_on", "sd", "sd_on"]] = pd.DataFrame([[np.nan, np.nan, np.nan, np.nan]], index=df.index) 
59 -
        controllable_storages = net.storage.index[net.storage.controllable==True]
59 +
        controllable_storages = net.storage.index[net.storage.controllable]
60 60
        df_pm = pd.DataFrame.from_dict(result_pmi["storage"]).T
61 61
        df_pm.index = controllable_storages
62 62
        df.loc[controllable_storages] = df_pm

@@ -429,7 +429,7 @@
Loading
429 429
        all_diffs["load_q_diff_is"] = load_q_diff_is
430 430
431 431
    logger.debug('verifying ext_grid')
432 -
    eg_oos = net.ext_grid[net.ext_grid.in_service == False].index
432 +
    eg_oos = net.ext_grid[~net.ext_grid.in_service].index
433 433
    ext_grid_p_diff = net.res_ext_grid.pf_p.replace(np.nan, 0).drop(eg_oos) - net.res_ext_grid.p_mw
434 434
    ext_grid_q_diff = net.res_ext_grid.pf_q.replace(np.nan, 0).drop(
435 435
        eg_oos) - net.res_ext_grid.q_mvar

@@ -642,10 +642,9 @@
Loading
642 642
    calculate_voltage_angles = net._options["calculate_voltage_angles"]
643 643
    neglect_open_switch_branches = net._options["neglect_open_switch_branches"]
644 644
    mode = net._options["mode"]
645 -
    open_switches = (net.switch.closed.values == False)
646 645
    n_bus = ppc["bus"].shape[0]
647 646
    for et, element in [("l", "line"), ("t", "trafo"), ("t3", "trafo3w")]:
648 -
        switch_mask = open_switches & (net.switch.et.values == et)
647 +
        switch_mask = ~net.switch.closed.values & (net.switch.et.values == et)
649 648
        if not switch_mask.any():
650 649
            continue
651 650
        nr_open_switches = np.count_nonzero(switch_mask)

@@ -617,6 +617,7 @@
Loading
617 617
    if "in_ka" in net.switch.columns:
618 618
        net[res_switch_df]["loading_percent"] = net[res_switch_df]["i_ka"].values / net.switch["in_ka"].values * 100
619 619
        
620 +
620 621
def _copy_switch_results_from_branches(net, suffix=None, current_parameter="i_ka"):
621 622
    res_switch_df = "res_switch" if suffix is None else "res_switch%s" % suffix
622 623
@@ -636,6 +637,6 @@
Loading
636 637
            current, unit = current_parameter.split("_")
637 638
            side_current = "{}_{}_{}".format(current, side, unit)
638 639
            net[res_switch_df].loc[switches, current_parameter] = net[res_trafo_df].loc[trafos, side_current].values
639 -
    open_switches = net.switch.closed.values==False
640 +
    open_switches = ~net.switch.closed.values
640 641
    if any(open_switches):
641 642
        net[res_switch_df].loc[open_switches, current_parameter] = 0

@@ -366,7 +366,7 @@
Loading
366 366
    if kwargs.get("drop_boundary_buses", True):
367 367
        pp.drop_elements_at_buses(net_internal, boundary_buses_inclusive_bswitch,
368 368
                                  branch_elements=False)
369 -
369 +
  
370 370
    # --- merge equivalent external net and internal net
371 371
    merged_net = pp.merge_nets(net_internal, net_eq, validate=kwargs.pop("validate", False),
372 372
                               retain_original_indices_in_net1=retain_original_internal_indices,
@@ -446,10 +446,11 @@
Loading
446 446
    unsupplied_boundary_buses = boundary_buses & unsupplied_buses
447 447
    if len(unsupplied_boundary_buses):
448 448
        raise ValueError(
449 -
            "Although get_equivalent() do not allow unsupplied boundary " +
449 +
            "get_equivalent() do not allow unsupplied boundary " +
450 450
            "buses, these have no voltage results (possibly because power " +
451 451
            "flow results miss, the buses are isolated " +
452 -
            "or out of service): " + str(sorted(unsupplied_boundary_buses)))
452 +
            "or out of service): " + str(sorted(unsupplied_boundary_buses)) +
453 +
            ". Remove these buses from the boundary buses and try again.")
453 454
454 455
    if internal_buses & boundary_buses:
455 456
        logger.info("Some internal buses are also contained in the boundary buses, " +

@@ -168,6 +168,9 @@
Loading
168 168
            net, boundary_buses, all_internal_buses, all_external_buses,
169 169
            show_computing_time, calc_volt_angles=calc_volt_angles, runpp_fct=runpp_fct)
170 170
    net_zpbn = net_external
171 +
    # --- remove buses without power flow results in net_eq
172 +
    # pp.drop_buses(net_zpbn, net_zpbn.res_bus.index[net_zpbn.res_bus.vm_pu.isnull()])
173 +
    
171 174
    Z, S, v, limits = calc_zpbn_parameters(net_zpbn, boundary_buses, all_external_buses)
172 175
    # --- remove the original load, sgen and gen in exteranl area,
173 176
    #     and creat new buses and impedance
Files Coverage
pandapower 76.70%
setup.py 0.00%
Project Totals (189 files) 76.65%

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading