def test_get_simbench_net(sb_codes=None, n=8, scenarios=None, input_path=None):
    """ Test nets exctracted from csv (shortened) folder. 'shortened' and 'test' must be set
        properly in extract_simbench_grids_from_csv.py
        If sb_codes is None, randomn simbench codes are tested in the number of n.
        If in input_path is None, no input_path will be given to get_simbench_net()
    """
    shortened = input_path is not None and "shortened" in input_path
    scenarios = scenarios if scenarios is not None else [0, 1, 2]
    if not sb_codes:
        sb_codes = []
        for scenario in scenarios:
            sb_codes += sb.collect_all_simbench_codes(scenario=scenario,
                                                      shortened=shortened)
        first = 2  # always test the first 2 (complete_data and complete_grid)
        np.random.seed(int(time.time()))
        sb_codes = [
            sb_codes[i] for i in np.append(
                np.random.randint(first,
                                  len(sb_codes) - first, n), range(first))
        ]
    else:
        sb_codes = sb.ensure_iterability(sb_codes)

    for sb_code_info in sb_codes:
        sb_code, sb_code_params = sb.get_simbench_code_and_parameters(
            sb_code_info)
        logger.info("Get SimBench net '%s'" % sb_code)
        net = sb.get_simbench_net(sb_code, input_path=input_path)
        logger.info("Now test validity...")
        _test_net_validity(net,
                           sb_code_params,
                           shortened,
                           input_path=input_path)
Exemplo n.º 2
0
def _get_connected_buses_via_bus_bus_switch(net, buses):
    """ Returns a set of buses which are connected to 'buses' via bus-bus switches. """
    buses = set(ensure_iterability(buses))
    add_buses = [1]  # set anything to add_buses to start the while loop
    while(len(add_buses)):
        add_buses = pp.get_connected_buses(net, buses, consider=("s"))
        buses |= add_buses
    return buses
def test_ensure_iterability():
    assert len(sb.ensure_iterability(2))
    assert len(sb.ensure_iterability("df")) == 1
    assert len(sb.ensure_iterability(2, 4)) == 4
    assert len(sb.ensure_iterability("df", 5)) == 5
    a = [2, 3.1, "df"]
    assert sb.ensure_iterability(a) == a
    a = np.array(a)
    assert all(sb.ensure_iterability(a) == a)
    assert all(sb.ensure_iterability(a, 3) == a)
    try:
        sb.ensure_iterability(a, 5)
        bool_ = False
    except ValueError:
        bool_ = True
    assert bool_
