e2nIEE / pandapower
1
# -*- coding: utf-8 -*-
2

3
# Copyright (c) 2016-2021 by University of Kassel and Fraunhofer Institute for Energy Economics
4
# and Energy System Technology (IEE), Kassel. All rights reserved.
5

6 1
from numpy import nan_to_num, array
7

8 1
from pandapower.auxiliary import ppException, _clean_up, _add_auxiliary_elements
9 1
from pandapower.build_branch import _calc_trafo_parameter, _calc_trafo3w_parameter
10 1
from pandapower.build_gen import _build_gen_ppc
11 1
from pandapower.pd2ppc import _pd2ppc, _calc_pq_elements_and_add_on_ppc, _ppc2ppci
12 1
from pandapower.pf.ppci_variables import _get_pf_variables_from_ppci
13 1
from pandapower.pf.run_bfswpf import _run_bfswpf
14 1
from pandapower.pf.run_dc_pf import _run_dc_pf
15 1
from pandapower.pf.run_newton_raphson_pf import _run_newton_raphson_pf
16 1
from pandapower.pf.runpf_pypower import _runpf_pypower
17 1
from pandapower.pypower.bustypes import bustypes
18 1
from pandapower.pypower.idx_bus import VM
19 1
from pandapower.pypower.makeYbus import makeYbus as makeYbus_pypower
20 1
from pandapower.pypower.pfsoln import pfsoln as pfsoln_pypower
21 1
from pandapower.results import _extract_results, _copy_results_ppci_to_ppc, init_results, verify_results, \
22
    _ppci_bus_to_ppc, _ppci_other_to_ppc
23

24

25 1
class AlgorithmUnknown(ppException):
26
    """
27
    Exception being raised in case optimal powerflow did not converge.
28
    """
29 1
    pass
30

31

32 1
class LoadflowNotConverged(ppException):
33
    """
34
    Exception being raised in case loadflow did not converge.
35
    """
36 1
    pass
37

38

39 1
def _powerflow(net, **kwargs):
40
    """
41
    Gets called by runpp or rundcpp with different arguments.
42
    """
43

44
    # get infos from options
45 1
    ac = net["_options"]["ac"]
46 1
    algorithm = net["_options"]["algorithm"]
47

48 1
    net["converged"] = False
49 1
    net["OPF_converged"] = False
50 1
    _add_auxiliary_elements(net)
51

52 1
    if not ac or net["_options"]["init_results"]:
53 1
        verify_results(net)
54
    else:
55 1
        init_results(net)
56

57
    # TODO remove this when zip loads are integrated for all PF algorithms
58 1
    if algorithm not in ['nr', 'bfsw']:
59 1
        net["_options"]["voltage_depend_loads"] = False
60

61
    # clear lookups
62 1
    net._pd2ppc_lookups = {"bus": array([], dtype=int), "ext_grid": array([], dtype=int),
63
                           "gen": array([], dtype=int), "branch": array([], dtype=int)}
64

65
    # convert pandapower net to ppc
66 1
    ppc, ppci = _pd2ppc(net)
67

68
    # store variables
69 1
    net["_ppc"] = ppc
70

71 1
    if not "VERBOSE" in kwargs:
72 1
        kwargs["VERBOSE"] = 0
73

74
    # ----- run the powerflow -----
75 1
    result = _run_pf_algorithm(ppci, net["_options"], **kwargs)
76
    # read the results (=ppci with results) to net
77 1
    _ppci_to_net(result, net)
78

79

80 1
def _recycled_powerflow(net, **kwargs):
81 1
    options = net["_options"]
82 1
    options["recycle"] = kwargs.get("recycle", None)
83 1
    options["init_vm_pu"] = "results"
84 1
    options["init_va_degree"] = "results"
85 1
    algorithm = options["algorithm"]
86 1
    ac = options["ac"]
87 1
    ppci = {"bus": net["_ppc"]["internal"]["bus"],
88
            "gen": net["_ppc"]["internal"]["gen"],
89
            "branch": net["_ppc"]["internal"]["branch"],
90
            "baseMVA": net["_ppc"]["internal"]["baseMVA"],
91
            "internal": net["_ppc"]["internal"],
92
            }
93 1
    if not ac:
94
        # DC recycle
95 0
        result = _run_dc_pf(ppci)
96 0
        _ppci_to_net(result, net)
97 0
        return
98 1
    if not algorithm in ['nr', 'iwamoto_nr'] and ac:
99 0
        raise ValueError("recycle is only available with Newton-Raphson power flow. Choose algorithm='nr'")
100

101 1
    recycle = options["recycle"]
102 1
    ppc = net["_ppc"]
103 1
    ppc["success"] = False
