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

7 1
try:
8 1
    import pplog as logging
9 1
except ImportError:
10 1
    import logging
11

12 1
logger = logging.getLogger(__name__)
13

14 1
import numpy as np
15 1
from scipy.sparse.linalg import factorized
16

17 1
from pandapower.auxiliary import _clean_up, _add_ppc_options, _add_sc_options, _add_auxiliary_elements
18 1
from pandapower.pd2ppc import _pd2ppc
19 1
from pandapower.pd2ppc_zero import _pd2ppc_zero
20 1
from pandapower.results import _copy_results_ppci_to_ppc
21 1
from pandapower.shortcircuit.currents import _calc_ikss, \
22
    _calc_ikss_1ph, _calc_ip, _calc_ith, _calc_branch_currents, \
23
    _calc_single_bus_sc, _calc_single_bus_sc_no_y_inv
24 1
from pandapower.shortcircuit.impedance import _calc_zbus, _calc_ybus, _calc_rx
25 1
from pandapower.shortcircuit.kappa import _add_kappa_to_ppc
26 1
from pandapower.shortcircuit.results import _extract_results, _extract_single_results
27 1
from pandapower.results import init_results
28

29

30 1
def calc_sc(net, fault="3ph", case='max', lv_tol_percent=10, topology="auto", ip=False,
31
            ith=False, tk_s=1., kappa_method="C", r_fault_ohm=0., x_fault_ohm=0.,
32
            branch_results=False, check_connectivity=True, return_all_currents=False,
33
            bus=None, inverse_y=True, suppress_warnings=False):
34
    """
35
    Calculates minimal or maximal symmetrical short-circuit currents.
36
    The calculation is based on the method of the equivalent voltage source
37
    according to DIN/IEC EN 60909.
38
    The initial short-circuit alternating current *ikss* is the basis of the short-circuit
39
    calculation and is therefore always calculated.
40
    Other short-circuit currents can be calculated from *ikss* with the conversion factors defined
41
    in DIN/IEC EN 60909.
42

43
    The output is stored in the net.res_bus_sc table as a short_circuit current
44
    for each bus.
45

46
    INPUT:
47
        **net** (pandapowerNet) pandapower Network
48

49
        ***fault** (str, 3ph) type of fault
50

51
            - "3ph" for three-phase
52

53
            - "2ph" for two-phase short-circuits
54

55
            - "1ph" for single-phase ground faults
56

57
        **case** (str, "max")
58

59
            - "max" for maximal current calculation
60

61
            - "min" for minimal current calculation
62

63
        **lv_tol_percent** (int, 10) voltage tolerance in low voltage grids
64

65
            - 6 for 6% voltage tolerance
66

67
            - 10 for 10% voltage olerance
68

69
        **ip** (bool, False) if True, calculate aperiodic short-circuit current
70

71
        **Ith** (bool, False) if True, calculate equivalent thermical short-circuit current Ith
72

73
        **topology** (str, "auto") define option for meshing (only relevant for ip and ith)
74

75
            - "meshed" - it is assumed all buses are supplied over multiple paths
76

77
            - "radial" - it is assumed all buses are supplied over exactly one path
78

79
            - "auto" - topology check for each bus is performed to see if it is supplied over multiple paths
80

81
        **tk_s** (float, 1) failure clearing time in seconds (only relevant for ith)
82

83
        **r_fault_ohm** (float, 0) fault resistance in Ohm
84

85
        **x_fault_ohm** (float, 0) fault reactance in Ohm
86

87
        **branch_results** (bool, False) defines if short-circuit results should also be generated for branches
88

89
        **return_all_currents** (bool, False) applies only if branch_results=True, if True short-circuit currents for
90
        each (branch, bus) tuple is returned otherwise only the max/min is returned
91

92
        **bus** (int, list, np.array, None) defines if short-circuit calculations should only be calculated for defined bus
93

94
        **inverse_y** (bool, True) defines if complete inverse should be used instead of LU factorization, factorization version is in experiment which should be faster and memory efficienter
95

96

97
    OUTPUT:
98

99
    EXAMPLE:
100
        calc_sc(net)
101

102
        print(net.res_bus_sc)
103
    """
104 1
    if fault not in ["3ph", "2ph", "1ph"]:
105 0
        raise NotImplementedError(
106
            "Only 3ph, 2ph and 1ph short-circuit currents implemented")
107

108 1
    if len(net.gen) and (ip or ith) and not suppress_warnings:
109 0
        logger.warning("aperiodic and thermal short-circuit currents are only implemented for "
110
                       "faults far from generators!")
