예제 #1
0
def wrong_switch_configuration(net):
    """
    Checks, if a loadflow calculation converges. If not, checks, if the switch configuration is
    the reason for that by closing all switches

     INPUT:

        **net** (PandapowerNet)         - variable that contains a pandapower network

     RETURN:

        **check_result** (boolean)

     EXAMPLE:

        import misc
        misc.check_wrong_switch_configuration(net)


    """
    switch_configuration = copy.deepcopy(net.switch.closed)
    try:
        runpp(net)

    except:
        try:
            net.switch.closed = 1
            runpp(net)
            net.switch.closed = switch_configuration
            return True
        except:
            net.switch.closed = switch_configuration
            return 'uncertain'
예제 #2
0
def impedance_values_close_to_zero(net, min_r_ohm, min_x_ohm, min_r_pu, min_x_pu):
    """
    Checks, if there are lines, xwards or impedances with an impedance value close to zero.

     INPUT:
        **net** (pandapowerNet)         - pandapower network


     OUTPUT:
        **implausible_lines** (list)    - list that contains the indices of all lines with an
                                          impedance value of zero.


    """
    check_results = []
    implausible_elements = {}

    line = net.line[((net.line.r_ohm_per_km * net.line.length_km) <= min_r_ohm)
                    | ((net.line.x_ohm_per_km * net.line.length_km) <= min_x_ohm) & net.line.in_service].index

    xward = net.xward[(net.xward.r_ohm <= min_r_ohm)
                      | (net.xward.x_ohm <= min_x_ohm) & net.xward.in_service].index

    impedance = net.impedance[(net.impedance.rft_pu <= min_r_pu)
                              | (net.impedance.xft_pu <= min_x_pu)
                              | (net.impedance.rtf_pu <= min_r_pu)
                              | (net.impedance.xtf_pu <= min_x_pu) & net.impedance.in_service].index
    if len(line) > 0:
        implausible_elements['line'] = list(line)
    if len(xward) > 0:
        implausible_elements['xward'] = list(xward)
    if len(impedance) > 0:
        implausible_elements['impedance'] = list(impedance)
    check_results.append(implausible_elements)
    # checks if loadflow converges when implausible lines or impedances are replaced by switches
    if ("line" in implausible_elements) or ("impedance" in implausible_elements):
        switch_copy = copy.deepcopy(net.switch)
        line_copy = copy.deepcopy(net.line)
        impedance_copy = copy.deepcopy(net.impedance)
        try:
            runpp(net)
        except:
            try:
                for key in implausible_elements:
                    if key == 'xward':
                        continue
                    implausible_idx = implausible_elements[key]
                    net[key].in_service.loc[implausible_idx] = False
                    for idx in implausible_idx:
                        pp.create_switch(net, net[key].from_bus.at[idx], net[key].to_bus.at[idx], et="b")
                runpp(net)
                switch_replacement = True
            except:
                switch_replacement = False
            check_results.append({"loadflow_converges_with_switch_replacement": switch_replacement})
        net.switch = switch_copy
        net.line = line_copy
        net.impedance = impedance_copy
    if implausible_elements:
        return check_results
예제 #3
0
def wrong_switch_configuration(net):
    """
    Checks, if a loadflow calculation converges. If not, checks, if the switch configuration is
    the reason for that by closing all switches

     INPUT:
        **net** (pandapowerNet)         - pandapower network

     OUTPUT:
        **check_result** (boolean)

    """
    switch_configuration = copy.deepcopy(net.switch.closed)
    try:
        runpp(net)

    except (ValueError, LoadflowNotConverged):
        try:
            net.switch.closed = 1
            runpp(net)
            net.switch.closed = switch_configuration
            return True
        except LoadflowNotConverged:
            net.switch.closed = switch_configuration
            return 'uncertain'