104 1
    ppc["iterations"] = 0.
105 1
    ppc["et"] = 0.
106

107 1
    if "bus_pq" in recycle and recycle["bus_pq"]:
108
        # update pq values in bus
109 1
        _calc_pq_elements_and_add_on_ppc(net, ppc)
110

111 1
    if "trafo" in recycle and recycle["trafo"]:
112
        # update trafo in branch and Ybus
113 1
        lookup = net._pd2ppc_lookups["branch"]
114 1
        if "trafo" in lookup:
115 1
            _calc_trafo_parameter(net, ppc)
116 1
        if "trafo3w" in lookup:
117 1
            _calc_trafo3w_parameter(net, ppc)
118

119 1
    if "gen" in recycle and recycle["gen"]:
120
        # updates the ppc["gen"] part
121 1
        _build_gen_ppc(net, ppc)
122 1
        ppc["gen"] = nan_to_num(ppc["gen"])
123

124 1
    ppci = _ppc2ppci(ppc, net, ppci=ppci)
125 1
    ppci["internal"] = net["_ppc"]["internal"]
126 1
    net["_ppc"] = ppc
127

128
    # run the Newton-Raphson power flow
129 1
    result = _run_newton_raphson_pf(ppci, options)
130 1
    ppc["success"] = ppci["success"]
131 1
    ppc["iterations"] = ppci["iterations"]
132 1
    ppc["et"] = ppci["et"]
133 1
    if options["only_v_results"]:
134 1
        _ppci_bus_to_ppc(result, ppc)
135 1
        _ppci_other_to_ppc(result, ppc, options["mode"])
136 1
        return
137
    # read the results from  result (==ppci) to net
138 1
    _ppci_to_net(result, net)
139

140

141 1
def _run_pf_algorithm(ppci, options, **kwargs):
142 1
    algorithm = options["algorithm"]
143 1
    ac = options["ac"]
144

145 1
    if ac:
146 1
        _, pv, pq = bustypes(ppci["bus"], ppci["gen"])
147
        # ----- run the powerflow -----
148 1
        if pq.shape[0] == 0 and pv.shape[0] == 0:
149 1
            result = _bypass_pf_and_set_results(ppci, options)
150 1
        elif algorithm == 'bfsw':  # forward/backward sweep power flow algorithm
151 1
            result = _run_bfswpf(ppci, options, **kwargs)[0]
152 1
        elif algorithm in ['nr', 'iwamoto_nr']:
153 1
            result = _run_newton_raphson_pf(ppci, options)
154 1
        elif algorithm in ['fdbx', 'fdxb', 'gs']:  # algorithms existing within pypower
155 1
            result = _runpf_pypower(ppci, options, **kwargs)[0]
156
        else:
157 0
            raise AlgorithmUnknown("Algorithm {0} is unknown!".format(algorithm))
158
    else:
159 1
        result = _run_dc_pf(ppci)
160

161 1
    return result
162

163

164 1
def _ppci_to_net(result, net):
165
    # reads the results from result (== ppci with results) to pandapower net
166

167 1
    mode = net["_options"]["mode"]
168
    # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly
169 1
    ppc = net["_ppc"]
170 1
    result = _copy_results_ppci_to_ppc(result, ppc, mode)
171

172
    # raise if PF was not successful. If DC -> success is always 1
173 1
    if result["success"] != 1:
174 1
        _clean_up(net, res=False)
175 1
        algorithm = net["_options"]["algorithm"]
176 1
        max_iteration = net["_options"]["max_iteration"]
177 1
        raise LoadflowNotConverged("Power Flow {0} did not converge after "
178
                                   "{1} iterations!".format(algorithm, max_iteration))
179
    else:
180 1
        net["_ppc"] = result
181 1
        net["converged"] = True
182

183 1
    _extract_results(net, result)
184 1
    _clean_up(net)
185

186

187 1
def _bypass_pf_and_set_results(ppci, options):
188 1
    Ybus, Yf, Yt = makeYbus_pypower(ppci["baseMVA"], ppci["bus"], ppci["branch"])
189 1
    baseMVA, bus, gen, branch, ref, _, pq, _, _, V0, ref_gens = _get_pf_variables_from_ppci(ppci)
190 1
    V = ppci["bus"][:, VM]
191 1
    bus, gen, branch = pfsoln_pypower(baseMVA, bus, gen, branch, Ybus, Yf, Yt, V, ref, ref_gens)
192 1
    ppci["bus"], ppci["gen"], ppci["branch"] = bus, gen, branch
193 1
    ppci["success"] = True
194 1
    ppci["iterations"] = 1
195 1
    ppci["et"] = 0
196 1
    return ppci

Read our documentation on viewing source code .

Loading