def powerflow(self): try: pp.runpp(self.net) return self._results() except pp.LoadflowNotConverged: pp.diagnostic(self.net) return None, None
def test_no_issues(diag_params, diag_errors, report_methods): net = nw.example_simple() diag_results = pp.diagnostic(net, report_style=None) assert diag_results == {} for bool_value in [True, False]: for check_function in report_methods.keys(): diag_report = DiagnosticReports(net, diag_results, diag_errors, diag_params, compact_report=bool_value) report_check = None try: eval(report_methods[check_function]) report_check = True except: report_check = False assert report_check
def test_diagnostic_report(): net = nw.example_multivoltage() net.line.loc[7, 'length_km'] = -1 net.gen.bus.at[0] = 0 net.load.p_kw.at[4] *= 1000 net.switch.closed.at[0] = 0 net.switch.closed.at[2] = 0 pp.create_switch(net, 41, 45, et='b') net.line.r_ohm_per_km.at[1] = 0 net.load.p_kw.at[0] = -1 net.switch.closed.loc[37, 38] = False net.line.x_ohm_per_km.loc[6] -= 1 net.line.from_bus.iloc[0] = 10000 pp.create_switch(net, 1, 2, et='b') diag_results = pp.diagnostic(net) diag_params = { "overload_scaling_factor": 0.001, "lines_min_length_km": 0, "lines_min_z_ohm": 0, "nom_voltage_tolerance": 0.3, "numba_tolerance": 1e-5 } diag_report = DiagnosticReports(net, diag_results, diag_params, compact_report=False) report_methods = { "missing_bus_indeces": diag_report.report_missing_bus_indeces, "disconnected_elements": diag_report.report_disconnected_elements, "different_voltage_levels_connected": diag_report.report_different_voltage_levels_connected, "lines_with_impedance_close_to_zero": diag_report.report_lines_with_impedance_close_to_zero, "nominal_voltages_dont_match": diag_report.report_nominal_voltages_dont_match, "invalid_values": diag_report.report_invalid_values, "overload": diag_report.report_overload, "multiple_voltage_controlling_elements_per_bus": diag_report.report_multiple_voltage_controlling_elements_per_bus, "wrong_switch_configuration": diag_report.report_wrong_switch_configuration, "no_ext_grid": diag_report.report_no_ext_grid, "wrong_reference_system": diag_report.report_wrong_reference_system, "deviation_from_std_type": diag_report.report_deviation_from_std_type, "numba_comparison": diag_report.report_numba_comparison, "parallel_switches": diag_report.report_parallel_switches } for key in diag_results: report_check = None try: report_methods[key]() report_check = True except: report_check = False assert report_check diag_report = DiagnosticReports(net, diag_results, diag_params, compact_report=True) for key in diag_results: report_check = None try: report_methods[key]() report_check = True except: report_check = False assert report_check
def test_runpp_errors(test_net, diag_params, diag_errors, report_methods): net = copy.deepcopy(test_net) net.load.p_mw *= 100 diag = pp.diagnostic(net, report_style=None)
def diag(): net = faulty_example_network() # pp.runpp(net) # pplt.simple_plot(net, plot_line_switches=True) pp.diagnostic(net)
def sim_request(data): is_three_phase = utils.get_or_error("3phase", data) elements_dict = utils.get_or_error("elements", data) buses = {} # Used for matching bus UUIDs to index def process_potential_bus(key, value): """ Inner method for processing a positional argument that could be a bus This function checks if the value is in the bus keys. This should never cause issues so long as UUID's aren't used for any other purpose except for bus identification and as long as there are no UUID collisions. Both of those cases seem exceptionally unlikely, so this should work fine. """ if value in buses.keys(): return buses[value] else: return value bus_list = [(uuid, element) for uuid, element in elements_dict.items() if utils.get_or_error("etype", element) == "bus"] element_list = [(uuid, element) for uuid, element in elements_dict.items() if utils.get_or_error("etype", element) != "bus" and utils.get_or_error("etype", element) != "switch"] switch_list = [(uuid, element) for uuid, element in elements_dict.items() if utils.get_or_error("etype", element) == "switch"] net = pp.create_empty_network() for uuid, bus in bus_list: element_type = "bus" req_props = utils.required_props[element_type] positional_args = [ value for key, value in bus.items() if key in req_props ] optional_args = { key: value for key, value in bus.items() if (not key in req_props) and (not key == "etype")} index = pp.create_bus(net, *positional_args, **optional_args, name=uuid) buses[uuid] = index for uuid, element in element_list: element_type = utils.get_or_error("etype", element) req_props = utils.required_props[element_type] positional_args = [process_potential_bus(key, value) for key, value in element.items() if key in req_props] optional_args = { key: value for key, value in element.items() if (not key in req_props) and (not key == "etype")} if element_type == "load": pp.create_load(net, *positional_args, **optional_args, name=uuid) elif element_type == "gen": pp.create_gen(net, *positional_args, **optional_args, name=uuid) elif element_type == "ext_grid": pp.create_ext_grid(net, *positional_args, **optional_args, name=uuid) elif element_type == "line": pp.create_line(net, *positional_args, *optional_args, name=uuid) elif element_type == "trafo": pp.create_transformer_from_parameters(net, *positional_args, **optional_args, name=uuid) elif element_type == "storage": pp.create_storage(net, *positional_args, **optional_args, name=uuid) else: raise InvalidError(f"Element type {element_type} is invalid or not implemented!") for uuid, switch in switch_list: element_type = "switch" req_props = utils.required_props[element_type] positional_args = [process_potential_bus(key, value) for key, value in element.items() if key in req_props] optional_args = { key: value for key, value in element.items() if (not key in req_props) and (not key == "etype")} et = positional_args[2] if et == "b": pass # This is handled by process_potential_buses if et == "l": positional_args[1] = pp.get_element_index(net, "line", positional_args[1]) elif et == "t": positional_args[1] = pp.get_element_index(net, "trafo", positional_args[1]) elif et == "t3": positional_args[1] = pp.get_element_index(net, "trafo3w", positional_args[1]) else: raise InvalidError(f"Invalid element type {et}. Must be b,l,t, or t3.") pp.create_switch(net, *positional_args, **optional_args, name=uuid) try: if is_three_phase: pp.runpp_3ph(net) else: pp.runpp(net) except LoadflowNotConverged: report = pp.diagnostic(net, report_style="compact", warnings_only=True) raise ConvError("Load flow did not converge.") except (KeyError, ValueError) as e: raise PPError(str(e)) except Exception as e: raise PPError("Unknown exception has occured: " + str(e)) message = {} message["status"] = "SIM_RESULT" results = {} for uuid,element in elements_dict.items(): element_type = elements_dict[uuid]["etype"] if element_type == "switch": continue net["res_" + element_type] = net["res_" + element_type].fillna(0) results[uuid] = {} results[uuid]["etype"] = element_type index = pp.get_element_index(net, element_type, uuid, exact_match=True) results[uuid].update(net["res_" + element_type].iloc[index].to_dict()) message["elements"] = results return json.dumps(message)
for pq in pqs.itertuples(index=True, name='Pandas'): bus_num = getattr(pq, "bus_num") p_mw = getattr(pq, "active_power") q_mvar = getattr(pq, "reactive_power") pq_num = getattr(pq, "Index") pp.create_load(net, bus_num-1, p_mw=p_mw, q_mvar=q_mvar, name='Load %s' % pq_num) print(net.load) # show loads table ### PQgen ### pqgens = pd.read_csv('data/PQgen.csv',names=['bus_num','power_rating','voltage_rating','active_power','reactive_power', 'v_max','v_min','conv_imp','area'],index_col=False) for pqgen in pqgens.itertuples(index=True, name='Pandas'): bus_num = getattr(pqgen, "bus_num") try: mask=pqs[pqs['bus_num']==bus_num].index.tolist()[0] raise ValueError("Attention static gens and loads at the same bus. Manually modify database") except: p_mw = getattr(pqgen, "active_power") q_mvar = getattr(pqgen, "reactive_power") sn_mva = getattr(pqgen, "power_rating") pqgen_num = getattr(pqgen, "Index") pp.create_sgen(net, bus_num-1, p_mw=p_mw, q_mvar=q_mvar, sn_mva=sn_mva, name='StatGen %s' % pqgen_num) #pp.create_load(net, bus_num-1, p_mw=p_mw, q_mvar=q_mvar, name='StatGen %s' % pqgen_num) print(net.sgen) # show static gen table ### Diagnosis ### pp.diagnostic(net, report_style='detailed', warnings_only=False, return_result_dict=True, overload_scaling_factor=0.001, min_r_ohm=0.001, min_x_ohm=0.001, min_r_pu=1e-05, min_x_pu=1e-05, nom_voltage_tolerance=0.3, numba_tolerance=1e-05) ### Run Power Flow ### pp.runpp(net, algorithm="iwamoto_nr", calculate_voltage_angles="auto", init="dc", check_connectivity=True, v_debug=True) #, init_vm_pu=True, init_va_degree=True print(net)
def test_no_issues(test_net): net = copy.deepcopy(test_net) assert pp.diagnostic(net, report_style=None) == {}
def validate_pf_conversion(net, is_unbalanced=False, **kwargs): """ Trys to run a Loadflow with the converted pandapower network. If the loadflow converges, \ PowerFactory and pandapower loadflow results will be compared. Note that a pf validation can \ only be done if there are pf results available. INPUT: - **net** (PandapowerNetwork) - converted pandapower network OUTPUT: - **all_diffs** (list) - returns a list with the difference in all validated values. If all values are zero -> results are equal """ logger.debug('starting verification') toolbox.replace_zero_branches_with_switches(net) pf_results = _get_pf_results(net, is_unbalanced=is_unbalanced) if "controller" not in net.keys() or len(net.controller) == 0: try: for arg in 'trafo_model check_connectivity'.split(): if arg in kwargs: kwargs.pop(arg) if is_unbalanced: logger.info("running pandapower 3ph loadflow") pp.runpp_3ph(net, trafo_model="t", check_connectivity=True, **kwargs) else: logger.info("running pandapower loadflow") pp.runpp(net, trafo_model="t", check_connectivity=True, **kwargs) except Exception as err: logger.error('pandapower load flow failed: %s' % err, exc_info=True) diagnostic(net) raise err else: import pandapower.control as control try: control.run_control(net, max_iter=50, trafo_model="t", check_connectivity=True, **kwargs) except Exception as err: logger.error('pandapower load flow with converter failed: %s' % err) diagnostic(net) raise err all_diffs = dict() logger.info('pandapower net converged: %s' % net.converged) _set_pf_results(net, pf_results, is_unbalanced=is_unbalanced) net.bus.name.fillna("", inplace=True) only_in_pandapower = set(net.bus[net.bus.name.str.endswith("_aux")].index) | \ set(net.bus[net.bus.type == "ls"].index) in_both = set(net.bus.index) - only_in_pandapower pf_closed = pf_results['pf_switch_status'] wrong_switches = net.res_switch.loc[pf_closed != net.switch.loc[ pf_closed.index, 'closed']].index.values if 'res_switch' in net.keys() else [] if len(net.switch) > 0: logger.info('%d switches are wrong: %s' % (len(wrong_switches), wrong_switches)) if len(net.trafo3w[net.trafo3w.in_service]) > 0: trafo3w_idx = net.trafo3w.query('in_service').index trafo3w_diff = net.res_trafo3w.loc[ trafo3w_idx].pf_loading - net.res_trafo3w.loc[ trafo3w_idx].loading_percent trafo3w_id = abs(trafo3w_diff).idxmax() logger.info( "Maximum trafo3w loading difference between pandapower and powerfactory: %.1f " "percent at trafo3w %d (%s)" % (max(abs(trafo3w_diff)), trafo3w_id, net.trafo3w.at[trafo3w_id, 'name'])) all_diffs["trafo3w_diff"] = trafo3w_diff if len(net.sgen[net.sgen.in_service]) > 0: logger.debug('verifying sgen') sgen_p_diff = net.res_sgen.pf_p.replace(np.nan, 0) - net.res_sgen.p_mw sgen_q_diff = net.res_sgen.pf_q.replace(np.nan, 0) - net.res_sgen.q_mvar sgen_p_diff_is = net.res_sgen.pf_p.replace(np.nan, 0) * net.sgen.loc[ net.res_sgen.index, 'in_service'] - net.res_sgen.p_mw sgen_q_diff_is = net.res_sgen.pf_q.replace(np.nan, 0) * net.sgen.loc[ net.res_sgen.index, 'in_service'] - net.res_sgen.q_mvar logger.info( "Maximum sgen active power difference between pandapower and powerfactory: " "%.1f MW, in service only: %.1f MW" % (max(abs(sgen_p_diff)), max(abs(sgen_p_diff_is)))) logger.info( "Maximum sgen reactive power difference between pandapower and powerfactory: " "%.1f Mvar, in service only: %.1f Mvar" % (max(abs(sgen_q_diff)), max(abs(sgen_q_diff_is)))) all_diffs["sgen_p_diff_is"] = sgen_p_diff_is all_diffs["sgen_q_diff_is"] = sgen_q_diff_is if len(net.gen[net.gen.in_service]) > 0: logger.debug('verifying gen') gen_p_diff = net.res_gen.pf_p.replace(np.nan, 0) - net.res_gen.p_mw gen_q_diff = net.res_gen.pf_q.replace(np.nan, 0) - net.res_gen.q_mvar gen_p_diff_is = net.res_gen.pf_p.replace(np.nan, 0) * net.gen.loc[ net.res_gen.index, 'in_service'] - net.res_gen.p_mw gen_q_diff_is = net.res_gen.pf_q.replace(np.nan, 0) * net.gen.loc[ net.res_gen.index, 'in_service'] - net.res_gen.q_mvar logger.info( "Maximum gen active power difference between pandapower and powerfactory: " "%.1f MW, in service only: %.1f MW" % (max(abs(gen_p_diff)), max(abs(gen_p_diff_is)))) logger.info( "Maximum gen reactive power difference between pandapower and powerfactory: " "%.1f Mvar, in service only: %.1f Mvar" % (max(abs(gen_q_diff)), max(abs(gen_q_diff_is)))) all_diffs["gen_p_diff_is"] = gen_p_diff_is all_diffs["gen_q_diff_is"] = gen_q_diff_is if len(net.ward[net.ward.in_service]) > 0: logger.debug('verifying ward') ward_p_diff = net.res_ward.pf_p.replace(np.nan, 0) - net.res_ward.p_mw ward_q_diff = net.res_ward.pf_q.replace(np.nan, 0) - net.res_ward.q_mvar ward_p_diff_is = net.res_ward.pf_p.replace(np.nan, 0) * net.ward.loc[ net.res_ward.index, 'in_service'] - net.res_ward.p_mw ward_q_diff_is = net.res_ward.pf_q.replace(np.nan, 0) * net.ward.loc[ net.res_ward.index, 'in_service'] - net.res_ward.q_mvar logger.info( "Maximum ward active power difference between pandapower and powerfactory: " "%.1f MW, in service only: %.1f MW" % (max(abs(ward_p_diff)), max(abs(ward_p_diff_is)))) logger.info( "Maximum ward reactive power difference between pandapower and powerfactory: " "%.1f Mvar, in service only: %.1f Mvar" % (max(abs(ward_q_diff)), max(abs(ward_q_diff_is)))) all_diffs["ward_p_diff_is"] = ward_p_diff_is all_diffs["ward_q_diff_is"] = ward_q_diff_is if is_unbalanced: _validate_pf_conversion_unbalanced(net, in_both, all_diffs) else: _validate_pf_conversion_balanced(net, in_both, all_diffs) return all_diffs