예제 #4
0
def numba_comparison(net, numba_tolerance):
    """
        Compares the results of loadflows with numba=True vs. numba=False.

         INPUT:
            **net** (pandapowerNet)    - pandapower network

         OPTIONAL:
            **tol** (float, 1e-5)      - Maximum absolute deviation allowed between
                                         numba=True/False results.

         OUTPUT:
            **check_result** (dict)    - Absolute deviations between numba=True/False results.
    """
    check_results = {}
    try:
        runpp(net, numba=True)
    except LoadflowNotConverged:
        pass
    if net.converged:
        try:
            result_numba_true = copy.deepcopy(net)
            runpp(net, numba=False)
            result_numba_false = copy.deepcopy(net)
            res_keys = [
                key for key in result_numba_true.keys() if (key in [
                    'res_bus', 'res_ext_grid', 'res_gen', 'res_impedance',
                    'res_line', 'res_load', 'res_sgen', 'res_shunt',
                    'res_trafo', 'res_trafo3w', 'res_ward', 'res_xward'
                ])
            ]
            for key in res_keys:
                diffs = abs(result_numba_true[key] -
                            result_numba_false[key]) > numba_tolerance
                if any(diffs.any()):
                    if (key not in check_results.keys()):
                        check_results[key] = {}
                    for col in diffs.columns:
                        if (col not in check_results[key].keys()) and (
                                diffs.any()[col]):
                            check_results[key][col] = {}
                            numba_true = result_numba_true[key][col][
                                diffs[col]]
                            numba_false = result_numba_false[key][col][
                                diffs[col]]
                            check_results[key][col] = abs(numba_true -
                                                          numba_false)
        except LoadflowNotConverged:
            pass

    if check_results:
        return check_results
예제 #5
0
def overload(net, overload_scaling_factor):
    """
    Checks, if a loadflow calculation converges. If not, checks, if an overload is the reason for
    that by scaling down the loads, gens and sgens to 0.1%.

     INPUT:
        **net** (pandapowerNet)         - pandapower network


     OUTPUT:
        **check_results** (dict)        - dict with the results of the overload check
                                          Format: {'load_overload': True/False
                                                   'generation_overload', True/False}

    """
    check_result = {}
    load_scaling = copy.deepcopy(net.load.scaling)
    gen_scaling = copy.deepcopy(net.gen.scaling)
    sgen_scaling = copy.deepcopy(net.sgen.scaling)

    try:
        runpp(net)
    except LoadflowNotConverged:
        check_result['load'] = False
        check_result['generation'] = False
        try:
            net.load.scaling = overload_scaling_factor
            runpp(net)
            check_result['load'] = True
        except:
            net.load.scaling = load_scaling
            try:
                net.gen.scaling = overload_scaling_factor
                net.sgen.scaling = overload_scaling_factor
                runpp(net)
                check_result['generation'] = True
            except:
                net.sgen.scaling = sgen_scaling
                net.gen.scaling = gen_scaling
                try:
                    net.load.scaling = overload_scaling_factor
                    net.gen.scaling = overload_scaling_factor
                    net.sgen.scaling = overload_scaling_factor
                    runpp(net)
                    check_result['generation'] = True
                    check_result['load'] = True
                except:
                    pass
        net.sgen.scaling = sgen_scaling
        net.gen.scaling = gen_scaling
        net.load.scaling = load_scaling
    if check_result:
        return check_result
