예제 #1
0
def replace_branch_switches(net, reserved_aux_node_names=None):
    """ Instead of directly connect branch elements (trafo and line) to nodes which connection is
        done by switches, this function creates an auxiliary node in between of the branch on the
        one hand and the switch and node on the other hand. """

    # --- determine indices
    idx_t_sw = net.switch.index[net.switch.et == "t"]
    idx_l_sw = net.switch.index[net.switch.et == "l"]
    n_branch_switches = len(idx_t_sw)+len(idx_l_sw)
    idx_bus = net.switch.bus[idx_t_sw | idx_l_sw]

    # --- create auxiliary nodes
    names, reserved_aux_node_names = append_str_by_underline_count(
        net.bus.name[idx_bus], reserved_strings=reserved_aux_node_names)
    if "subnet" in net.switch.columns:
        # if replace_branch_switches() is called by pp2csv_data(), "subnet" is available
        subnets = net.switch.subnet.loc[idx_t_sw | idx_l_sw].values
    else:
        # if replace_branch_switches() is called out of pp2csv_data(), this else statement is given
        subnets = net.bus.zone[idx_bus].values
    geodata = net.bus_geodata.loc[idx_bus, ["x", "y"]].values if net["bus_geodata"].shape[0] else \
        np.empty((len(idx_bus), 2))
    aux_buses = pp.create_buses(
        net, n_branch_switches, net.bus.vn_kv[idx_bus].values, name=names.values, type="auxiliary",
        geodata=geodata, zone=subnets)
    for col in ["min_vm_pu", "max_vm_pu", "substation", "voltLvl"]:
        if col in net.bus.columns:
            net.bus[col].loc[aux_buses] = net.bus[col][idx_bus].values
    if "subnet" in net.bus.columns:
        net.bus.subnet.loc[aux_buses] = subnets
    assert len(idx_bus) == len(aux_buses)

    # --- replace branch bus by new auxiliary node
    for idx_b_sw, branch, bus_types in zip([idx_t_sw, idx_l_sw], ["trafo", "line"],
                                           [["hv_bus", "lv_bus"], ["from_bus", "to_bus"]]):
        idx_elm = net.switch.element[idx_b_sw]
        is_first_bus_type = net[branch][bus_types[0]].loc[idx_elm].values == idx_bus.loc[
            idx_b_sw].values
        # is_first_bus_type == hv_bus resp. from_bus
        pos_in_aux_buses = idx_in_2nd_array(np.array(idx_b_sw[is_first_bus_type]),
                                               np.array(idx_t_sw | idx_l_sw))
        net[branch][bus_types[0]].loc[idx_elm[is_first_bus_type]] = aux_buses[pos_in_aux_buses]
        # ~is_first_bus_type == lv_bus resp. to_bus
        pos_in_aux_buses = idx_in_2nd_array(np.array(idx_b_sw[~is_first_bus_type]),
                                               np.array(idx_t_sw | idx_l_sw))
        net[branch][bus_types[1]].loc[idx_elm[~is_first_bus_type]] = aux_buses[pos_in_aux_buses]

    # --- replace switch element by new auxiliary nodes
    net.switch.element.loc[idx_t_sw | idx_l_sw] = aux_buses
    net.switch.et.loc[idx_t_sw | idx_l_sw] = "b"

    return reserved_aux_node_names
예제 #2
0
def _sort_switch_nodes_and_prepare_element_and_et(csv_data):
    """ 1) Swaps nodeA and nodeB data in switch table, if nodeA has auxiliary node names.
    As a result, no auxiliary node names are in nodeA column.
    2) Prepares "et" and "nodeB" (-> "element") columns for conversion to pp format. """
    # --- get indices/booleans
    idx_aux_node = csv_data["Node"].type == "auxiliary"
    aux_node_names = csv_data["Node"].id[idx_aux_node]
    nodeA_is_aux_node = csv_data["Switch"].nodeA.isin(aux_node_names)
    nodeB_is_aux_node = csv_data["Switch"].nodeB.isin(aux_node_names)
    both_are_aux_nodes = nodeA_is_aux_node & nodeB_is_aux_node
    if sum(both_are_aux_nodes):
        raise ValueError(
            "In switch table, nodeA and nodeB are auxiliary node names in the"
            + "indices: " + str(list(both_are_aux_nodes)))

    # --- swap nodeA data if there are auxiliary node names
    nodeA_data = deepcopy(csv_data["Switch"].nodeA[nodeA_is_aux_node])
    csv_data["Switch"].nodeA.loc[nodeA_is_aux_node] = csv_data["Switch"].nodeB[
        nodeA_is_aux_node]
    csv_data["Switch"].nodeB.loc[nodeA_is_aux_node] = nodeA_data

    # --- prepare 'element' and 'et' columns
    csv_data["Switch"]["et"] = "b"
    csv_data["Switch"]["nodeB"] = csv_data["Node"].index[idx_in_2nd_array(
        csv_data["Switch"]["nodeB"].values, csv_data["Node"]["id"].values)]