Exemplo n.º 4
0
def _extract_csv_table_by_subnet(csv_table, tablename, relevant_subnets, bus_bus_switches={}):
    """ Extracts csv table by subnet names.

        INPUT:
            **csv_table** (DataFrame)

            **tablename** (str)

            **relevant_subnets** (tuple) - first item is hv_subnet (str), second lv_subnets (list of
                strings)

        OPTIONAL:
            **bus_bus_switches** (set, {}) - indices of bus-bus-switches in csv DataFrame.
                Only used if tablename == "Switch".
    """
    hv_subnets = ensure_iterability(relevant_subnets[0])
    lv_subnets = relevant_subnets[1]
    if "complete_data" in hv_subnets or \
       isinstance(csv_table, pd.DataFrame) and not csv_table.shape[0]:
        return csv_table  # no extraction needed
    csv_table = deepcopy(csv_table)

    if isinstance(csv_table, pd.DataFrame) and "subnet" in csv_table.columns:
        logger.debug("Start extracting %s" % tablename)
        subnet_split = csv_table.subnet.str.split("_", expand=True)

        # --- hv_elms: all elements starting with hv_subnet
        hv_elms = set(subnet_split.index[subnet_split[0].isin(hv_subnets)])
        if tablename in ["Node", "Coordinates", "Measurement", "Switch", "Substation"]:
            # including elements that subnet data is hv_subnet between 1st "_" and 2nd "_" or end
            hv_elms_to_add = set(subnet_split.index[subnet_split[1].isin(hv_subnets)])
            if tablename == "Switch":
                hv_elms_to_add = hv_elms_to_add & bus_bus_switches
            elif tablename == "Measurement":
                bus_measurements = set(csv_table.index[
                    pd.isnull(csv_table[["element1", "element2"]]).any(axis=1)])
                hv_elms_to_add = hv_elms_to_add & bus_measurements
            hv_elms |= hv_elms_to_add

        # --- lv_elms: all elements starting with lv_subnet
        lv_elms = set(subnet_split.index[subnet_split[0].isin(lv_subnets)])

        lv_hv_elms = set()
        hv_lv_elms = set()
        if 1 in subnet_split.columns:

            # --- lv_hv_elms
            if tablename in ["Node", "Coordinates", "Measurement", "Switch", "Substation"]:
                # all elements with a higher voltage level before 1st "_" than after the first "_"
                subnet_split_level = pd.DataFrame(None, index=subnet_split.index,
                                                  columns=subnet_split.columns)
                subnet_split.loc[[0, 1]] = subnet_split.loc[[0, 1]].replace(
                    {"EHV": 1, "HV": 3, "MV": 5, "LV": 5}
                )
                # for col in [0, 1]:
                #     for level_str, level_int in zip(["EHV", "HV", "MV", "LV"], [1, 3, 5, 7]):
                #         subnet_split_level.loc[
                #             subnet_split[col].fillna("").str.contains(level_str), col] = level_int
                lv_hv_elms = set(subnet_split_level.index[
                    subnet_split_level[0] > subnet_split_level[1]])
            else:
                # all elements with lv_subnet before 1st "_"
                # and is hv_subnet between 1st "_" and 2nd or end
                lv_hv_elms = set(subnet_split.index[
                    (subnet_split[0].isin(lv_subnets)) & (subnet_split[1].isin(hv_subnets))])

            # --- hv_lv_elms: all elements with hv_subnet before 1st "_"
            # and is lv_subnet between 1st "_" and 2nd or end
            if tablename not in ["Node", "Coordinates", "Switch", "Substation"]:
                hv_lv_elms = set(subnet_split.index[
                    (subnet_split[0].isin(hv_subnets)) & (subnet_split[1].isin(lv_subnets))])
            if tablename == "Measurement":
                hv_lv_elms -= bus_measurements

        # --- determine indices to drop and examine dropping
        drop_idx = (set(csv_table.index) - hv_elms - lv_elms) | hv_lv_elms | lv_hv_elms
        csv_table.drop(drop_idx, inplace=True)
        no_extraction = False
    else:
        no_extraction = "Profile" not in tablename and "Type" not in tablename and \
            tablename != "StudyCases"
        if no_extraction:
            logger.warning("From %s no extraction can be made by 'subnet'." % tablename)
    return csv_table