예제 #6
0
def overload(net, overload_scaling_factor):
    """
    Checks, if a loadflow calculation converges. If not, checks, if an overload is the reason for
    that by scaling down the loads, gens and sgens to 0.1%.

     INPUT:

        **net** (PandapowerNet)         - variable that contains a pandapower network


     RETURN:

        **check_results** (dict)        - dict with the results of the overload check
                                          Format: {'load_overload': True/False/uncertain
                                                   'generation_overload', True/False/uncertain}

     EXAMPLE:

         import misc
         misc.check_overload(net)

    """
    check_result = {}
    load_scaling = copy.deepcopy(net.load.scaling)
    gen_scaling = copy.deepcopy(net.gen.scaling)
    sgen_scaling = copy.deepcopy(net.sgen.scaling)
    try:
        runpp(net)

    except:
        try:
            net.load.scaling = overload_scaling_factor
            runpp(net)
            net.load.scaling = load_scaling
            check_result['load'] = True

        except:
            net.load.scaling = load_scaling
            check_result['load'] = 'uncertain'

        try:
            net.gen.scaling = overload_scaling_factor
            net.sgen.scaling = overload_scaling_factor
            runpp(net)
            net.gen.scaling = gen_scaling
            net.gen.scaling = sgen_scaling
            check_result['generation'] = True

        except:
            net.gen.scaling = gen_scaling
            check_result['generation'] = 'uncertain'

    if check_result:
        return check_result