def _replace_buses_connected_to_busbars(net, buses):
    """ Replaces buses, which are no busbars, connected to a transformer and connected at least one
        busbar via bus-bus switch, by busbars to set transformer setpoints to the busbars. """
    no_busbar = ~net.bus.loc[buses].type.str.contains("busbar")
    non_busbars = buses[no_busbar.values]
    bb_sw = net.switch.loc[net.switch.et == "b"]

    new_buses = pd.Series()
    for X, Y in zip(["element", "bus"], ["bus", "element"]):
        X_in_nonb = bb_sw[X].isin(non_busbars)
        Y_is_busbar = net.bus.loc[bb_sw[Y]].type.str.contains("busbar").values
        idx_sw_to_set = bb_sw.index[X_in_nonb & Y_is_busbar]

        if len(idx_sw_to_set):
            idx_sw_in_nonb = idx_in_2nd_array(
                bb_sw[X].loc[idx_sw_to_set].values, non_busbars.values)

            trafos = non_busbars.index[idx_sw_in_nonb]
            new_buses = pd.concat([
                new_buses,
                pd.Series(bb_sw[Y].loc[idx_sw_to_set].values, index=trafos)
            ])

    new_buses = pd.concat([
        buses.loc[~pd.Series(buses.index).isin(new_buses.index).values],
        new_buses
    ])
    return new_buses
예제 #4
0
def _add_phys_type_and_vm_va_setpoints_to_element_tables(csv_data):
    """ Creates 'phys_type', 'vm_pu' and 'va_degree' column in 'ExternalNet', 'PowerPlant', 'RES'
        tables as well as 'vm_from_pu' and 'vm_to_pu' in 'Line' table for dclines and autoTapSetp
        for trafos. """
    # --- "ExternalNet", "PowerPlant", "RES"
    for gen_table in ["ExternalNet", "PowerPlant", "RES"]:
        csv_data[gen_table]["phys_type"] = gen_table
        idx_node = idx_in_2nd_array(csv_data[gen_table].node.values,
                                    csv_data["Node"].id.values)
        csv_data[gen_table]["vm_pu"] = csv_data["Node"].vmSetp[idx_node].values
        csv_data[gen_table]["va_degree"] = csv_data["Node"].vaSetp[
            idx_node].values

    # --- Line (for dclines)
    for bus_type, param in zip(["nodeA", "nodeB"], ['vm_from_pu', 'vm_to_pu']):
        idx_node = idx_in_2nd_array(csv_data["Line"][bus_type].values,
                                    csv_data["Node"].id.values)
        csv_data["Line"][param] = csv_data["Node"].vmSetp[idx_node].values
예제 #5
0
def _ensure_single_switch_at_aux_node_and_copy_vm_setp(csv_data,
                                                       new_type_name="node"):
    """
    This function set the Node type from 'auxiliary' to new_type_name for all nodes which are
    connected to multiple switches, because 'auxiliary' Nodes will be removed in
    create_branch_switches() while nodes with multiple switches are necessary for bus-bus switches.
    Furthermore, this function copies the vmSetp information from connected busbars to the nodes
    which got a new type name.
    """
    sw_nodes = pd.concat([csv_data["Switch"].nodeA, csv_data["Switch"].nodeB],
                         ignore_index=True)
    dupl_sw_node = sw_nodes[sw_nodes.duplicated()]
    dupl_node_ids = csv_data["Node"].id.isin(dupl_sw_node)
    aux_node_ids = csv_data["Node"].type == "auxiliary"
    idx_nodes_dupl_sw = csv_data["Node"].index[dupl_node_ids & aux_node_ids]

    # rename node type
    csv_data["Node"].type.loc[idx_nodes_dupl_sw] = new_type_name

    for X, Y in zip(["nodeA", "nodeB"], ["nodeB", "nodeA"]):
        # get indices to copy the setpoint
        node_names_dupl_sw = csv_data["Node"].id.loc[idx_nodes_dupl_sw]
        X_in_dupl = csv_data["Switch"][X].isin(node_names_dupl_sw)
        idx_Y = idx_in_2nd_array(csv_data["Switch"][Y].values,
                                 csv_data["Node"]["id"].values)
        Y_is_busbar = csv_data["Node"].loc[idx_Y].type.str.contains(
            "busbar").values
        idx_in_sw_to_set = csv_data["Switch"].index[X_in_dupl & Y_is_busbar]

        idx_X = idx_in_2nd_array(
            csv_data["Switch"][X].loc[idx_in_sw_to_set].values,
            csv_data["Node"]["id"].values)
        idx_Y = idx_Y[X_in_dupl & Y_is_busbar]

        # only use the first setpoint for nodes which are connected to multiple busbars
        idx_X_pd = pd.Series(idx_X)
        idx_node_dupl = idx_X_pd.duplicated()

        # set setpoint
        csv_data["Node"].vmSetp.loc[idx_X[idx_node_dupl]] = csv_data[
            "Node"].vmSetp.loc[idx_Y[idx_node_dupl]].values
