def _calc_sc(net): # t0 = time.perf_counter() _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) # t1 = time.perf_counter() _calc_ybus(ppci) # t2 = time.perf_counter() _calc_zbus(ppci) _calc_rx(net, ppci) # t3 = time.perf_counter() _add_kappa_to_ppc(net, ppci) # t4 = time.perf_counter() _calc_ikss(net, ppci) if net["_options"]["ip"]: _calc_ip(net, ppci) if net["_options"]["ith"]: _calc_ith(net, ppci) if net._options["branch_results"]: _calc_branch_currents(net, ppci) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc) _clean_up(net) # t5 = time.perf_counter() # net._et = {"sum": t5-t0, "model": t1-t0, "ybus": t2-t1, "zbus": t3-t2, "kappa": t4-t3, # "currents": t5-t4}
def _calc_sc(net): _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) _calc_ybus(ppci) try: _calc_zbus(ppci) except Exception as e: _clean_up(net, res=False) raise (e) _calc_rx(net, ppci) _add_kappa_to_ppc(net, ppci) _calc_ikss(net, ppci) if net["_options"]["ip"]: _calc_ip(net, ppci) if net["_options"]["ith"]: _calc_ith(net, ppci) if net._options["branch_results"]: _calc_branch_currents(net, ppci) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") if net["_options"]["return_all_currents"]: _extract_results(net, ppc, ppc_0=None) else: _extract_results(net, ppc, ppc_0=None) _clean_up(net)
def _optimal_powerflow(net, verbose, suppress_warnings, **kwargs): ac = net["_options"]["ac"] ppopt = ppoption(VERBOSE=verbose, OPF_FLOW_LIM=2, PF_DC=not ac, **kwargs) net["OPF_converged"] = False net["converged"] = False _add_auxiliary_elements(net) reset_results(net) ppc, ppci = _pd2ppc(net) if not ac: ppci["bus"][:, VM] = 1.0 net["_ppc_opf"] = ppc if len(net.dcline) > 0: ppci = add_userfcn(ppci, 'formulation', _add_dcline_constraints, args=net) if suppress_warnings: with warnings.catch_warnings(): warnings.simplefilter("ignore") result = opf(ppci, ppopt) else: result = opf(ppci, ppopt) net["_ppc_opf"] = result if not result["success"]: raise OPFNotConverged("Optimal Power Flow did not converge!") # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly mode = net["_options"]["mode"] result = _copy_results_ppci_to_ppc(result, ppc, mode=mode) net["_ppc_opf"] = result net["OPF_converged"] = True _extract_results_opf(net, result) _clean_up(net)
def _calc_sc_1ph(net, bus): """ calculation method for single phase to ground short-circuit currents """ _add_auxiliary_elements(net) # pos. seq bus impedance ppc, ppci = _pd2ppc(net) _calc_ybus(ppci) # zero seq bus impedance ppc_0, ppci_0 = _pd2ppc_zero(net) _calc_ybus(ppci_0) if net["_options"]["inverse_y"]: _calc_zbus(net, ppci) _calc_zbus(net, ppci_0) else: # Factorization Ybus once ppci["internal"]["ybus_fact"] = factorized(ppci["internal"]["Ybus"]) ppci_0["internal"]["ybus_fact"] = factorized( ppci_0["internal"]["Ybus"]) _calc_rx(net, ppci, bus=bus) _add_kappa_to_ppc(net, ppci) _calc_rx(net, ppci_0, bus=bus) _calc_ikss_1ph(net, ppci, ppci_0, bus=bus) if net._options["branch_results"]: _calc_branch_currents(net, ppci, bus=bus) ppc_0 = _copy_results_ppci_to_ppc(ppci_0, ppc_0, "sc") ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc, ppc_0, bus=bus) _clean_up(net)
def _calc_sc(net, bus): _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) _calc_ybus(ppci) if net["_options"]["inverse_y"]: _calc_zbus(net, ppci) else: # Factorization Ybus once ppci["internal"]["ybus_fact"] = factorized(ppci["internal"]["Ybus"]) _calc_rx(net, ppci, bus) # kappa required inverse of Zbus, which is optimized if net["_options"]["kappa"]: _add_kappa_to_ppc(net, ppci) _calc_ikss(net, ppci, bus) if net["_options"]["ip"]: _calc_ip(net, ppci) if net["_options"]["ith"]: _calc_ith(net, ppci) if net._options["branch_results"]: _calc_branch_currents(net, ppci, bus) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc, ppc_0=None, bus=bus) _clean_up(net) if "ybus_fact" in ppci["internal"]: # Delete factorization object ppci["internal"].pop("ybus_fact")
def _calc_sc(net): # t0 = time.perf_counter() _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) # t1 = time.perf_counter() _calc_ybus(ppci) # t2 = time.perf_counter() try: _calc_zbus(ppci) except Exception as e: _clean_up(net, res=False) raise(e) _calc_rx(net, ppci) # t3 = time.perf_counter() _add_kappa_to_ppc(net, ppci) # t4 = time.perf_counter() _calc_ikss(net, ppci) if net["_options"]["ip"]: _calc_ip(net, ppci) if net["_options"]["ith"]: _calc_ith(net, ppci) if net._options["branch_results"]: _calc_branch_currents(net, ppci) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc, ppc_0=None) _clean_up(net)
def _powerflow(net, **kwargs): """ Gets called by runpp or rundcpp with different arguments. """ # get infos from options init_results = net["_options"]["init_results"] ac = net["_options"]["ac"] recycle = net["_options"]["recycle"] mode = net["_options"]["mode"] algorithm = net["_options"]["algorithm"] max_iteration = net["_options"]["max_iteration"] net["converged"] = False net["OPF_converged"] = False _add_auxiliary_elements(net) if not ac or init_results: verify_results(net) else: reset_results(net) # TODO remove this when zip loads are integrated for all PF algorithms if algorithm not in ['nr', 'bfsw']: net["_options"]["voltage_depend_loads"] = False if recycle["ppc"] and "_ppc" in net and net[ "_ppc"] is not None and "_pd2ppc_lookups" in net: # update the ppc from last cycle ppc, ppci = _update_ppc(net) else: # convert pandapower net to ppc ppc, ppci = _pd2ppc(net) # store variables net["_ppc"] = ppc if not "VERBOSE" in kwargs: kwargs["VERBOSE"] = 0 # ----- run the powerflow ----- result = _run_pf_algorithm(ppci, net["_options"], **kwargs) # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly result = _copy_results_ppci_to_ppc(result, ppc, mode) # raise if PF was not successful. If DC -> success is always 1 if result["success"] != 1: _clean_up(net, res=False) raise LoadflowNotConverged("Power Flow {0} did not converge after " "{1} iterations!".format( algorithm, max_iteration)) else: net["_ppc"] = result net["converged"] = True _extract_results(net, result) _clean_up(net)
def _runpppf_dd(net, init, ac, calculate_voltage_angles, tolerance_kva, trafo_model, trafo_loading, enforce_q_lims, numba, recycle, **kwargs): """ Gets called by runpp or rundcpp with different arguments. """ net["converged"] = False if (ac and not init == "results") or not ac: reset_results(net) # select elements in service (time consuming, so we do it once) is_elems = _select_is_elements(net, recycle) if recycle["ppc"] and "_ppc" in net and net[ "_ppc"] is not None and "_bus_lookup" in net: # update the ppc from last cycle ppc, ppci, bus_lookup = _update_ppc(net, is_elems, recycle, calculate_voltage_angles, enforce_q_lims, trafo_model) else: # convert pandapower net to ppc ppc, ppci, bus_lookup = _pd2ppc(net, is_elems, calculate_voltage_angles, enforce_q_lims, trafo_model, init_results=(init == "results")) # store variables net["_ppc"] = ppc net["_bus_lookup"] = bus_lookup net["_is_elems"] = is_elems if not "VERBOSE" in kwargs: kwargs["VERBOSE"] = 0 # run the powerflow result = _run_fbsw(ppci, ppopt=ppoption(ENFORCE_Q_LIMS=enforce_q_lims, PF_TOL=tolerance_kva * 1e-3, **kwargs))[0] # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly result = _copy_results_ppci_to_ppc(result, ppc, bus_lookup) # raise if PF was not successful. If DC -> success is always 1 if result["success"] != 1: raise LoadflowNotConverged("Loadflow did not converge!") else: net["_ppc"] = result net["converged"] = True _extract_results(net, result, is_elems, bus_lookup, trafo_loading, ac) _clean_up(net)
def _calc_sc(net): # net["_is_elements"] = _select_is_elements(net) _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) _calc_equiv_sc_impedance(net, ppci) _add_kappa_to_ppc(net, ppci) _calc_ikss(net, ppci) _calc_ip(ppci) _calc_ith(net, ppci) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc) _clean_up(net)
def _calc_sc(net, bus): ppc, ppci = _init_ppc(net) _calc_current(net, ppci, bus) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc, ppc_0=None, bus=bus) _clean_up(net) if "ybus_fact" in ppci["internal"]: # Delete factorization object ppci["internal"].pop("ybus_fact")
def _calc_zbus(net, ppci): try: Ybus = ppci["internal"]["Ybus"] sparsity = Ybus.nnz / Ybus.shape[0]**2 if sparsity < 0.002: with warnings.catch_warnings(): warnings.simplefilter("ignore") ppci["internal"]["Zbus"] = inv_sparse(Ybus).toarray() else: ppci["internal"]["Zbus"] = inv(Ybus.toarray()) except Exception as e: _clean_up(net, res=False) raise (e)
def _calc_sc_single(net, bus): _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) _calc_ybus(ppci) try: _calc_zbus(ppci) except Exception as e: _clean_up(net, res=False) raise (e) _calc_rx(net, ppci) _calc_ikss(net, ppci) _calc_single_bus_sc(net, ppci, bus) ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_single_results(net, ppc) _clean_up(net)
def read_pm_results_to_net(net, ppc, ppci, result_pm): """ reads power models results from result_pm to ppc / ppci and then to pandapower net """ # read power models results from result_pm to result (== ppc with results) result, multinetwork = pm_results_to_ppc_results(net, ppc, ppci, result_pm) net._pm_result = result_pm success = ppc["success"] if success: if not multinetwork: # results are extracted from a single time step to pandapower dataframes _extract_results(net, result) _clean_up(net) net["OPF_converged"] = True else: _clean_up(net, res=False) logger.warning("OPF did not converge!")
def _powerflow(net, **kwargs): """ Gets called by runpp or rundcpp with different arguments. """ # get infos from options init = net["_options"]["init"] ac = net["_options"]["ac"] recycle = net["_options"]["recycle"] mode = net["_options"]["mode"] net["converged"] = False _add_auxiliary_elements(net) if (ac and not init == "results") or not ac: reset_results(net) if recycle["ppc"] and "_ppc" in net and net[ "_ppc"] is not None and "_pd2ppc_lookups" in net: # update the ppc from last cycle ppc, ppci = _update_ppc(net) else: # convert pandapower net to ppc ppc, ppci = _pd2ppc(net) # store variables net["_ppc"] = ppc if not "VERBOSE" in kwargs: kwargs["VERBOSE"] = 0 # ----- run the powerflow ----- result = _run_pf_algorithm(ppci, net["_options"], **kwargs) # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly result = _copy_results_ppci_to_ppc(result, ppc, mode) # raise if PF was not successful. If DC -> success is always 1 if result["success"] != 1: raise LoadflowNotConverged("Power Flow did not converge!") else: net["_ppc"] = result net["converged"] = True _extract_results(net, result) _clean_up(net)
def _ppci_to_net(result, net): # reads the results from result (== ppci with results) to pandapower net mode = net["_options"]["mode"] # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly ppc = net["_ppc"] result = _copy_results_ppci_to_ppc(result, ppc, mode) # raise if PF was not successful. If DC -> success is always 1 if result["success"] != 1: _clean_up(net, res=False) algorithm = net["_options"]["algorithm"] max_iteration = net["_options"]["max_iteration"] raise LoadflowNotConverged("Power Flow {0} did not converge after " "{1} iterations!".format(algorithm, max_iteration)) else: net["_ppc"] = result net["converged"] = True _extract_results(net, result) _clean_up(net)
def read_pm_results_to_net(net, ppc, ppci, result_pm): """ reads power models results from result_pm to ppc / ppci and then to pandapower net """ # read power models results from result_pm to result (== ppc with results) net._pm_result_orig = result_pm result_pm = _deep_copy_pm_results(result_pm) result_pm = _convert_pm_units_to_pp_units(result_pm, net.sn_mva) net._pm_result = result_pm result, multinetwork = pm_results_to_ppc_results(net, ppc, ppci, result_pm) success = ppc["success"] if success: if not multinetwork: # results are extracted from a single time step to pandapower dataframes _extract_results(net, result) _clean_up(net) net["OPF_converged"] = True else: _clean_up(net, res=False) logger.warning("OPF did not converge!") raise OPFNotConverged("PowerModels.jl OPF not converged")
def _calc_sc_1ph(net): """ calculation method for single phase to ground short-circuit currents """ _add_auxiliary_elements(net) # pos. seq bus impedance ppc, ppci = _pd2ppc(net) _calc_ybus(ppci) try: _calc_zbus(ppci) except Exception as e: _clean_up(net, res=False) raise (e) _calc_rx(net, ppci) _add_kappa_to_ppc(net, ppci) # zero seq bus impedance ppc_0, ppci_0 = _pd2ppc_zero(net) _calc_ybus(ppci_0) try: _calc_zbus(ppci_0) except Exception as e: _clean_up(net, res=False) raise (e) _calc_rx(net, ppci_0) _calc_ikss_1ph(net, ppci, ppci_0) if net._options["branch_results"]: _calc_branch_currents(net, ppci) ppc_0 = _copy_results_ppci_to_ppc(ppci_0, ppc_0, "sc") ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_results(net, ppc, ppc_0) _clean_up(net)
def _runpm(net, julia_file=None, pp_to_pm_callback=None): net["OPF_converged"] = False net["converged"] = False _add_auxiliary_elements(net) reset_results(net) ppc, ppci = _pd2ppc(net) pm = ppc_to_pm(net, ppci) net._pm = pm if pp_to_pm_callback is not None: pp_to_pm_callback(net, ppci, pm) result_pm = _call_powermodels(pm, julia_file) net._result_pm = result_pm result = pm_results_to_ppc_results(net, ppc, ppci, result_pm) success = ppc["success"] net["_ppc_opf"] = ppci if success: _extract_results_opf(net, result) _clean_up(net) net["OPF_converged"] = True else: _clean_up(net) logger.warning("OPF did not converge!")
def _runpm(net): #pragma: no cover net["OPF_converged"] = False net["converged"] = False _add_auxiliary_elements(net) reset_results(net) ppc, ppci = _pd2ppc(net) net["_ppc_opf"] = ppci pm = ppc_to_pm(net, ppci) net._pm = pm if net._options["pp_to_pm_callback"] is not None: net._options["pp_to_pm_callback"](net, ppci, pm) result_pm = _call_powermodels(pm, net._options["julia_file"]) net._pm_res = result_pm result = pm_results_to_ppc_results(net, ppc, ppci, result_pm) net._pm_result = result_pm success = ppc["success"] if success: _extract_results(net, result) _clean_up(net) net["OPF_converged"] = True else: _clean_up(net, res=False) logger.warning("OPF did not converge!")
def _extract_result_ppci_to_pp(net, ppc, ppci): # convert to pandapower indices ppc = _copy_results_ppci_to_ppc(ppci, ppc, mode="se") # extract results from ppc try: _add_pf_options(net, tolerance_mva=1e-8, trafo_loading="current", numba=True, ac=True, algorithm='nr', max_iteration="auto") except: pass # writes res_bus.vm_pu / va_degree and res_line _extract_results_se(net, ppc) # restore backup of previous results _rename_results(net) # additionally, write bus power demand results (these are not written in _extract_results) mapping_table = net["_pd2ppc_lookups"]["bus"] net.res_bus_est.index = net.bus.index net.res_bus_est.p_mw = get_values(ppc["bus"][:, 2], net.bus.index.values, mapping_table) net.res_bus_est.q_mvar = get_values(ppc["bus"][:, 3], net.bus.index.values, mapping_table) _clean_up(net) # delete results which are not correctly calculated for k in list(net.keys()): if k.startswith("res_") and k.endswith("_est") and \ k not in ("res_bus_est", "res_line_est", "res_trafo_est", "res_trafo3w_est"): del net[k] return net
def _calc_sc_single(net, bus): _add_auxiliary_elements(net) ppc, ppci = _pd2ppc(net) _calc_ybus(ppci) if net["_options"]["inverse_y"]: _calc_zbus(net, ppci) _calc_rx(net, ppci, bus=None) _calc_ikss(net, ppci, bus=None) _calc_single_bus_sc(net, ppci, bus) else: # Factorization Ybus once ppci["internal"]["ybus_fact"] = factorized(ppci["internal"]["Ybus"]) _calc_rx(net, ppci, bus) _calc_ikss(net, ppci, bus) _calc_single_bus_sc_no_y_inv(net, ppci, bus) # Delete factorization object ppci["internal"].pop("ybus_fact") ppc = _copy_results_ppci_to_ppc(ppci, ppc, "sc") _extract_single_results(net, ppc) _clean_up(net)
def ts_newtonpf(self, net): options = net["_options"] bus = self.ppci["bus"] branch = self.ppci["branch"] gen = self.ppci["gen"] # compute complex bus power injections [generation - load] # self.Cg = _get_Cg(gen_on, bus) # Sbus = _get_Sbus(self.baseMVA, bus, gen, self.Cg) Sbus = makeSbus(self.baseMVA, bus, gen) # run the newton power flow V, success, _, _, _, _ = nr_pf.newtonpf(self.Ybus, Sbus, self.V, self.pv, self.pq, self.ppci, options) if not success: logger.warning("Loadflow not converged") logger.info("Lines of of service:") logger.info(net.line[~net.line.in_service]) raise LoadflowNotConverged("Power Flow did not converge after") if self.ppci["gen"].shape[ 0] == 1 and not options["voltage_depend_loads"]: pfsoln = pf_solution_single_slack else: pfsoln = pfsoln_full bus, gen, branch = pfsoln(self.baseMVA, bus, gen, branch, self.Ybus, self.Yf, self.Yt, V, self.ref, self.ref_gens, Ibus=self.Ibus) self.ppci["bus"] = bus self.ppci["branch"] = branch self.ppci["gen"] = gen self.ppci["success"] = success self.ppci["et"] = None # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly self.ppc = _copy_results_ppci_to_ppc(self.ppci, self.ppc, options["mode"]) # raise if PF was not successful. If DC -> success is always 1 if self.ppc["success"] != 1: _clean_up(net, res=False) else: net["_ppc"] = self.ppc net["converged"] = True self.V = V _extract_results(net, self.ppc) return net
def _runpppf(net, **kwargs): """ Gets called by runpp or rundcpp with different arguments. """ # get infos from options init = net["_options"]["init"] ac = net["_options"]["ac"] recycle = net["_options"]["recycle"] numba = net["_options"]["numba"] enforce_q_lims = net["_options"]["enforce_q_lims"] tolerance_kva = net["_options"]["tolerance_kva"] mode = net["_options"]["mode"] algorithm = net["_options"]["algorithm"] max_iteration = net["_options"]["max_iteration"] net["converged"] = False _add_auxiliary_elements(net) if (ac and not init == "results") or not ac: reset_results(net) # select elements in service (time consuming, so we do it once) net["_is_elems"] = _select_is_elements(net, recycle) if recycle["ppc"] and "_ppc" in net and net[ "_ppc"] is not None and "_pd2ppc_lookups" in net: # update the ppc from last cycle ppc, ppci = _update_ppc(net, recycle) else: # convert pandapower net to ppc ppc, ppci = _pd2ppc(net) # store variables net["_ppc"] = ppc if not "VERBOSE" in kwargs: kwargs["VERBOSE"] = 0 # run the powerflow # algorithms implemented within pypower algorithm_pypower_dict = {'nr': 1, 'fdBX': 2, 'fdXB': 3, 'gs': 4} if algorithm == 'fbsw': # foreward/backward sweep power flow algorithm result = _run_fbsw_ppc(ppci, ppopt=ppoption(ENFORCE_Q_LIMS=enforce_q_lims, PF_TOL=tolerance_kva * 1e-3, PF_MAX_IT_GS=max_iteration, **kwargs))[0] elif algorithm in algorithm_pypower_dict: ppopt = ppoption(**kwargs) ppopt['PF_ALG'] = algorithm_pypower_dict[algorithm] ppopt['ENFORCE_Q_LIMS'] = enforce_q_lims ppopt['PF_TOL'] = tolerance_kva if max_iteration is not None: if algorithm == 'nr': ppopt['PF_MAX_IT'] = max_iteration elif algorithm == 'gs': ppopt['PF_MAX_IT_GS'] = max_iteration else: ppopt['PF_MAX_IT_FD'] = max_iteration result = _runpf(ppci, init, ac, numba, recycle, ppopt=ppoption(ENFORCE_Q_LIMS=enforce_q_lims, PF_TOL=tolerance_kva * 1e-3, **kwargs))[0] else: AlgorithmUnknown("Algorithm {0} is unknown!".format(algorithm)) # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly result = _copy_results_ppci_to_ppc(result, ppc, mode) # raise if PF was not successful. If DC -> success is always 1 if result["success"] != 1: raise LoadflowNotConverged("Loadflow did not converge!") else: net["_ppc"] = result net["converged"] = True _extract_results(net, result) _clean_up(net)
def _optimal_powerflow(net, verbose, suppress_warnings, **kwargs): ac = net["_options"]["ac"] init = net["_options"]["init"] ppopt = ppoption(VERBOSE=verbose, OPF_FLOW_LIM=2, PF_DC=not ac, INIT=init, **kwargs) net["OPF_converged"] = False net["converged"] = False _add_auxiliary_elements(net) reset_results(net, all_empty=False) ppc, ppci = _pd2ppc(net) if not ac: ppci["bus"][:, VM] = 1.0 net["_ppc_opf"] = ppci if len(net.dcline) > 0: ppci = add_userfcn(ppci, 'formulation', _add_dcline_constraints, args=net) if init == "pf": ppci = _run_pf_before_opf(net, ppci) if suppress_warnings: with warnings.catch_warnings(): warnings.simplefilter("ignore") result = opf(ppci, ppopt) else: result = opf(ppci, ppopt) # net["_ppc_opf"] = result if verbose: ppopt['OUT_ALL'] = 1 printpf(baseMVA=result["baseMVA"], bus=result["bus"], gen=result["gen"], fd=stdout, branch=result["branch"], success=result["success"], et=result["et"], ppopt=ppopt) if verbose: ppopt['OUT_ALL'] = 1 printpf(baseMVA=result["baseMVA"], bus=result["bus"], gen=result["gen"], fd=stdout, branch=result["branch"], success=result["success"], et=result["et"], ppopt=ppopt) if not result["success"]: raise OPFNotConverged("Optimal Power Flow did not converge!") # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly mode = net["_options"]["mode"] result = _copy_results_ppci_to_ppc(result, ppc, mode=mode) # net["_ppc_opf"] = result net["OPF_converged"] = True _extract_results(net, result) _clean_up(net)
def runpp_3ph(net, calculate_voltage_angles=True, init="auto", max_iteration="auto", tolerance_mva=1e-8, trafo_model='t', trafo_loading="current", enforce_q_lims=False, numba=True, recycle=None, check_connectivity=True, switch_rx_ratio=2.0, delta_q=0, v_debug=False, **kwargs): """ runpp_3ph: Performs Unbalanced/Asymmetric/Three Phase Load flow INPUT: **net** - The pandapower format network OPTIONAL: **algorithm** (str, "nr") - algorithm that is used to solve the power flow problem. The following algorithms are available: - "nr" Newton-Raphson (pypower implementation with numba accelerations) Used only for positive sequence network Zero and Negative sequence networks use Current Injection method Vnew = Y.inv * Ispecified ( from s_abc/v_abc old) Icalculated = Y * Vnew **calculate_voltage_angles** (bool, "auto") - consider voltage angles in loadflow calculation If True, voltage angles of ext_grids and transformer shifts are considered in the loadflow calculation. Considering the voltage angles is only necessary in meshed networks that are usually found in higher voltage levels. calculate_voltage_angles in "auto" mode defaults to: - True, if the network voltage level is above 70 kV - False otherwise The network voltage level is defined as the maximum rated voltage of any bus in the network that is connected to a line. **max_iteration** (int, "auto") - maximum number of iterations carried out in the power flow algorithm. In "auto" mode, the default value depends on the power flow solver: - 10 for "nr" For three phase calculations, its extended to 3 * max_iteration **tolerance_mva** (float, 1e-8) - loadflow termination condition referring to P / Q mismatch of node power in MVA **trafo_model** - transformer equivalent models - "t" - transformer is modeled as equivalent with the T-model. - "pi" - This is not recommended, since it is less exact than the T-model. So, for three phase load flow, its not implemented **trafo_loading** (str, "current") - mode of calculation for transformer loading 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. - "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. - "power" - transformer loading is given as ratio of apparent power flow to the rated apparent power of the transformer. **enforce_q_lims** (bool, False) (Not tested with 3 Phase load flow) - respect generator reactive power limits If True, the reactive power limits in net.gen.max_q_mvar/min_q_mvar are respected in the loadflow. This is done by running a second loadflow if reactive power limits are violated at any generator, so that the runtime for the loadflow will increase if reactive power has to be curtailed. Note: enforce_q_lims only works if algorithm="nr"! **check_connectivity** (bool, True) - Perform an extra connectivity test after the conversion from pandapower to PYPOWER. If True, an extra connectivity test based on SciPy Compressed Sparse Graph Routines is perfomed. If check finds unsupplied buses, they are set out of service in the ppc **voltage_depend_loads** (bool, True) (Not tested with 3 Phase load flow) - 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. **consider_line_temperature** (bool, False) (Not tested with 3 Phase load flow) - adjustment of line impedance based on provided line temperature. If True, ``net.line`` must contain a column ``temperature_degree_celsius``. The temperature dependency coefficient alpha must be provided in the ``net.line.alpha`` column, otherwise the default value of 0.004 is used. **KWARGS**: **numba** (bool, True) - Activation of numba JIT compiler in the newton solver If set to True, the numba JIT compiler is used to generate matrices for the powerflow, which leads to significant speed improvements. **switch_rx_ratio** (float, 2) (Not tested with 3 Phase load flow) - 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 **delta_q** (Not tested with 3 Phase load flow) - Reactive power tolerance for option "enforce_q_lims" in kvar - helps convergence in some cases. **trafo3w_losses** (Not tested with 3 Phase load flow) - 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. **v_debug** (bool, False) (Not tested with 3 Phase load flow) - if True, voltage values in each newton-raphson iteration are logged in the ppc. **init_vm_pu** (string/float/array/Series, None) (Not tested with 3 Phase load flow) - Allows to define initialization specifically for voltage magnitudes. Only works with ``init == "auto"``! - "auto": all buses are initialized with the mean value of all voltage controlled elements in the grid - "flat" for flat start from 1.0 - "results": voltage magnitude vector is taken from result table - a float with which all voltage magnitudes are initialized - an iterable with a voltage magnitude value for each bus (length and order has to match with the buses in net.bus) - a pandas Series with a voltage magnitude value for each bus (indexes have to match the indexes in net.bus) **init_va_degree** (string/float/array/Series, None) (Not tested with 3 Phase load flow) - Allows to define initialization specifically for voltage angles. Only works with ``init == "auto"``! - "auto": voltage angles are initialized from DC power flow if angles are calculated or as 0 otherwise - "dc": voltage angles are initialized from DC power flow - "flat" for flat start from 0 - "results": voltage angle vector is taken from result table - a float with which all voltage angles are initialized - an iterable with a voltage angle value for each bus (length and order has to match with the buses in net.bus) - a pandas Series with a voltage angle value for each bus (indexes have to match the indexes in net.bus) **recycle** (dict, none) - Reuse of internal powerflow variables for time series calculation. Contains a dict with the following parameters: bus_pq: If True PQ values of buses are updated gen: If True Sbus and the gen table in the ppc are recalculated Ybus: If True the admittance matrix (Ybus, Yf, Yt) is taken from ppc["internal"] and not reconstructed **neglect_open_switch_branches** (bool, False) (Not tested with 3 Phase load flow) - If True no auxiliary buses are created for branches when switches are opened at the branch. Instead branches are set out of service SEE ALSO: pp.add_zero_impedance_parameters(net): To add zero sequence parameters into network from the standard type EXAMPLES: Use this module like this: .. code-block:: python from pandapower.pf.runpp_3ph import runpp_3ph runpp_3ph(net) NOTES: - Three phase load flow uses Sequence Frame for power flow solution. - Three phase system is modelled with earth return. - PH-E load type is called as wye since Neutral and Earth are considered same - This solver has proved successful only for Earthed transformers (i.e Dyn,Yyn,YNyn & Yzn vector groups) """ # ============================================================================= # pandapower settings # ============================================================================= overrule_options = {} if "user_pf_options" in net.keys() and len(net.user_pf_options) > 0: passed_parameters = _passed_runpp_parameters(locals()) overrule_options = { key: val for key, val in net.user_pf_options.items() if key not in passed_parameters.keys() } if numba: numba = _check_if_numba_is_installed(numba) ac = True mode = "pf_3ph" # TODO: Make valid modes (pf, pf_3ph, se, etc.) available in seperate file (similar to idx_bus.py) # v_debug = kwargs.get("v_debug", False) copy_constraints_to_ppc = False if trafo_model == 'pi': raise Not_implemented("Three phase Power Flow doesnot support pi model\ because of lack of accuracy") # if calculate_voltage_angles == "auto": # calculate_voltage_angles = False # hv_buses = np.where(net.bus.vn_kv.values > 70)[0] # Todo: Where does that number come from? # if len(hv_buses) > 0: # line_buses = net.line[["from_bus", "to_bus"]].values.flatten() # if len(set(net.bus.index[hv_buses]) & set(line_buses)) > 0: # scipy spsolve options in NR power flow use_umfpack = kwargs.get("use_umfpack", True) permc_spec = kwargs.get("permc_spec", None) calculate_voltage_angles = True if init == "results" and net.res_bus_3ph.empty: init = "auto" if init == "auto": init = "dc" if calculate_voltage_angles else "flat" default_max_iteration = { "nr": 10, "bfsw": 10, "gs": 10000, "fdxb": 30, "fdbx": 30 } if max_iteration == "auto": max_iteration = default_max_iteration["nr"] neglect_open_switch_branches = kwargs.get("neglect_open_switch_branches", False) only_v_results = kwargs.get("only_v_results", False) net._options = {} _add_ppc_options(net, calculate_voltage_angles=calculate_voltage_angles, trafo_model=trafo_model, check_connectivity=check_connectivity, mode=mode, switch_rx_ratio=switch_rx_ratio, init_vm_pu=init, init_va_degree=init, enforce_q_lims=enforce_q_lims, recycle=None, voltage_depend_loads=False, delta=delta_q,\ neglect_open_switch_branches=neglect_open_switch_branches ) _add_pf_options(net, tolerance_mva=tolerance_mva, trafo_loading=trafo_loading, numba=numba, ac=ac, algorithm="nr", max_iteration=max_iteration,\ only_v_results=only_v_results,v_debug=v_debug, use_umfpack=use_umfpack, permc_spec=permc_spec) net._options.update(overrule_options) _check_bus_index_and_print_warning_if_high(net) _check_gen_index_and_print_warning_if_high(net) # ========================================================================= # pd2ppc conversion # ========================================================================= _, ppci1 = _pd2ppc_recycle(net, 1, recycle=recycle) _, ppci2 = _pd2ppc_recycle(net, 2, recycle=recycle) gs_eg, bs_eg = _add_ext_grid_sc_impedance(net, ppci2) _, ppci0 = _pd2ppc_recycle(net, 0, recycle=recycle) _, bus0, gen0, branch0, _, _, _ = _get_pf_variables_from_ppci(ppci0) base_mva, bus1, gen1, branch1, sl_bus, _, pq_bus = _get_pf_variables_from_ppci( ppci1) _, bus2, gen2, branch2, _, _, _ = _get_pf_variables_from_ppci(ppci2) # initialize the results after the conversion to ppc is done, otherwise init=results does not work init_results(net, "pf_3ph") # ============================================================================= # P Q values aggragated and summed up for each bus to make s_abc matrix # s_abc for wye connections ; s_abc_delta for delta connection # ============================================================================= s_abc_delta, s_abc = _load_mapping(net, ppci1) # ========================================================================= # Construct Sequence Frame Bus admittance matrices Ybus # ========================================================================= ppci0, ppci1, ppci2, y_0_pu, y_1_pu, y_2_pu, y_0_f, y_1_f, _,\ y_0_t, y_1_t, _ = _get_y_bus(ppci0, ppci1, ppci2, recycle) # ========================================================================= # Initial voltage values # ========================================================================= nb = ppci1["bus"].shape[0] # make sure flat start is always respected, even with other voltage data in recycled ppc if init == "flat": v_012_it = np.zeros((3, nb), dtype=np.complex128) v_012_it[1, :] = 1.0 else: v_012_it = np.concatenate([ np.array(ppc["bus"][:, VM] * np.exp(1j * np.deg2rad(ppc["bus"][:, VA]))).reshape( (1, nb)) for ppc in (ppci0, ppci1, ppci2) ], axis=0).astype(np.complex128) # For Delta transformation: # Voltage changed from line-earth to line-line using V_T # s_abc/v_abc will now give line-line currents. This is converted to line-earth # current using I-T v_del_xfmn = np.array([[1, -1, 0], [0, 1, -1], [-1, 0, 1]]) i_del_xfmn = np.array([[1, 0, -1], [-1, 1, 0], [0, -1, 1]]) v_abc_it = sequence_to_phase(v_012_it) # ========================================================================= # Iteration using Power mismatch criterion # ========================================================================= outer_tolerance_mva = 3e-8 count = 0 s_mismatch = np.array([[True], [True]], dtype=bool) t0 = perf_counter() while (s_mismatch > outer_tolerance_mva).any() and count < 30 * max_iteration: # ===================================================================== # Voltages and Current transformation for PQ and Slack bus # ===================================================================== s_abc_pu = -np.divide(s_abc, ppci1["baseMVA"]) s_abc_delta_pu = -np.divide(s_abc_delta, ppci1["baseMVA"]) i_abc_it_wye = (np.divide(s_abc_pu, v_abc_it)).conjugate() i_abc_it_delta = np.matmul(i_del_xfmn, (np.divide( s_abc_delta_pu, np.matmul(v_del_xfmn, v_abc_it))).conjugate()) # For buses with both delta and wye loads we need to sum of their currents # to sum up the currents i_abc_it = i_abc_it_wye + i_abc_it_delta i012_it = phase_to_sequence(i_abc_it) v1_for_s1 = v_012_it[1, :] i1_for_s1 = -i012_it[1, :] v0_pu_it = X012_to_X0(v_012_it) v2_pu_it = X012_to_X2(v_012_it) i0_pu_it = X012_to_X0(i012_it) i2_pu_it = X012_to_X2(i012_it) s1 = np.multiply(v1_for_s1, i1_for_s1.conjugate()) # ============================================================================= # Current used to find S1 Positive sequence power # ============================================================================= ppci1["bus"][pq_bus, PD] = np.real(s1[pq_bus]) * ppci1["baseMVA"] ppci1["bus"][pq_bus, QD] = np.imag(s1[pq_bus]) * ppci1["baseMVA"] # ============================================================================= # Conduct Positive sequence power flow # ============================================================================= _run_newton_raphson_pf(ppci1, net._options) # ============================================================================= # Conduct Negative and Zero sequence power flow # ============================================================================= v0_pu_it = V_from_I(y_0_pu, i0_pu_it) v2_pu_it = V_from_I(y_2_pu, i2_pu_it) # ============================================================================= # Evaluate Positive Sequence Power Mismatch # ============================================================================= i1_from_v_it = I1_from_V012(v_012_it, y_1_pu).flatten() s_from_voltage = S_from_VI_elementwise(v1_for_s1, i1_from_v_it) v1_pu_it = V1_from_ppc(ppci1) v_012_new = combine_X012(v0_pu_it, v1_pu_it, v2_pu_it) s_mismatch = np.abs( np.abs(s1[pq_bus]) - np.abs(s_from_voltage[pq_bus])) v_012_it = v_012_new v_abc_it = sequence_to_phase(v_012_it) count += 1 et = perf_counter() - t0 success = (count < 30 * max_iteration) for ppc in [ppci0, ppci1, ppci2]: ppc["et"] = et ppc["success"] = success # TODO: Add reference to paper to explain the following steps # This is required since the ext_grid power results are not correct if its # not done ref, pv, pq = bustypes(ppci0["bus"], ppci0["gen"]) ref_gens = ppci0["internal"]["ref_gens"] ppci0["bus"][ref, GS] -= gs_eg ppci0["bus"][ref, BS] -= bs_eg y_0_pu, y_0_f, y_0_t = makeYbus(ppci0["baseMVA"], ppci0["bus"], ppci0["branch"]) # revert the change, otherwise repeated calculation with recycled elements will fail ppci0["bus"][ref, GS] += gs_eg ppci0["bus"][ref, BS] += bs_eg # Bus, Branch, and Gen power values bus0, gen0, branch0 = pfsoln(base_mva, bus0, gen0, branch0, y_0_pu, y_0_f, y_0_t, v_012_it[0, :].flatten(), sl_bus, ref_gens) bus1, gen1, branch1 = pfsoln(base_mva, bus1, gen1, branch1, y_1_pu, y_1_f, y_1_t, v_012_it[1, :].flatten(), sl_bus, ref_gens) bus2, gen2, branch2 = pfsoln(base_mva, bus2, gen2, branch2, y_1_pu, y_1_f, y_1_t, v_012_it[2, :].flatten(), sl_bus, ref_gens) ppci0 = _store_results_from_pf_in_ppci(ppci0, bus0, gen0, branch0) ppci1 = _store_results_from_pf_in_ppci(ppci1, bus1, gen1, branch1) ppci2 = _store_results_from_pf_in_ppci(ppci2, bus2, gen2, branch2) i_012_res = _current_from_voltage_results(y_0_pu, y_1_pu, v_012_it) s_012_res = S_from_VI_elementwise(v_012_it, i_012_res) * ppci1["baseMVA"] eg_is_mask = net["_is_elements"]['ext_grid'] ext_grid_lookup = net["_pd2ppc_lookups"]["ext_grid"] eg_is_idx = net["ext_grid"].index.values[eg_is_mask] eg_idx_ppc = ext_grid_lookup[eg_is_idx] """ # 2 ext_grids Fix: Instead of the generator index, bus indices of the generators are used""" eg_bus_idx_ppc = np.real(ppci1["gen"][eg_idx_ppc, GEN_BUS]).astype(int) ppci0["gen"][eg_idx_ppc, PG] = s_012_res[0, eg_bus_idx_ppc].real ppci1["gen"][eg_idx_ppc, PG] = s_012_res[1, eg_bus_idx_ppc].real ppci2["gen"][eg_idx_ppc, PG] = s_012_res[2, eg_bus_idx_ppc].real ppci0["gen"][eg_idx_ppc, QG] = s_012_res[0, eg_bus_idx_ppc].imag ppci1["gen"][eg_idx_ppc, QG] = s_012_res[1, eg_bus_idx_ppc].imag ppci2["gen"][eg_idx_ppc, QG] = s_012_res[2, eg_bus_idx_ppc].imag ppc0 = net["_ppc0"] ppc1 = net["_ppc1"] ppc2 = net["_ppc2"] # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly ppc0 = _copy_results_ppci_to_ppc(ppci0, ppc0, mode=mode) ppc1 = _copy_results_ppci_to_ppc(ppci1, ppc1, mode=mode) ppc2 = _copy_results_ppci_to_ppc(ppci2, ppc2, mode=mode) _extract_results_3ph(net, ppc0, ppc1, ppc2) # Raise error if PF was not successful. If DC -> success is always 1 if not ppci0["success"]: net["converged"] = False _clean_up(net, res=False) raise LoadflowNotConverged("Power Flow {0} did not converge after\ {1} iterations!".format("nr", count)) else: net["converged"] = True _clean_up(net)
def estimate(self, v_start='flat', delta_start='flat', calculate_voltage_angles=True, zero_injection=None, fuse_buses_with_bb_switch='all'): """ The function estimate is the main function of the module. It takes up to three input arguments: v_start, delta_start and calculate_voltage_angles. The first two are the initial state variables for the estimation process. Usually they can be initialized in a "flat-start" condition: All voltages being 1.0 pu and all voltage angles being 0 degrees. In this case, the parameters can be left at their default values (None). If the estimation is applied continuously, using the results from the last estimation as the starting condition for the current estimation can decrease the amount of iterations needed to estimate the current state. The third parameter defines whether all voltage angles are calculated absolutely, including phase shifts from transformers. If only the relative differences between buses are required, this parameter can be set to False. Returned is a boolean value, which is true after a successful estimation and false otherwise. The resulting complex voltage will be written into the pandapower network. The result fields are found res_bus_est of the pandapower network. INPUT: **net** - The net within this line should be created **v_start** (np.array, shape=(1,), optional) - Vector with initial values for all voltage magnitudes in p.u. (sorted by bus index) **delta_start** (np.array, shape=(1,), optional) - Vector with initial values for all voltage angles in degrees (sorted by bus index) OPTIONAL: **calculate_voltage_angles** - (bool) - Take into account absolute voltage angles and phase shifts in transformers Default is True **zero_injection** - (str, iterable, None) - Defines which buses are zero injection bus or the method to identify zero injection bus, with 'wls_estimator' virtual measurements will be added, with 'wls_estimator with zero constraints' the buses will be handled as constraints "auto": all bus without p,q measurement, without p, q value (load, sgen...) and aux buses will be identified as zero injection bus "aux_bus": only aux bus will be identified as zero injection bus None: no bus will be identified as zero injection bus iterable: the iterable should contain index of the zero injection bus and also aux bus will be identified as zero-injection bus **fuse_buses_with_bb_switch** - (str, iterable, None) - Defines how buses with closed bb switches should be handled, if fuse buses will only fused to one for calculation, if not fuse, an auxiliary bus and auxiliary line will be automatically added to the network to make the buses with different p,q injection measurements identifieble "all": all buses with bb-switches will be fused, the same as the default behaviour in load flow None: buses with bb-switches and individual p,q measurements will be reconfigurated by auxiliary elements iterable: the iterable should contain the index of buses to be fused, the behaviour is contigous e.g. if one of the bus among the buses connected through bb switch is given, then all of them will still be fused OUTPUT: **successful** (boolean) - True if the estimation process was successful Optional estimation variables: The bus power injections can be accessed with *se.s_node_powers* and the estimated values corresponding to the (noisy) measurement values with *se.hx*. (*hx* denotes h(x)) EXAMPLE: success = estimate(np.array([1.0, 1.0, 1.0]), np.array([0.0, 0.0, 0.0])) """ if self.net is None: raise UserWarning("Component was not initialized with a network.") t0 = time() # change the configuration of the pp net to avoid auto fusing of buses connected # through bb switch with elements on each bus if this feature enabled bus_to_be_fused = None if fuse_buses_with_bb_switch != 'all' and not self.net.switch.empty: if isinstance(fuse_buses_with_bb_switch, str): raise UserWarning( "fuse_buses_with_bb_switch parameter is not correctly initialized" ) elif hasattr(fuse_buses_with_bb_switch, '__iter__'): bus_to_be_fused = fuse_buses_with_bb_switch _add_aux_elements_for_bb_switch(self.net, bus_to_be_fused) # add initial values for V and delta # node voltages # V<delta if v_start is None: v_start = "flat" if delta_start is None: delta_start = "flat" # initialize result tables if not existent _copy_power_flow_results(self.net) # initialize ppc ppc, ppci = _init_ppc(self.net, v_start, delta_start, calculate_voltage_angles) # add measurements to ppci structure ppci = _add_measurements_to_ppc(self.net, ppci, zero_injection) # Finished converting pandapower network to ppci # Estimate voltage magnitude and angle with the given estimator delta, v_m = self.estimator.estimate(ppci) # store results for all elements # calculate bus power injections v_cpx = v_m * np.exp(1j * delta) bus_powers_conj = np.zeros(len(v_cpx), dtype=np.complex128) for i in range(len(v_cpx)): bus_powers_conj[i] = np.dot(ppci['internal']['Y_bus'][i, :], v_cpx) * np.conjugate(v_cpx[i]) ppci["bus"][:, 2] = bus_powers_conj.real # saved in per unit ppci["bus"][:, 3] = -bus_powers_conj.imag # saved in per unit ppci["bus"][:, 7] = v_m ppci["bus"][:, 8] = delta * 180 / np.pi # convert to degree # calculate line results (in ppc_i) s_ref, bus, gen, branch = _get_pf_variables_from_ppci(ppci)[0:4] out = np.flatnonzero(branch[:, BR_STATUS] == 0) # out-of-service branches br = np.flatnonzero(branch[:, BR_STATUS]).astype( int) # in-service branches # complex power at "from" bus Sf = v_cpx[np.real(branch[br, F_BUS]).astype(int)] * np.conj( ppci['internal']['Yf'][br, :] * v_cpx) * s_ref # complex power injected at "to" bus St = v_cpx[np.real(branch[br, T_BUS]).astype(int)] * np.conj( ppci['internal']['Yt'][br, :] * v_cpx) * s_ref branch[np.ix_(br, [PF, QF, PT, QT])] = np.c_[Sf.real, Sf.imag, St.real, St.imag] branch[np.ix_(out, [PF, QF, PT, QT])] = np.zeros((len(out), 4)) et = time() - t0 ppci = _store_results_from_pf_in_ppci(ppci, bus, gen, branch, self.estimator.successful, self.estimator.iterations, et) # convert to pandapower indices ppc = _copy_results_ppci_to_ppc(ppci, ppc, mode="se") # extract results from ppc _add_pf_options(self.net, tolerance_mva=1e-8, trafo_loading="current", numba=True, ac=True, algorithm='nr', max_iteration="auto") # writes res_bus.vm_pu / va_degree and res_line _extract_results_se(self.net, ppc) # restore backup of previous results _rename_results(self.net) # additionally, write bus power injection results (these are not written in _extract_results) mapping_table = self.net["_pd2ppc_lookups"]["bus"] self.net.res_bus_est.p_mw = -get_values( ppc["bus"][:, 2], self.net.bus.index.values, mapping_table) self.net.res_bus_est.q_mvar = -get_values( ppc["bus"][:, 3], self.net.bus.index.values, mapping_table) _clean_up(self.net) # clear the aux elements and calculation results created for the substitution of bb switches if fuse_buses_with_bb_switch != 'all' and not self.net.switch.empty: _drop_aux_elements_for_bb_switch(self.net) # delete results which are not correctly calculated for k in list(self.net.keys()): if k.startswith("res_") and k.endswith("_est") and \ k not in ("res_bus_est", "res_line_est", "res_trafo_est", "res_trafo3w_est"): del self.net[k] return self.estimator.successful
def _optimal_powerflow(net, verbose, suppress_warnings, **kwargs): ac = net["_options"]["ac"] init = net["_options"]["init"] if "OPF_FLOW_LIM" not in kwargs: kwargs["OPF_FLOW_LIM"] = 2 if net["_options"]["voltage_depend_loads"] and not ( allclose(net.load.const_z_percent.values, 0) and allclose(net.load.const_i_percent.values, 0)): logger.error( "pandapower optimal_powerflow does not support voltage depend loads." ) ppopt = ppoption(VERBOSE=verbose, PF_DC=not ac, INIT=init, **kwargs) net["OPF_converged"] = False net["converged"] = False _add_auxiliary_elements(net) if not ac or net["_options"]["init_results"]: verify_results(net) else: init_results(net, "opf") ppc, ppci = _pd2ppc(net) if not ac: ppci["bus"][:, VM] = 1.0 net["_ppc_opf"] = ppci if len(net.dcline) > 0: ppci = add_userfcn(ppci, 'formulation', _add_dcline_constraints, args=net) if init == "pf": ppci = _run_pf_before_opf(net, ppci) if suppress_warnings: with warnings.catch_warnings(): warnings.simplefilter("ignore") result = opf(ppci, ppopt) else: result = opf(ppci, ppopt) # net["_ppc_opf"] = result if verbose: ppopt['OUT_ALL'] = 1 printpf(baseMVA=result["baseMVA"], bus=result["bus"], gen=result["gen"], branch=result["branch"], f=result["f"], success=result["success"], et=result["et"], fd=stdout, ppopt=ppopt) if not result["success"]: raise OPFNotConverged("Optimal Power Flow did not converge!") # ppci doesn't contain out of service elements, but ppc does -> copy results accordingly mode = net["_options"]["mode"] result = _copy_results_ppci_to_ppc(result, ppc, mode=mode) # net["_ppc_opf"] = result net["OPF_converged"] = True _extract_results(net, result) _clean_up(net)
def cleanup(self): _clean_up(self.net) self.init_newton_variables()