def _test_net_validity(net, sb_code_params, shortened, input_path=None):
    """ This function is to test validity of a simbench net. """

    # --- deduce values from sb_code_params to test extracted csv data
    # lv_net_extent: 0-no lv_net    1-one lv_net    2-all lv_nets
    lv_net_extent = int(bool(len(sb_code_params[2])))
    if bool(lv_net_extent) and sb_code_params[4] == "all":
        lv_net_extent += 1
    # net_factor: how many lower voltage grids are expected to be connected
    if shortened:
        net_factor = 8
    else:
        if sb_code_params[1] == "HV":
            net_factor = 10
        else:
            net_factor = 50

    # --- test data existence
    # buses
    expected_buses = {0: 12, 1: 80, 2: net_factor*12}[lv_net_extent] if sb_code_params[1] != "EHV" \
        else {0: 6, 1: 65, 2: 125}[lv_net_extent]
    assert net.bus.shape[0] > expected_buses

    # ext_grid
    assert bool(net.ext_grid.shape[0])

    # switches
    if sb_code_params[6]:
        if int(sb_code_params[5]) > 0:
            if net.switch.shape[0] <= net.line.shape[0] * 2 - 2:
                logger.info(
                    "There are %i switches, but %i " %
                    (net.switch.shape[0], net.line.shape[0]) +
                    "lines -> some lines are not surrounded by switches.")
        else:
            assert net.switch.shape[0] > net.line.shape[0] * 2 - 2
    else:
        assert not net.switch.closed.any()
        assert (net.switch.et != "b").all()

    # all buses supplied
    if sb_code_params[1] != "complete_data":
        unsup_buses = unsupplied_buses(net, respect_switches=False)
        if len(unsup_buses):
            logger.error("There are %i unsupplied buses." % len(unsup_buses))
            if len(unsup_buses) < 10:
                logger.error("These are: " +
                             str(net.bus.name.loc[unsup_buses]))
        assert not len(unsup_buses)

    # lines
    assert net.line.shape[0] >= net.bus.shape[0]-net.trafo.shape[0]-(net.switch.et == "b").sum() - \
        2*net.trafo3w.shape[0]-net.impedance.shape[0]-net.dcline.shape[0]-net.ext_grid.shape[0]

    # trafos
    if sb_code_params[1] == "EHV":
        expected_trafos = {0: 0, 1: 2, 2: 8}[lv_net_extent]
    elif sb_code_params[1] == "HV":
        expected_trafos = {0: 2, 1: 4, 2: net_factor * 2}[lv_net_extent]
    elif sb_code_params[1] == "MV":
        expected_trafos = {0: 2, 1: 3, 2: net_factor * 1}[lv_net_extent]
    elif sb_code_params[1] == "LV":
        expected_trafos = {0: 1}[lv_net_extent]
    elif sb_code_params[1] == "complete_data":
        expected_trafos = 200
    assert net.trafo.shape[0] >= expected_trafos

    # load
    expected_loads = {0: 10, 1: net_factor, 2: net_factor*10}[lv_net_extent] if \
        sb_code_params[1] != "EHV" else {0: 3, 1: 53, 2: 113}[lv_net_extent]
    assert net.load.shape[0] > expected_loads

    # sgen
    if sb_code_params[1] == "LV":
        expected_sgen = {0: 0}[lv_net_extent]
    elif sb_code_params[2] == "LV":
        expected_sgen = {1: 50, 2: 50 + net_factor * 1}[lv_net_extent]
    else:
        expected_sgen = expected_loads
    assert net.sgen.shape[0] > expected_sgen

    # measurement
    if pd.Series(["HV", "MV"]).isin([sb_code_params[1],
                                     sb_code_params[2]]).any():
        assert net.measurement.shape[0] > 1

    # bus_geodata
    assert net.bus.shape[0] == net.bus_geodata.shape[0]
    # check_that_all_buses_connected_by_switches_have_same_geodata
    for bus_group in bus_groups_connected_by_switches(net):
        first_bus = list(bus_group)[0]
        assert all(
            np.isclose(net.bus_geodata.x.loc[bus_group],
                       net.bus_geodata.x.loc[first_bus])
            & np.isclose(net.bus_geodata.y.loc[bus_group],
                         net.bus_geodata.y.loc[first_bus]))

    # --- test data content
    # substation
    for elm in ["bus", "trafo", "trafo3w", "switch"]:
        mentioned_substations = pd.Series(
            net[elm].substation.unique()).dropna()
        if not mentioned_substations.isin(net.substation.name.values).all():
            raise AssertionError(
                str(
                    list(mentioned_substations.
                         loc[~mentioned_substations.isin(net.substation.name.
                                                         values)].values)) +
                " from element '%s' misses in net.substation" % elm)

    # check subnet
    input_path = input_path if input_path is not None else sb.complete_data_path(
        sb_code_params[5])
    hv_subnet, lv_subnets = sb.get_relevant_subnets(sb_code_params,
                                                    input_path=input_path)
    allowed_elms_missing_subnet = [
        "gen", "dcline", "trafo3w", "impedance", "measurement", "shunt",
        "storage", "ward", "xward"
    ]
    if not sb_code_params[6]:
        allowed_elms_missing_subnet += ["switch"]

    if sb_code_params[1] != "complete_data":
        hv_subnets = sb.ensure_iterability(hv_subnet)
        for elm in pp.pp_elements():
            if "subnet" not in net[elm].columns or not bool(net[elm].shape[0]):
                assert elm in allowed_elms_missing_subnet
            else:  # subnet is in net[elm].columns and there are one or more elements
                subnet_split = net[elm].subnet.str.split("_", expand=True)
                subnet_ok = set()
                subnet_ok |= set(
                    subnet_split.index[subnet_split[0].isin(hv_subnets +
                                                            lv_subnets)])
                if elm in ["bus", "measurement", "switch"]:
                    if 1 in subnet_split.columns:
                        subnet_ok |= set(subnet_split.index[
                            subnet_split[1].isin(hv_subnets)])
                assert len(subnet_ok) == net[elm].shape[0]

    # check profile existing
    assert not sb.profiles_are_missing(net)

    # --- check profiles and loadflow
    check_loadflow = sb_code_params[1] != "complete_data"
    check_loadflow &= sb_code_params[2] != "HVMVLV"
    if check_loadflow:
        try:
            pp.runpp(net)
            converged = net.converged
        except:
            sb_code = sb.get_simbench_code_from_parameters(sb_code_params)
            logger.error("Loadflow not converged with %s" % sb_code)
            converged = False
        assert converged