예제 #6
0
def create_branch_switches(net):
    """ Changes bus-bus switches with auxiliary buses into bus-branch switches and drops all
        auxiliary buses. """
    # initialize DataFrame to store the indices of auxiliary buses ("aux_buses"), the switch indices
    # the auxiliary buses are connected to ("idx_switch"), the bus indices which are connected to
    # auxiliary buses via the switches("connected_buses"), the element type the auxiliary buses are
    # connected to ("et") and the element the auxiliary buses are connected to ("element")
    aux_bus_df = pd.DataFrame([], columns=["idx_switch", "aux_buses", "connected_buses", "et",
                                           "element"])

    # determine the bus indices of all auxiliary buses
    all_aux_buses = net.bus.index[net.bus.type == "auxiliary"]

    # determine the switch indices which are connected to auxiliary buses
    aux_bus_df["idx_switch"] = net.switch.index[net.switch.element.isin(all_aux_buses)]

    # determine the auxiliary bus indices of the switches
    aux_bus_df["aux_buses"] = net.switch.element.loc[aux_bus_df["idx_switch"]].values

    # determine the indices of the buses which are connected to auxiliary buses via switches
    aux_bus_df["connected_buses"] = net.switch.bus.loc[aux_bus_df["idx_switch"]].values

    # determine the element types and element indices which are connected to auxiliary buses
    for branch, bus_types in zip(["trafo", "line"], [["hv_bus", "lv_bus"], ["from_bus", "to_bus"]]):
        for bus_type in bus_types:
            current_branch_bus_type_buses = net[branch][bus_type].astype(int)
            aux_buses_are_cbbtb = aux_bus_df["aux_buses"].isin(current_branch_bus_type_buses)
            current_branch_bus_types_aux_buses = aux_bus_df["aux_buses"][aux_buses_are_cbbtb].values
            aux_bus_df["element"].loc[aux_buses_are_cbbtb] = current_branch_bus_type_buses.index[
                idx_in_2nd_array(current_branch_bus_types_aux_buses,
                                    current_branch_bus_type_buses.values)]  # requirement: only one
            # switch per aux bus
            aux_bus_df["et"].loc[aux_buses_are_cbbtb] = branch[0]

            # replace auxiliary buses in line and trafo tables
            net[branch][bus_type].loc[aux_bus_df["element"].loc[aux_buses_are_cbbtb]] = aux_bus_df[
                "connected_buses"].loc[aux_buses_are_cbbtb].values

    if pd.isnull(aux_bus_df).any().any():
        logger.error("Auxiliary bus replacement fails.")

    # replace auxiliary buses in switch table by branch elements
    for col in ["et", "element"]:
        net.switch[col].loc[aux_bus_df["idx_switch"]] = aux_bus_df[col].values

    # drop all auxiliary buses
    net.bus.drop(aux_bus_df["aux_buses"], inplace=True)
    idx_in_res_bus = aux_bus_df["aux_buses"][aux_bus_df["aux_buses"].isin(net.res_bus.index)]
    net.res_bus.drop(idx_in_res_bus, inplace=True)
    idx_in_bus_geodata = aux_bus_df["aux_buses"][aux_bus_df["aux_buses"].isin(
        net.bus_geodata.index)]
    net.bus_geodata.drop(idx_in_bus_geodata, inplace=True)
예제 #7
0
def _extend_coordinates_to_node_shape(csv_data):
    """ Extends the Coordinates table to the shape of Nodes to enable copying simply to bus_geodata.
    """
    bus_geodata = pd.DataFrame([],
                               index=csv_data["Node"].index,
                               columns=["x", "y"])
    with_coord = ~csv_data["Node"]["coordID"].isnull()
    idx_in_coordID = idx_in_2nd_array(
        csv_data["Node"]["coordID"].loc[with_coord].values,
        csv_data["Coordinates"]["id"].values)
    bus_geodata.loc[with_coord, ["x", "y"]] = csv_data["Coordinates"].loc[
        idx_in_coordID, ["x", "y"]].values
    csv_data["Coordinates"] = bus_geodata
예제 #8
0
def _set_vm_setpoint_to_trafos(net, csv_data):
    """ Adds 'autoTapSetp' to trafo and trafo3w tables. """
    for elm in ["trafo", "trafo3w"]:
        if "autoTap" in net[elm] and "autoTapSide" in net[elm]:
            autotap_trafos = net[elm].autoTap.fillna(False).astype(bool)
            assert all(autotap_trafos == net[elm].autoTapSide.fillna(False).astype(bool))
            if sum(autotap_trafos):
                bus_type = net[elm].autoTapSide.loc[autotap_trafos].str.lower() + "_bus"
                bus_type_col_idx = column_indices(net[elm], bus_type)
                buses = net[elm].values[autotap_trafos.index[autotap_trafos], bus_type_col_idx]
                bus_names = net.bus.name.loc[buses]
                idx_node = idx_in_2nd_array(bus_names.values, csv_data["Node*bus"].name.values)
                net[elm].loc[autotap_trafos, "autoTapSetp"] = csv_data["Node*bus"].vmSetp[
                    idx_node].values