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
import inspect
8

9 1
from pandapower.auxiliary import _check_bus_index_and_print_warning_if_high, \
10
    _check_gen_index_and_print_warning_if_high, _init_runpp_options, _init_rundcopp_options, \
11
    _init_rundcpp_options, _init_runopp_options, _internal_stored
12 1
from pandapower.opf.validate_opf_input import _check_necessary_opf_parameters
13 1
from pandapower.optimal_powerflow import _optimal_powerflow
14 1
from pandapower.powerflow import _powerflow, _recycled_powerflow
15

16 1
try:
17 1
    import pplog as logging
18 1
except ImportError:
19 1
    import logging
20

21 1
logger = logging.getLogger(__name__)
22

23

24 1
def set_user_pf_options(net, overwrite=False, **kwargs):
25
    """
26
    This function sets the 'user_pf_options' dict for net. These options overrule
27
    net.__internal_options once they are added to net. These options are used in configuration of
28
    load flow calculation.
29
    At the same time, user-defined arguments for pandapower.runpp() always have a higher priority.
30
    To remove user_pf_options, set overwrite=True and provide no additional arguments
31

32
    :param net: pandaPower network
33
    :param overwrite: specifies whether the user_pf_options is removed before setting new options
34
    :param kwargs: load flow options, e. g. tolerance_mva = 1e-3
35
    :return: None
36
    """
37 1
    standard_parameters = ['calculate_voltage_angles', 'trafo_model', 'check_connectivity', 'mode',
38
                           'copy_constraints_to_ppc', 'switch_rx_ratio', 'enforce_q_lims',
39
                           'recycle', 'voltage_depend_loads', 'consider_line_temperature', 'delta',
40
                           'trafo3w_losses', 'init_vm_pu', 'init_va_degree', 'init_results',
41
                           'tolerance_mva', 'trafo_loading', 'numba', 'ac', 'algorithm',
42
                           'max_iteration', 'v_debug', 'run_control']
43

44 1
    if overwrite or 'user_pf_options' not in net.keys():
45 1
        net['user_pf_options'] = dict()
46

47 1
    net.user_pf_options.update({key: val for key, val in kwargs.items()
48
                                if key in standard_parameters})
49

50 1
    additional_kwargs = {key: val for key, val in kwargs.items()
51
                         if key not in standard_parameters}
52

53
    # this part is to inform user and to make typos in parameters visible
54 1
    if len(additional_kwargs) > 0:
55 1
        logger.info('parameters %s are not in the list of standard options' % list(
56
            additional_kwargs.keys()))
57

58 1
        net.user_pf_options.update(additional_kwargs)
59

60

61 1
def runpp(net, algorithm='nr', calculate_voltage_angles="auto", init="auto",
62
          max_iteration="auto", tolerance_mva=1e-8, trafo_model="t",
63
          trafo_loading="current", enforce_q_lims=False, check_connectivity=True,
64
          voltage_depend_loads=True, consider_line_temperature=False,
65
          run_control=False, **kwargs):
