Exemplo n.º 1
0
def _run_bfsw_ppc(ppc, ppopt=None):
    """
    SPARSE version of distribution power flow solution according to [1]
    :References:
    [1] Jen-Hao Teng, "A Direct Approach for Distribution System Load Flow Solutions", IEEE Transactions on Power Delivery, vol. 18, no. 3, pp. 882-887, July 2003.

    :param ppc: matpower-style case data
    :return: results (pypower style), success (flag about PF convergence)
    """
    ppci = ppc

    ppopt = ppoption(ppopt)

    baseMVA, bus, gen, branch = \
        ppci["baseMVA"], ppci["bus"], ppci["gen"], ppci["branch"]
    nbus = bus.shape[0]

    # get bus index lists of each type of bus
    ref, pv, pq = bustypes(bus, gen)

    # depth-first-search bus ordering and generating Direct Load Flow matrix DLF = BCBV * BIBC
    DLF, ppc_bfsw, buses_ordered_bfsw = bibc_bcbv(ppci)


    baseMVA_bfsw, bus_bfsw, gen_bfsw, branch_bfsw = \
        ppc_bfsw["baseMVA"], ppc_bfsw["bus"], ppc_bfsw["gen"], ppc_bfsw["branch"]

    time_start = time() # starting pf calculation timing

    # initialize voltages to flat start and buses with gens to their setpoints
    V0 = np.ones(nbus, dtype=complex)
    V0[gen[:, GEN_BUS].astype(int)] = gen[:, VG]

    Sbus_bfsw = makeSbus(baseMVA_bfsw, bus_bfsw, gen_bfsw)

    # update data matrices with solution
    Ybus_bfsw, Yf_bfsw, Yt_bfsw = makeYbus(baseMVA_bfsw, bus_bfsw, branch_bfsw)
    ## get bus index lists of each type of bus
    ref_bfsw, pv_bfsw, pq_bfsw = bustypes(bus_bfsw, gen_bfsw)

    # #-----  run the power flow  -----
    V_final, success = bfsw(DLF, bus_bfsw, gen_bfsw, branch_bfsw, baseMVA_bfsw, Ybus_bfsw, Sbus_bfsw, V0,
                                   ref_bfsw, pv_bfsw, pq_bfsw, ppopt=ppopt)

    V_final = V_final[np.argsort(buses_ordered_bfsw)]  # return bus voltages in original bus order


    # #----- output results to ppc ------
    ppci["et"] = time() - time_start    # pf time end

    # generate results for original bus ordering
    Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)

    bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V_final, ref, pv, pq)

    ppci["success"] = success

    ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch

    return ppci, success
Exemplo n.º 2
0
def _run_ac_pf_without_qlims_enforced(ppci, recycle, makeYbus, ppopt):
    baseMVA, bus, gen, branch, ref, pv, pq, on, gbus, V0 = _get_pf_variables_from_ppci(
        ppci)

    ppci, Ybus, Yf, Yt = _get_Y_bus(ppci, recycle, makeYbus, baseMVA, bus,
                                    branch)

    ## compute complex bus power injections [generation - load]
    Sbus = makeSbus(baseMVA, bus, gen)

    ## run the power flow
    V, success = _call_power_flow_function(baseMVA, bus, branch, Ybus, Sbus,
                                           V0, ref, pv, pq, ppopt)

    ## update data matrices with solution
    bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref,
                              pv, pq)

    return ppci, success, bus, gen, branch
Exemplo n.º 3
0
def _run_ac_pf_without_qlims_enforced(ppci, options):
    numba, makeYbus = _import_numba_extensions_if_flag_is_true(
        options["numba"])

    baseMVA, bus, gen, branch, ref, pv, pq, on, gbus, V0 = _get_pf_variables_from_ppci(
        ppci)

    ppci, Ybus, Yf, Yt = _get_Y_bus(ppci, options, makeYbus, baseMVA, bus,
                                    branch)

    ## compute complex bus power injections [generation - load]
    Sbus = makeSbus(baseMVA, bus, gen)

    ## run the newton power  flow
    V, success, _ = newtonpf(Ybus, Sbus, V0, pv, pq, options, numba)

    ## update data matrices with solution
    bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref,
                              pv, pq)

    return ppci, success, bus, gen, branch