111

112 1
    if case not in ['max', 'min']:
113 0
        raise ValueError('case can only be "min" or "max" for minimal or maximal short "\
114
                                "circuit current')
115 1
    if topology not in ["meshed", "radial", "auto"]:
116 0
        raise ValueError(
117
            'specify network structure as "meshed", "radial" or "auto"')
118

119 1
    if branch_results and not suppress_warnings:
120 1
        logger.warning("Branch results are in beta mode and might not always be reliable, "
121
                       "especially for transformers")
122

123
    # Convert bus to numpy array for better performance
124 1
    if isinstance(bus, int):
125 1
        bus = np.array([bus])
126 1
    elif isinstance(bus, list):
127 1
        bus = np.array(bus)
128

129 1
    kappa = ith or ip
130 1
    net["_options"] = {}
131 1
    _add_ppc_options(net, calculate_voltage_angles=False, trafo_model="pi",
132
                     check_connectivity=check_connectivity, mode="sc", switch_rx_ratio=2,
133
                     init_vm_pu="flat", init_va_degree="flat", enforce_q_lims=False,
134
                     recycle=None)
135 1
    _add_sc_options(net, fault=fault, case=case, lv_tol_percent=lv_tol_percent, tk_s=tk_s,
136
                    topology=topology, r_fault_ohm=r_fault_ohm, kappa_method=kappa_method,
137
                    x_fault_ohm=x_fault_ohm, kappa=kappa, ip=ip, ith=ith,
138
                    branch_results=branch_results, return_all_currents=return_all_currents,
139
                    inverse_y=inverse_y)
140 1
    init_results(net, "sc")
141 1
    if fault in ("2ph", "3ph"):
142 1
        _calc_sc(net, bus)
143 1
    elif fault == "1ph":
144 1
        _calc_sc_1ph(net, bus)
145
    else:
146 0
        raise ValueError("Invalid fault %s" % fault)
147

148

149 1
def calc_single_sc(net, bus, fault="3ph", case='max', lv_tol_percent=10,
150
                   check_connectivity=True, inverse_y=True):
151
    """
152
    Calculates minimal or maximal symmetrical short-circuit currents.
153
    The calculation is based on the method of the equivalent voltage source
154
    according to DIN/IEC EN 60909.
155
    The initial short-circuit alternating current *ikss* is the basis of the short-circuit
156
    calculation and is therefore always calculated.
157
    Other short-circuit currents can be calculated from *ikss* with the conversion factors defined
158
    in DIN/IEC EN 60909.
159

160
    The output is stored in the net.res_bus_sc table as a short_circuit current
161
    for each bus.
162

163
    INPUT:
164
        **net** (pandapowerNet) pandapower Network
165

166
        ***fault** (str, 3ph) type of fault
167

168
            - "3ph" for three-phase
169

170
            - "2ph" for two-phase short-circuits
171

172
        **case** (str, "max")
173

174
            - "max" for maximal current calculation
175

176
            - "min" for minimal current calculation
177

178
        **lv_tol_percent** (int, 10) voltage tolerance in low voltage grids
179

180
            - 6 for 6% voltage tolerance
181

182
            - 10 for 10% voltage olerance
183

184
        **r_fault_ohm** (float, 0) fault resistance in Ohm
185

186
        **x_fault_ohm** (float, 0) fault reactance in Ohm
187

188
    OUTPUT:
189

190
    EXAMPLE:
191
        calc_sc(net)
192

193
        print(net.res_bus_sc)
194
    """
195 1
    if fault not in ["3ph", "2ph"]:
196 0
        raise NotImplementedError("Only 3ph and 2ph short-circuit currents implemented")
197

198 1
    if case not in ['max', 'min']:
199 0
        raise ValueError('case can only be "min" or "max" for minimal or maximal short "\
200
                                "circuit current')
201 1
    net["_options"] = {}
202 1
    _add_ppc_options(net, calculate_voltage_angles=False, trafo_model="pi",
203
                     check_connectivity=check_connectivity, mode="sc", switch_rx_ratio=2,
204
                     init_vm_pu="flat", init_va_degree="flat", enforce_q_lims=False,
205
                     recycle=None)
206 1
    _add_sc_options(net, fault=fault, case=case, lv_tol_percent=lv_tol_percent, tk_s=1.,
207
                    topology="auto", r_fault_ohm=0., kappa_method="C",
208
                    x_fault_ohm=0., kappa=False, ip=False, ith=False,
209
                    branch_results=True, return_all_currents=False,
210
                    inverse_y=inverse_y)
211 1
    init_results(net, "sc")
212 1
    if fault in ("2ph", "3ph"):
213 1
        _calc_sc_single(net, bus)
214 0
    elif fault == "1ph":
215 0
        raise NotImplementedError("1ph short-circuits are not yet implemented")
216
    else:
217 0
        raise ValueError("Invalid fault %s" % fault)
218

219

220 1
def _calc_sc_single(net, bus):
221 1
    _add_auxiliary_elements(net)
222 1
    ppc, ppci = _pd2ppc(net)
223 1
    _calc_ybus(ppci)
224

225 1
    if net["_options"]["inverse_y"]:
226 1
        _calc_zbus(net, ppci)
227 1
        _calc_rx(net, ppci, bus=None)
228 1
        _calc_ikss(net, ppci, bus=None)
229 1
        _calc_single_bus_sc(net, ppci, bus)
230
    else:
231
        # Factorization Ybus once
232 1
        ppci["internal"]["ybus_fact"] = factorized(ppci["internal"]["Ybus"])
233

234 1
        _calc_rx(net, ppci, bus)
235 1
        _calc_ikss(net, ppci, bus)
236 1
        _calc_single_bus_sc_no_y_inv(net, ppci, bus)
237

238
        # Delete factorization object
239 1
        ppci["internal"].pop("ybus_fact")
240

241 1
    ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc")
242 1
    _extract_single_results(net, ppc)
243 1
    _clean_up(net)
244

245

246 1
def _calc_sc(net, bus):
247 1
    _add_auxiliary_elements(net)
248 1
    ppc, ppci = _pd2ppc(net)
249 1
    _calc_ybus(ppci)
250

251 1
    if net["_options"]["inverse_y"]:
252 1
        _calc_zbus(net, ppci)
253
    else:
254
        # Factorization Ybus once
255 1
        ppci["internal"]["ybus_fact"] = factorized(ppci["internal"]["Ybus"])
256

257 1
    _calc_rx(net, ppci, bus)
258

259
    # kappa required inverse of Zbus, which is optimized
260 1
    if net["_options"]["kappa"]:
261 1
        _add_kappa_to_ppc(net, ppci)
262 1
    _calc_ikss(net, ppci, bus)
263

264 1
    if net["_options"]["ip"]:
265 1
        _calc_ip(net, ppci)
266 1
    if net["_options"]["ith"]:
267 1
        _calc_ith(net, ppci)
268

269 1
    if net._options["branch_results"]:
270 1
        _calc_branch_currents(net, ppci, bus)
271

272 1
    ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc")
273 1
    _extract_results(net, ppc, ppc_0=None, bus=bus)
274 1
    _clean_up(net)
275

276 1
    if "ybus_fact" in ppci["internal"]:
277
        # Delete factorization object
278 1
        ppci["internal"].pop("ybus_fact")
279

280

281 1
def _calc_sc_1ph(net, bus):
282
    """
283
    calculation method for single phase to ground short-circuit currents
284
    """
285 1
    _add_auxiliary_elements(net)
286
    # pos. seq bus impedance
287 1
    ppc, ppci = _pd2ppc(net)
288 1
    _calc_ybus(ppci)
289

290
    # zero seq bus impedance
291 1
    ppc_0, ppci_0 = _pd2ppc_zero(net)
292 1
    _calc_ybus(ppci_0)
293

294 1
    if net["_options"]["inverse_y"]:
295 1
        _calc_zbus(net, ppci)
296 1
        _calc_zbus(net, ppci_0)
297
    else:
298
        # Factorization Ybus once
299 1
        ppci["internal"]["ybus_fact"] = factorized(ppci["internal"]["Ybus"])
300 1
        ppci_0["internal"]["ybus_fact"] = factorized(ppci_0["internal"]["Ybus"])
301

302 1
    _calc_rx(net, ppci, bus=bus)
303 1
    _add_kappa_to_ppc(net, ppci)
304

305 1
    _calc_rx(net, ppci_0, bus=bus)
306 1
    _calc_ikss_1ph(net, ppci, ppci_0, bus=bus)
307

308 1
    if net._options["branch_results"]:
309 1
        _calc_branch_currents(net, ppci, bus=bus)
310 1
    ppc_0 = _copy_results_ppci_to_ppc(ppci_0, ppc_0, "sc")
311 1
    ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc")
312 1
    _extract_results(net, ppc, ppc_0, bus=bus)
313 1
    _clean_up(net)

Read our documentation on viewing source code .

Loading