66
    """
67
    Runs a power flow
68

69
    INPUT:
70
        **net** - The pandapower format network
71

72
    OPTIONAL:
73
        **algorithm** (str, "nr") - algorithm that is used to solve the power flow problem.
74

75
            The following algorithms are available:
76

77
                - "nr" Newton-Raphson (pypower implementation with numba accelerations)
78
                - "iwamoto_nr" Newton-Raphson with Iwamoto multiplier (maybe slower than NR but more robust)
79
                - "bfsw" backward/forward sweep (specially suited for radial and weakly-meshed networks)
80
                - "gs" gauss-seidel (pypower implementation)
81
                - "fdbx" fast-decoupled (pypower implementation)
82
                - "fdxb" fast-decoupled (pypower implementation)
83

84
        **calculate_voltage_angles** (str or bool, "auto") - consider voltage angles in loadflow calculation
85

86
            If True, voltage angles of ext_grids and transformer shifts are considered in the
87
            loadflow calculation. Considering the voltage angles is only necessary in meshed
88
            networks that are usually found in higher voltage levels. calculate_voltage_angles
89
            in "auto" mode defaults to:
90

91
                - True, if the network voltage level is above 70 kV
92
                - False otherwise
93

94
            The network voltage level is defined as the maximum rated voltage of any bus in the network that
95
            is connected to a line.
96

97
        **init** (str, "auto") - initialization method of the loadflow
98
        pandapower supports four methods for initializing the loadflow:
99

100
            - "auto" - init defaults to "dc" if calculate_voltage_angles is True or "flat" otherwise
101
            - "flat"- flat start with voltage of 1.0pu and angle of 0° at all PQ-buses and 0° for PV buses as initial solution, the slack bus is initialized with the values provided in net["ext_grid"]
102
            - "dc" - initial DC loadflow before the AC loadflow. The results of the DC loadflow are used as initial solution for the AC loadflow. Note that the DC loadflow only calculates voltage angles at PQ and PV buses, voltage magnitudes are still flat started.
103
            - "results" - voltage vector of last loadflow from net.res_bus is used as initial solution. This can be useful to accelerate convergence in iterative loadflows like time series calculations.
104

105
        Considering the voltage angles might lead to non-convergence of the power flow in flat start.
106
        That is why in "auto" mode, init defaults to "dc" if calculate_voltage_angles is True or "flat" otherwise
107

108
        **max_iteration** (int, "auto") - maximum number of iterations carried out in the power flow algorithm.
109

110
            In "auto" mode, the default value depends on the power flow solver:
111

112
                - 10 for "nr"
113
                - 100 for "bfsw"
114
                - 1000 for "gs"
115
                - 30 for "fdbx"
116
                - 30 for "fdxb"
117

118
        **tolerance_mva** (float, 1e-8) - loadflow termination condition referring to P / Q mismatch of node power in MVA
119

120
        **trafo_model** (str, "t")  - transformer equivalent circuit model
121
        pandapower provides two equivalent circuit models for the transformer:
122

123
            - "t" - transformer is modeled as equivalent with the T-model.
124
            - "pi" - transformer is modeled as equivalent PI-model. This is not recommended, since it is less exact than the T-model. It is only recommended for valdiation with other software that uses the pi-model.
125

126
        **trafo_loading** (str, "current") - mode of calculation for transformer loading
127

128
            Transformer loading can be calculated relative to the rated current or the rated power. In both cases the overall transformer loading is defined as the maximum loading on the two sides of the transformer.
129

130
            - "current"- transformer loading is given as ratio of current flow and rated current of the transformer. This is the recommended setting, since thermal as well as magnetic effects in the transformer depend on the current.
131
            - "power" - transformer loading is given as ratio of apparent power flow to the rated apparent power of the transformer.
132

133
        **enforce_q_lims** (bool, False) - respect generator reactive power limits
134

135
            If True, the reactive power limits in net.gen.max_q_mvar/min_q_mvar are respected in the
136
            loadflow. This is done by running a second loadflow if reactive power limits are
137
            violated at any generator, so that the runtime for the loadflow will increase if reactive
138
            power has to be curtailed.
139

140
            Note: enforce_q_lims only works if algorithm="nr"!
141

142

143
        **check_connectivity** (bool, True) - Perform an extra connectivity test after the conversion from pandapower to PYPOWER
144

145
            If True, an extra connectivity test based on SciPy Compressed Sparse Graph Routines is perfomed.
146
            If check finds unsupplied buses, they are set out of service in the ppc
147

148
        **voltage_depend_loads** (bool, True) - consideration of voltage-dependent loads. If False, net.load.const_z_percent and net.load.const_i_percent are not considered, i.e. net.load.p_mw and net.load.q_mvar are considered as constant-power loads.
149

150
        **consider_line_temperature** (bool, False) - adjustment of line impedance based on provided
151
            line temperature. If True, net.line must contain a column "temperature_degree_celsius".
152
            The temperature dependency coefficient alpha must be provided in the net.line.alpha
153
            column, otherwise the default value of 0.004 is used
154

155

156
        **KWARGS:
157

158
        **numba** (bool, True) - Activation of numba JIT compiler in the newton solver
159

160
            If set to True, the numba JIT compiler is used to generate matrices for the powerflow,
161
            which leads to significant speed improvements.
162

163
        **switch_rx_ratio** (float, 2) - rx_ratio of bus-bus-switches. If impedance is zero, buses connected by a closed bus-bus switch are fused to model an ideal bus. Otherwise, they are modelled as branches with resistance defined as z_ohm column in switch table and this parameter
164

165
        **delta_q** - Reactive power tolerance for option "enforce_q_lims" in kvar - helps convergence in some cases.
166

167
        **trafo3w_losses** - defines where open loop losses of three-winding transformers are considered. Valid options are "hv", "mv", "lv" for HV/MV/LV side or "star" for the star point.
168

169
        **v_debug** (bool, False) - if True, voltage values in each newton-raphson iteration are logged in the ppc
170

171
        **init_vm_pu** (string/float/array/Series, None) - Allows to define initialization specifically for voltage magnitudes. Only works with init == "auto"!
172

173
            - "auto": all buses are initialized with the mean value of all voltage controlled elements in the grid
174
            - "flat" for flat start from 1.0
175
            - "results": voltage magnitude vector is taken from result table
176
            - a float with which all voltage magnitudes are initialized
177
            - an iterable with a voltage magnitude value for each bus (length and order has to match with the buses in net.bus)
178
            - a pandas Series with a voltage magnitude value for each bus (indexes have to match the indexes in net.bus)
179

180
        **init_va_degree** (string/float/array/Series, None) - Allows to define initialization specifically for voltage angles. Only works with init == "auto"!
181

182
            - "auto": voltage angles are initialized from DC power flow if angles are calculated or as 0 otherwise
183
            - "dc": voltage angles are initialized from DC power flow
184
            - "flat" for flat start from 0
185
            - "results": voltage angle vector is taken from result table
186
            - a float with which all voltage angles are initialized
187
            - an iterable with a voltage angle value for each bus (length and order has to match with the buses in net.bus)
188
            - a pandas Series with a voltage angle value for each bus (indexes have to match the indexes in net.bus)
189

190
        **recycle** (dict, none) - Reuse of internal powerflow variables for time series calculation
191

192
            Contains a dict with the following parameters:
193
            bus_pq: If True PQ values of buses are updated
194
            trafo: If True trafo relevant variables, e.g., the Ybus matrix, is recalculated
195
            gen: If True Sbus and the gen table in the ppc are recalculated
196

197
        **neglect_open_switch_branches** (bool, False) - If True no auxiliary buses are created for branches when switches are opened at the branch. Instead branches are set out of service
198

199
    """