예제 #7
0
def pf_res_plotly(net, cmap="Jet", use_line_geodata=None, on_map=False, projection=None,
                  map_style='basic', figsize=1, aspectratio='auto', line_width=2, bus_size=10,
                  climits_volt=(0.9, 1.1), climits_load=(0, 100), cpos_volt=1.0, cpos_load=1.1,
                  filename="temp-plot.html", auto_open=True):
    """
        Plots a pandapower network in plotly

        using colormap for coloring lines according to line loading and buses according to voltage in p.u.
        If no geodata is available, artificial geodata is generated. For advanced plotting see the tutorial

        INPUT:
            **net** - The pandapower format network. If none is provided, mv_oberrhein() will be plotted as an example

        OPTIONAL:
            **respect_switches** (bool, False) - Respect switches when artificial geodata is created

            **cmap** (str, True) - name of the colormap

            **colors_dict** (dict, None) - by default 6 basic colors from default collor palette is used.
                                                Otherwise, user can define a dictionary in the form: voltage_kv : color

            **on_map** (bool, False) - enables using mapbox plot in plotly. If provided geodata are not
                                                    real geo-coordinates in lon/lat form, on_map will be set to False.

            **projection** (String, None) - defines a projection from which network geo-data will be transformed to
                                            lat-long. For each projection a string can be found at http://spatialreference.org/ref/epsg/

            **map_style** (str, 'basic') - enables using mapbox plot in plotly

            - 'streets'
            - 'bright'
            - 'light'
            - 'dark'
            - 'satellite'

            **figsize** (float, 1) - aspectratio is multiplied by it in order to get final image size

            **aspectratio** (tuple, 'auto') - when 'auto' it preserves original aspect ratio of the network geodata
                                                    any custom aspectration can be given as a tuple, e.g. (1.2, 1)

            **line_width** (float, 1.0) - width of lines

            **bus_size** (float, 10.0) -  size of buses to plot.

            **climits_volt** (tuple, (0.9, 1.0)) - limits of the colorbar for voltage

            **climits_load** (tuple, (0, 100)) - limits of the colorbar for line_loading

            **cpos_volt** (float, 1.0) - position of the bus voltage colorbar

            **cpos_load** (float, 1.1) - position of the loading percent colorbar

            **filename** (str, "temp-plot.html") - filename / path to plot to. Should end on `*.html`

            **auto_open** (bool, True) - automatically open plot in browser

        OUTPUT:
            **figure** (graph_objs._figure.Figure) figure object

    """

    version_check()
    if 'res_bus' not in net or net.get('res_bus').shape[0] == 0:
        logger.warning('There are no Power Flow results. A Newton-Raphson power flow will be executed.')
        runpp(net)

    # create geocoord if none are available
    if 'line_geodata' not in net:
        net.line_geodata = pd.DataFrame(columns=['coords'])
    if 'bus_geodata' not in net:
        net.bus_geodata = pd.DataFrame(columns=["x", "y"])
    if len(net.line_geodata) == 0 and len(net.bus_geodata) == 0:
        logger.warning("No or insufficient geodata available --> Creating artificial coordinates." +
                       " This may take some time")
        create_generic_coordinates(net, respect_switches=True)
        if on_map:
            logger.warning("Map plots not available with artificial coordinates and will be disabled!")
            on_map = False
    for geo_type in ["bus_geodata", "line_geodata"]:
        dupl_geo_idx = pd.Series(net[geo_type].index)[pd.Series(
                net[geo_type].index).duplicated()]
        if len(dupl_geo_idx):
            if len(dupl_geo_idx) > 20:
                logger.warning("In net.%s are %i duplicated " % (geo_type, len(dupl_geo_idx)) +
                               "indices. That can cause troubles for draw_traces()")
            else:
                logger.warning("In net.%s are the following duplicated " % geo_type +
                               "indices. That can cause troubles for draw_traces(): " + str(
                               dupl_geo_idx))


    # check if geodata are real geographycal lat/lon coordinates using geopy
    if on_map and projection is not None:
        geo_data_to_latlong(net, projection=projection)

    # ----- Buses ------
    # initializating bus trace
    # hoverinfo which contains name and pf results
    precision = 3
    hoverinfo = (
            net.bus.name.astype(str) + '<br />' +
            'V_m = ' + net.res_bus.vm_pu.round(precision).astype(str) + ' pu' + '<br />' +
            'V_m = ' + (net.res_bus.vm_pu * net.bus.vn_kv.round(2)).round(precision).astype(str) + ' kV' + '<br />' +
            'V_a = ' + net.res_bus.va_degree.round(precision).astype(str) + ' deg').tolist()
    hoverinfo = pd.Series(index=net.bus.index, data=hoverinfo)
    bus_trace = create_bus_trace(net, net.bus.index, size=bus_size, infofunc=hoverinfo, cmap=cmap,
                                 cbar_title='Bus Voltage [pu]', cmin=climits_volt[0], cmax=climits_volt[1],
                                 cpos=cpos_volt)

    # ----- Lines ------
    # if bus geodata is available, but no line geodata
    # if bus geodata is available, but no line geodata
    cmap_lines = 'jet' if cmap == 'Jet' else cmap
    if use_line_geodata is None:
        use_line_geodata = False if len(net.line_geodata) == 0 else True
    elif use_line_geodata and len(net.line_geodata) == 0:
        logger.warning("No or insufficient line geodata available --> only bus geodata will be used.")
        use_line_geodata = False
    # hoverinfo which contains name and pf results
    hoverinfo = (
            net.line.name.astype(str) + '<br />' +
            'I = ' + net.res_line.loading_percent.round(precision).astype(str) + ' %' + '<br />' +
            'I_from = ' + net.res_line.i_from_ka.round(precision).astype(str) + ' kA' + '<br />' +
            'I_to = ' + net.res_line.i_to_ka.round(precision).astype(str) + ' kA' + '<br />').tolist()
    hoverinfo = pd.Series(index=net.line.index, data=hoverinfo)
    line_traces = create_line_trace(net, use_line_geodata=use_line_geodata, respect_switches=True,
                                    width=line_width,
                                    infofunc=hoverinfo,
                                    cmap=cmap_lines,
                                    cmap_vals=net.res_line['loading_percent'].values,
                                    cmin=climits_load[0],
                                    cmax=climits_load[1],
                                    cbar_title='Line Loading [%]',
                                    cpos=cpos_load)

    # ----- Trafos ------
    # hoverinfo which contains name and pf results
    hoverinfo = (
            net.trafo.name.astype(str) + '<br />' +
            'I = ' + net.res_trafo.loading_percent.round(precision).astype(str) + ' %' + '<br />' +
            'I_hv = ' + net.res_trafo.i_hv_ka.round(precision).astype(str) + ' kA' + '<br />' +
            'I_lv = ' + net.res_trafo.i_lv_ka.round(precision).astype(str) + ' kA' + '<br />').tolist()
    hoverinfo = pd.Series(index=net.trafo.index, data=hoverinfo)
    trafo_traces = create_trafo_trace(net, width=line_width * 1.5, infofunc=hoverinfo,
                                      cmap=cmap_lines, cmin=0, cmax=100)

    # ----- Ext grid ------
    # get external grid from create_bus_trace
    marker_type = 'circle' if on_map else 'square'
    ext_grid_trace = create_bus_trace(net, buses=net.ext_grid.bus,
                                      color='grey', size=bus_size * 2, trace_name='external_grid',
                                      patch_type=marker_type)

    return draw_traces(line_traces + trafo_traces + ext_grid_trace + bus_trace,
                       showlegend=False, aspectratio=aspectratio, on_map=on_map,
                       map_style=map_style, figsize=figsize, filename=filename, auto_open=auto_open)