Exemplo n.º 4
0
def _run_fbsw_dense(ppc, ppopt=None):
    """
    DENSE version of distribution power flow solution according to [1]
    :References:
    [1] Jen-Hao Teng, "A Direct Approach for Distribution System Load Flow Solutions", IEEE Transactions on Power Delivery, vol. 18, no. 3, pp. 882-887, July 2003.

    :param ppc: matpower-style case data
    :return: results (pypower style), success (flag about PF convergence)
    """
    # time_start = time()

    # path_search = nx.shortest_path

    # ppci = ext2int(ppc)
    ppci = ppc

    ppopt = ppoption(ppopt)

    baseMVA, bus, gen, branch = \
        ppci["baseMVA"], ppci["bus"], ppci["gen"], ppci["branch"]
    nbus = bus.shape[0]

    # get bus index lists of each type of bus
    ref, pv, pq = bustypes(bus, gen)

    root_bus = ref[
        0]  # reference bus is assumed as root bus for a radial network

    DLF, ppc_fbsw, buses_ordered_fbsw = bibc_bcbv_dense(ppci)

    baseMVA_fbsw, bus_fbsw, gen_fbsw, branch_fbsw = \
        ppc_fbsw["baseMVA"], ppc_fbsw["bus"], ppc_fbsw["gen"], ppc_fbsw["branch"]

    time_start = time()

    # initialize voltages to flat start and buses with gens to their setpoints
    V0 = np.ones(nbus, dtype=complex)
    V0[gen[:, GEN_BUS].astype(int)] = gen[:, VG]

    Sbus_fbsw = makeSbus(baseMVA_fbsw, bus_fbsw, gen_fbsw)

    # update data matrices with solution
    Ybus_fbsw, Yf_fbsw, Yt_fbsw = makeYbus(baseMVA_fbsw, bus_fbsw, branch_fbsw)
    ## get bus index lists of each type of bus
    ref_fbsw, pv_fbsw, pq_fbsw = bustypes(bus_fbsw, gen_fbsw)

    ##-----  run the power flow  -----

    # ###
    # LF initialization and calculation
    V_final, success = fbsw_dense(DLF,
                                  bus_fbsw,
                                  gen_fbsw,
                                  branch_fbsw,
                                  baseMVA_fbsw,
                                  Ybus_fbsw,
                                  Sbus_fbsw,
                                  V0,
                                  ref_fbsw,
                                  pv_fbsw,
                                  pq_fbsw,
                                  ppopt=ppopt)
    V_final = V_final[np.argsort(
        buses_ordered_fbsw)]  # return bus voltages in original bus order

    ppci["et"] = time() - time_start

    Sbus = makeSbus(baseMVA, bus, gen)
    # update data matrices with solution
    Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)

    bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V_final,
                              ref, pv, pq)

    ppci["success"] = success

    ##-----  output results  -----
    ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch
    results = ppci

    return results, success