200

201
    # if dict 'user_pf_options' is present in net, these options overrule the net.__internal_options
202
    # except for parameters that are passed by user
203 1
    recycle = kwargs.get("recycle", None)
204 1
    if isinstance(recycle, dict) and _internal_stored(net):
205 1
        _recycled_powerflow(net, **kwargs)
206 1
        return
207

208 1
    if run_control and net.controller.in_service.any():
209 1
        from pandapower.control import run_control
210 1
        parameters = {**locals(), **kwargs}
211
        # disable run control for inner loop to avoid infinite loop
212 1
        parameters["run_control"] = False
213 1
        run_control(**parameters)
214
    else:
215 1
        passed_parameters = _passed_runpp_parameters(locals())
216 1
        _init_runpp_options(net, algorithm=algorithm, calculate_voltage_angles=calculate_voltage_angles,
217
                            init=init, max_iteration=max_iteration, tolerance_mva=tolerance_mva,
218
                            trafo_model=trafo_model, trafo_loading=trafo_loading,
219
                            enforce_q_lims=enforce_q_lims, check_connectivity=check_connectivity,
220
                            voltage_depend_loads=voltage_depend_loads,
221
                            consider_line_temperature=consider_line_temperature,
222
                            passed_parameters=passed_parameters, **kwargs)