예제 #8
0
def pf_res_plotly(net,
                  cmap='Jet',
                  use_line_geodata=None,
                  on_map=False,
                  projection=None,
                  map_style='basic',
                  figsize=1,
                  aspectratio='auto',
                  line_width=2,
                  bus_size=10):
    """
    Plots a pandapower network in plotly
    using colormap for coloring lines according to line loading and buses according to voltage in p.u.
    If no geodata is available, artificial geodata is generated. For advanced plotting see the tutorial

    INPUT:
        **net** - The pandapower format network. If none is provided, mv_oberrhein() will be
        plotted as an example

    OPTIONAL:
        **respect_switches** (bool, False) - Respect switches when artificial geodata is created

        *cmap** (str, True) - name of the colormap

        *colors_dict** (dict, None) - by default 6 basic colors from default collor palette is used.
        Otherwise, user can define a dictionary in the form: voltage_kv : color

        **on_map** (bool, False) - enables using mapbox plot in plotly
        If provided geodata are not real geo-coordinates in lon/lat form, on_map will be set to False.

        **projection** (String, None) - defines a projection from which network geo-data will be transformed to
        lat-long. For each projection a string can be found at http://spatialreference.org/ref/epsg/

        **map_style** (str, 'basic') - enables using mapbox plot in plotly

            - 'streets'
            - 'bright'
            - 'light'
            - 'dark'
            - 'satellite'

        **figsize** (float, 1) - aspectratio is multiplied by it in order to get final image size

        **aspectratio** (tuple, 'auto') - when 'auto' it preserves original aspect ratio of the network geodata
        any custom aspectration can be given as a tuple, e.g. (1.2, 1)

        **line_width** (float, 1.0) - width of lines

        **bus_size** (float, 10.0) -  size of buses to plot.

    """

    if 'res_bus' not in net or net.get('res_bus').shape[0] == 0:
        logger.warning(
            'There are no Power Flow results. A Newton-Raphson power flow will be executed.'
        )
        runpp(net)

    # create geocoord if none are available
    if 'line_geodata' not in net:
        net.line_geodata = pd.DataFrame(columns=['coords'])
    if 'bus_geodata' not in net:
        net.bus_geodata = pd.DataFrame(columns=["x", "y"])
    if len(net.line_geodata) == 0 and len(net.bus_geodata) == 0:
        logger.warning(
            "No or insufficient geodata available --> Creating artificial coordinates."
            + " This may take some time")
        create_generic_coordinates(net, respect_switches=True)
        if on_map == True:
            logger.warning(
                "Map plots not available with artificial coordinates and will be disabled!"
            )
            on_map = False

    # check if geodata are real geographycal lat/lon coordinates using geopy
    if on_map and projection is not None:
        geo_data_to_latlong(net, projection=projection)

    # ----- Buses ------
    # initializating bus trace
    idx = net.line.index
    # hoverinfo which contains name and pf results
    hoverinfo = (net.bus['name'] + '<br>' + 'U = ' +
                 net.res_bus.loc[idx, 'vm_pu'].astype(str) + ' pu' + '<br>' +
                 'U = ' +
                 (net.res_bus.loc[idx, 'vm_pu'] * net.bus.vn_kv).astype(str) +
                 ' kV' + '<br>' + 'ang = ' +
                 net.res_bus.loc[idx, 'va_degree'].astype(str) +
                 ' deg').tolist()
    bus_trace = create_bus_trace(net,
                                 net.bus.index,
                                 size=bus_size,
                                 infofunc=hoverinfo,
                                 cmap=cmap,
                                 cbar_title='Bus Voltage [pu]',
                                 cmin=0.9,
                                 cmax=1.1)

    # ----- Lines ------
    # if bus geodata is available, but no line geodata
    # if bus geodata is available, but no line geodata
    cmap_lines = 'jet' if cmap is 'Jet' else cmap
    if use_line_geodata is None:
        use_line_geodata = False if len(net.line_geodata) == 0 else True
    elif use_line_geodata and len(net.line_geodata) == 0:
        logger.warning(
            "No or insufficient line geodata available --> only bus geodata will be used."
        )
        use_line_geodata = False
    idx = net.line.index
    # hoverinfo which contains name and pf results
    hoverinfo = (net.line['name'] + '<br>' + 'I = ' +
                 net.res_line.loc[idx, 'loading_percent'].astype(str) + ' %' +
                 '<br>' + 'I_from = ' +
                 net.res_line.loc[idx, 'i_from_ka'].astype(str) + ' kA' +
                 '<br>' + 'I_to = ' +
                 net.res_line.loc[idx, 'i_to_ka'].astype(str) + ' kA' +
                 '<br>').tolist()
    line_traces = create_line_trace(
        net,
        use_line_geodata=use_line_geodata,
        respect_switches=True,
        width=line_width,
        infofunc=hoverinfo,
        cmap=cmap_lines,
        cmap_vals=net.res_line.loc[:, 'loading_percent'].values,
        cmin=0,
        cmax=100,
        cbar_title='Line Loading [%]')
    line_center_trace = []
    if use_line_geodata == False:
        line_center_trace = create_edge_center_trace(line_traces,
                                                     infofunc=hoverinfo)

    # ----- Trafos ------
    idx = net.trafo.index
    # hoverinfo which contains name and pf results
    hoverinfo = (net.trafo['name'] + '<br>' + 'I = ' +
                 net.res_trafo.loc[idx, 'loading_percent'].astype(str) + ' %' +
                 '<br>' + 'I_hv = ' +
                 net.res_trafo.loc[idx, 'i_hv_ka'].astype(str) + ' kA' +
                 '<br>' + 'I_lv = ' +
                 net.res_trafo.loc[idx, 'i_lv_ka'].astype(str) + ' kA' +
                 '<br>').tolist()
    trafo_traces = create_trafo_trace(net,
                                      width=line_width * 1.5,
                                      infofunc=hoverinfo,
                                      cmap=cmap_lines,
                                      cmin=0,
                                      cmax=100)
    trafo_center_trace = []
    if use_line_geodata == False:
        trafo_center_trace = create_edge_center_trace(trafo_traces,
                                                      infofunc=hoverinfo)

    # ----- Ext grid ------
    # get external grid from create_bus_trace
    marker_type = 'circle' if on_map else 'square'
    ext_grid_trace = create_bus_trace(net,
                                      buses=net.ext_grid.bus,
                                      color='grey',
                                      size=bus_size * 2,
                                      trace_name='external_grid',
                                      patch_type=marker_type)

    draw_traces(line_traces + trafo_traces + ext_grid_trace + bus_trace +
                line_center_trace + trafo_center_trace,
                showlegend=False,
                aspectratio=aspectratio,
                on_map=on_map,
                map_style=map_style,
                figsize=figsize)