Exemplo n.º 5
0
def _run_bfswpf(ppc, options, **kwargs):
    """
    SPARSE version of distribution power flow solution according to [1]
    :References:
    [1] Jen-Hao Teng, "A Direct Approach for Distribution System Load Flow Solutions", IEEE Transactions on Power Delivery, vol. 18, no. 3, pp. 882-887, July 2003.

    :param ppc: matpower-style case data
    :return: results (pypower style), success (flag about PF convergence)
    """
    time_start = time()  # starting pf calculation timing

    tap_shift = ppc['branch'][:, SHIFT].real

    enforce_q_lims, tolerance_kva, max_iteration, calculate_voltage_angles, numba = _get_options(
        options)

    numba, makeYbus = _import_numba_extensions_if_flag_is_true(numba)

    ppci = ppc

    baseMVA, bus, gen, branch = \
        ppci["baseMVA"], ppci["bus"], ppci["gen"], ppci["branch"]
    nbus = bus.shape[0]
    # generate results for original bus ordering
    Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)

    # get bus index lists of each type of bus
    ref, pv, pq = bustypes(bus, gen)

    # creating networkx graph from list of branches
    G = nx.Graph()
    G.add_edges_from((int(fb), int(tb), {
        "shift": float(shift)
    }) for fb, tb, shift in list(
        zip(branch[:, F_BUS].real, branch[:, T_BUS].real, tap_shift)))
    if not nx.is_connected(G):
        Graphs = list(nx.connected_component_subgraphs(G))
    else:
        Graphs = [G]

    V_final = np.zeros(nbus, dtype=complex)
    V_tapshifts = np.zeros(nbus)
    for subi, G in enumerate(Graphs):

        ppci_sub = _cut_ppc(ppci, G.nodes())
        nbus_sub = len(G)

        # depth-first-search bus ordering and generating Direct Load Flow matrix DLF = BCBV * BIBC
        DLF, ppc_bfsw, buses_ordered_bfsw = _bibc_bcbv(ppci_sub, G)
        ppc_bfsw['branch'][:, SHIFT] = 0

        baseMVA_bfsw, bus_bfsw, gen_bfsw, branch_bfsw, ref_bfsw, pv_bfsw, pq_bfsw,\
        on, gbus, V0 = _get_pf_variables_from_ppci(ppc_bfsw)

        Sbus_bfsw = makeSbus(baseMVA_bfsw, bus_bfsw, gen_bfsw)

        Ybus_bfsw, Yf_bfsw, Yt_bfsw = makeYbus(baseMVA_bfsw, bus_bfsw,
                                               branch_bfsw)

        # #-----  run the power flow  -----
        V_res, success = _bfswpf(DLF, bus_bfsw, gen_bfsw, branch_bfsw, baseMVA,
                                 Ybus_bfsw, buses_ordered_bfsw, Sbus_bfsw, V0,
                                 ref_bfsw, pv_bfsw, pq_bfsw, enforce_q_lims,
                                 tolerance_kva, max_iteration, **kwargs)

        V_final[
            buses_ordered_bfsw] = V_res  # return bus voltages in original bus order
        # TODO: find the better way to consider transformer phase shift and remove this workaround
        if calculate_voltage_angles:
            predecessors = nx.bfs_predecessors(G, ref[subi])
            branches = list(zip(branch[:, F_BUS].real, branch[:, T_BUS].real))
            for bus_start in predecessors.iterkeys():
                bus_pred = bus_start
                bus_next = bus_start
                while predecessors.get(bus_next) is not None:
                    bus_next = predecessors.get(bus_pred)
                    shift_angle = G.get_edge_data(bus_pred, bus_next)['shift']
                    if (bus_pred, bus_next) in branches:
                        V_tapshifts[bus_start] += shift_angle
                    else:
                        V_tapshifts[bus_start] -= shift_angle
                    bus_pred = bus_next

            V_final *= np.exp(1j * np.pi / 180 * V_tapshifts)

    # #----- output results to ppc ------
    ppci["et"] = time() - time_start  # pf time end

    bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V_final,
                              ref, pv, pq)

    ppci["success"] = success

    ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch

    return ppci, success