223 1
        _check_bus_index_and_print_warning_if_high(net)
224 1
        _check_gen_index_and_print_warning_if_high(net)
225 1
        _powerflow(net, **kwargs)
226

227

228 1
def rundcpp(net, trafo_model="t", trafo_loading="current", recycle=None, check_connectivity=True,
229
            switch_rx_ratio=2, trafo3w_losses="hv", **kwargs):
230
    """
231
    Runs PANDAPOWER DC Flow
232

233
    INPUT:
234
        **net** - The pandapower format network
235

236
    OPTIONAL:
237
        **trafo_model** (str, "t")  - transformer equivalent circuit model
238
        pandapower provides two equivalent circuit models for the transformer:
239

240
            - "t" - transformer is modeled as equivalent with the T-model. This is consistent with PowerFactory and is also more accurate than the PI-model. We recommend using this transformer model.
241
            - "pi" - transformer is modeled as equivalent PI-model. This is consistent with Sincal, but the method is questionable since the transformer is physically T-shaped. We therefore recommend the use of the T-model.
242

243
        **trafo_loading** (str, "current") - mode of calculation for transformer loading
244

245
            Transformer loading can be calculated relative to the rated current or the rated power. In both cases the overall transformer loading is defined as the maximum loading on the two sides of the transformer.
246

247
            - "current"- transformer loading is given as ratio of current flow and rated current of the transformer. This is the recommended setting, since thermal as well as magnetic effects in the transformer depend on the current.
248
            - "power" - transformer loading is given as ratio of apparent power flow to the rated apparent power of the transformer.
249

250
        **check_connectivity** (bool, False) - Perform an extra connectivity test after the conversion from pandapower to PYPOWER
251

252
            If true, an extra connectivity test based on SciPy Compressed Sparse Graph Routines is perfomed.
253
            If check finds unsupplied buses, they are put out of service in the PYPOWER matrix
254

255
        **switch_rx_ratio** (float, 2) - rx_ratio of bus-bus-switches. If impedance is zero, buses connected by a closed bus-bus switch are fused to model an ideal bus. Otherwise, they are modelled as branches with resistance defined as z_ohm column in switch table and this parameter
256

257
        **trafo3w_losses** (str, "hv") - defines where open loop losses of three-winding transformers are considered. Valid options are "hv", "mv", "lv" for HV/MV/LV side or "star" for the star point.
258

259
        ****kwargs** - options to use for PYPOWER.runpf
260
    """
261 1
    _init_rundcpp_options(net, trafo_model=trafo_model, trafo_loading=trafo_loading,
262
                          recycle=recycle, check_connectivity=check_connectivity,
263
                          switch_rx_ratio=switch_rx_ratio, trafo3w_losses=trafo3w_losses, **kwargs)
264

265 1
    _check_bus_index_and_print_warning_if_high(net)
266 1
    _check_gen_index_and_print_warning_if_high(net)
267 1
    _powerflow(net, **kwargs)
268

269

270 1
def runopp(net, verbose=False, calculate_voltage_angles=True, check_connectivity=True,
271
           suppress_warnings=True, switch_rx_ratio=2, delta=1e-10, init="flat", numba=True,
272
           trafo3w_losses="hv", consider_line_temperature=False, **kwargs):
273
    """
274
    Runs the  pandapower Optimal Power Flow.
275
    Flexibilities, constraints and cost parameters are defined in the pandapower element tables.
276

277
    Flexibilities can be defined in net.sgen / net.gen /net.load / net.storage /net.ext_grid
278
    net.sgen.controllable if a static generator is controllable. If False,
279
    the active and reactive power are assigned as in a normal power flow. If True, the following
280
    flexibilities apply:
281
        - net.gen.min_p_mw / net.gen.max_p_mw
282
        - net.gen.min_q_mvar / net.gen.max_q_mvar
283
        - net.sgen.min_p_mw / net.sgen.max_p_mw
284
        - net.sgen.min_q_mvar / net.sgen.max_q_mvar
285
        - net.dcline.max_p_mw
286
        - net.dcline.min_q_to_mvar / net.dcline.max_q_to_mvar / net.dcline.min_q_from_mvar / net.dcline.max_q_from_mvar
287
        - net.ext_grid.min_p_mw / net.ext_grid.max_p_mw
288
        - net.ext_grid.min_q_mvar / net.ext_grid.max_q_mvar
289
        - net.load.min_p_mw / net.load.max_p_mw
290
        - net.load.min_q_mvar / net.load.max_q_mvar
291
        - net.storage.min_p_mw / net.storage.max_p_mw
292
        - net.storage.min_q_mvar / net.storage.max_q_mvar
293

294
    Controllable loads behave just like controllable static generators. It must be stated if they are controllable.
295
    Otherwise, they are not respected as flexibilities.
296
    Dc lines are controllable per default
297

298
    Network constraints can be defined for buses, lines and transformers the elements in the following columns:
299
        - net.bus.min_vm_pu / net.bus.max_vm_pu
300
        - net.line.max_loading_percent
301
        - net.trafo.max_loading_percent
302
        - net.trafo3w.max_loading_percent
303

304
     If the external grid ist controllable, the voltage setpoint of the external grid can be optimized within the
305
    voltage constraints by the OPF. The same applies to the voltage setpoints of the controllable generator elements.
306

307
    How these costs are combined into a cost function depends on the cost_function parameter.
308

309
    INPUT:
310
        **net** - The pandapower format network
311

312
    OPTIONAL:
313
        **verbose** (bool, False) - If True, some basic information is printed
314

315
        **suppress_warnings** (bool, True) - suppress warnings in pypower
316

317
            If set to True, warnings are disabled during the loadflow. Because of the way data is
318
            processed in pypower, ComplexWarnings are raised during the loadflow.
319
            These warnings are suppressed by this option, however keep in mind all other pypower
320
            warnings are suppressed, too.
321

322
        **init** (str, "flat") - init of starting opf vector. Options are "flat" or "pf"
323

324
            Starting solution vector (x0) for opf calculations is determined by this flag. Options are:
325
            "flat" (default): starting vector is (upper bound - lower bound) / 2
326
            "pf": a power flow is executed prior to the opf and the pf solution is the starting vector. This may improve
327
            convergence, but takes a longer runtime (which are probably neglectible for opf calculations)
328

329
        **delta** (float, 1e-10) - power tolerance
330

331
        **trafo3w_losses** (str, "hv") - defines where open loop losses of three-winding transformers are considered. Valid options are "hv", "mv", "lv" for HV/MV/LV side or "star" for the star point.
332

333
        **consider_line_temperature** (bool, False) - adjustment of line impedance based on provided\
334
            line temperature. If True, net.line must contain a column "temperature_degree_celsius".\
335
            The temperature dependency coefficient alpha must be provided in the net.line.alpha\
336
            column, otherwise the default value of 0.004 is used
337

338
         **kwargs** - Pypower / Matpower keyword arguments:
339

340
         - OPF_VIOLATION (5e-6) constraint violation tolerance
341
         - PDIPM_COSTTOL (1e-6) optimality tolerance
342
         - PDIPM_GRADTOL (1e-6) gradient tolerance
343
         - PDIPM_COMPTOL (1e-6) complementarity condition (inequality) tolerance
344
         - PDIPM_FEASTOL (set to OPF_VIOLATION if not specified) feasibiliy (equality) tolerance
345
         - PDIPM_MAX_IT  (150) maximum number of iterations
346
         - SCPDIPM_RED_IT(20) maximum number of step size reductions per iteration
347

348
    """
349 1
    _check_necessary_opf_parameters(net, logger)
350 1
    _init_runopp_options(net, calculate_voltage_angles=calculate_voltage_angles,
351
                         check_connectivity=check_connectivity,
352
                         switch_rx_ratio=switch_rx_ratio, delta=delta, init=init, numba=numba,
353
                         trafo3w_losses=trafo3w_losses,
354
                         consider_line_temperature=consider_line_temperature, **kwargs)