Exemplo n.º 6
0
def _run_bfswpf(ppci, options, **kwargs):
    """
    SPARSE version of distribution power flow solution according to [1]
    :References:
    [1] Jen-Hao Teng, "A Direct Approach for Distribution System Load Flow Solutions",
    IEEE Transactions on Power Delivery, vol. 18, no. 3, pp. 882-887, July 2003.

    :param ppci: matpower-style case data
    :param options: pf options
    :return: results (pypower style), success (flag about PF convergence)
    """
    time_start = time()  # starting pf calculation timing

    baseMVA, bus, gen, branch, ref, pv, pq,\
    on, gbus, V0 = _get_pf_variables_from_ppci(ppci)

    enforce_q_lims, tolerance_kva, max_iteration, calculate_voltage_angles, numba = _get_options(
        options)

    numba, makeYbus = _import_numba_extensions_if_flag_is_true(numba)

    nobus = bus.shape[0]
    nobranch = branch.shape[0]

    # generate Sbus
    Sbus = makeSbus(baseMVA, bus, gen)
    # generate results for original bus ordering
    Ybus, Yf, Yt = makeYbus(baseMVA, bus, branch)

    # creating network graph from list of branches
    bus_from = branch[:, F_BUS].real.astype(int)
    bus_to = branch[:, T_BUS].real.astype(int)
    G = csr_matrix((np.ones(nobranch), (bus_from, bus_to)),
                   shape=(nobus, nobus))
    # create spanning trees using breadth-first-search
    # TODO add efficiency warning if a network is heavy-meshed
    G_trees = []
    for refbus in ref:
        G_trees.append(csgraph.breadth_first_tree(G, refbus, directed=False))

    # depth-first-search bus ordering and generating Direct Load Flow matrix DLF = BCBV * BIBC
    # TODO include recycling of the DLF matrix for repeated power flows with the same net topology
    DLF, buses_ordered_bfs_nets = _bibc_bcbv(bus, branch, G)

    # if there are trafos with phase-shift calculate Ybus without phase-shift for bfswpf
    any_trafo_shift = (branch[:, SHIFT] != 0).any()
    if any_trafo_shift:
        branch_noshift = branch.copy()
        branch_noshift[:, SHIFT] = 0
        Ybus_noshift, Yf_noshift, Yt_noshift = makeYbus(
            baseMVA, bus, branch_noshift)
    else:
        Ybus_noshift = Ybus.copy()

    # #-----  run the power flow  -----
    V_final, success = _bfswpf(DLF, bus, gen, branch, baseMVA, Ybus_noshift,
                               Sbus, V0, ref, pv, pq, buses_ordered_bfs_nets,
                               enforce_q_lims, tolerance_kva, max_iteration,
                               **kwargs)

    # if phase-shifting trafos are present adjust final state vector angles accordingly
    if calculate_voltage_angles and any_trafo_shift:
        brch_shift_mask = branch[:, SHIFT] != 0
        trafos_shift = dict(
            list(
                zip(
                    list(
                        zip(branch[brch_shift_mask, F_BUS].real.astype(int),
                            branch[brch_shift_mask, T_BUS].real.astype(int))),
                    branch[brch_shift_mask, SHIFT].real)))
        for trafo_ind, shift_degree in iteritems(trafos_shift):
            neti = 0
            # if multiple reference nodes, find in which network trafo is located
            if len(ref) > 0:
                for refbusi in range(len(ref)):
                    if trafo_ind[0] in buses_ordered_bfs_nets[refbusi]:
                        neti = refbusi
                        break
            G_tree = G_trees[neti]
            buses_ordered_bfs = buses_ordered_bfs_nets[neti]
            if (np.argwhere(buses_ordered_bfs == trafo_ind[0]) <
                    np.argwhere(buses_ordered_bfs == trafo_ind[1])):
                lv_bus = trafo_ind[1]
                shift_degree *= -1
            else:
                lv_bus = trafo_ind[0]

            buses_shifted_from_root = csgraph.breadth_first_order(
                G_tree, lv_bus, directed=True, return_predecessors=False)
            V_final[buses_shifted_from_root] *= np.exp(1j * np.pi / 180 *
                                                       shift_degree)

    # #----- output results to ppc ------
    ppci["et"] = time() - time_start  # pf time end

    bus, gen, branch = pfsoln(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V_final,
                              ref, pv, pq)

    ppci["success"] = success

    ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch

    return ppci, success