355 1
    _check_bus_index_and_print_warning_if_high(net)
356 1
    _check_gen_index_and_print_warning_if_high(net)
357 1
    _optimal_powerflow(net, verbose, suppress_warnings, **kwargs)
358

359

360 1
def rundcopp(net, verbose=False, check_connectivity=True, suppress_warnings=True,
361
             switch_rx_ratio=0.5, delta=1e-10, trafo3w_losses="hv", **kwargs):
362
    """
363
    Runs the  pandapower Optimal Power Flow.
364
    Flexibilities, constraints and cost parameters are defined in the pandapower element tables.
365

366
    Flexibilities for generators can be defined in net.sgen / net.gen.
367
    net.sgen.controllable / net.gen.controllable signals if a generator is controllable. If False,
368
    the active and reactive power are assigned as in a normal power flow. If yes, the following
369
    flexibilities apply:
370
        - net.sgen.min_p_mw / net.sgen.max_p_mw
371
        - net.gen.min_p_mw / net.gen.max_p_mw
372
        - net.load.min_p_mw / net.load.max_p_mw
373

374
        Network constraints can be defined for buses, lines and transformers the elements in the following columns:
375
        - net.line.max_loading_percent
376
        - net.trafo.max_loading_percent
377
        - net.trafo3w.max_loading_percent
378

379
    INPUT:
380
        **net** - The pandapower format network
381

382
    OPTIONAL:
383
        **verbose** (bool, False) - If True, some basic information is printed
384

385
        **suppress_warnings** (bool, True) - suppress warnings in pypower
386

387
            If set to True, warnings are disabled during the loadflow. Because of the way data is
388
            processed in pypower, ComplexWarnings are raised during the loadflow.
389
            These warnings are suppressed by this option, however keep in mind all other pypower
390
            warnings are suppressed, too.
391

392
        **delta** (float, 1e-10) - power tolerance
393

394
        **trafo3w_losses** (str, "hv") - defines where open loop losses of three-winding transformers are considered. Valid options are "hv", "mv", "lv" for HV/MV/LV side or "star" for the star point.
395
    """
396 1
    if (not net.sgen.empty) & ("controllable" not in net.sgen.columns):
397 0
        logger.warning('Warning: Please specify sgen["controllable"]\n')
398

399 1
    if (not net.load.empty) & ("controllable" not in net.load.columns):
400 0
        logger.warning('Warning: Please specify load["controllable"]\n')
401

402 1
    _init_rundcopp_options(net, check_connectivity=check_connectivity,
403
                           switch_rx_ratio=switch_rx_ratio, delta=delta,
404
                           trafo3w_losses=trafo3w_losses, **kwargs)
405 1
    _check_bus_index_and_print_warning_if_high(net)
406 1
    _check_gen_index_and_print_warning_if_high(net)
407 1
    _optimal_powerflow(net, verbose, suppress_warnings, **kwargs)
408

409

410 1
def _passed_runpp_parameters(local_parameters):
411
    """
412
    Internal function to distinguish arguments for pandapower.runpp() that are explicitly passed by
413
    the user.
414
    :param local_parameters: locals() in the runpp() function
415
    :return: dictionary of explicitly passed parameters
416
    """
417 1
    net = local_parameters.pop("net")
418 1
    if not ("user_pf_options" in net.keys() and len(net.user_pf_options) > 0):
419 1
        return None
420 1
    try:
421 1
        default_parameters = {k: v.default for k, v in inspect.signature(runpp).parameters.items()}
422 0
    except:
423 0
        args, varargs, keywords, defaults = inspect.getfullargspec(runpp)
424 0
        default_parameters = dict(zip(args[-len(defaults):], defaults))
425 1
    default_parameters.update({"init": "auto"})
426

427 1
    passed_parameters = {
428
        key: val for key, val in local_parameters.items()
429
        if key in default_parameters.keys() and val != default_parameters.get(key, None)}
430

431 1
    return passed_parameters

Read our documentation on viewing source code .

Loading