def test_json(net_in, tmp_path): filename = os.path.join(os.path.abspath(str(tmp_path)), "testfile.json") try: net_geo = copy.deepcopy(net_in) # make GeodataFrame from shapely.geometry import Point, LineString from fiona.crs import from_epsg import geopandas as gpd for tab in ('bus_geodata', 'line_geodata'): if tab == 'bus_geodata': geometry = net_geo[tab].apply(lambda x: Point(x.x, x.y), axis=1) else: geometry = net_geo[tab].coords.apply(LineString) net_geo[tab] = gpd.GeoDataFrame(net_geo[tab], geometry=geometry, crs=from_epsg(4326)) pp.to_json(net_geo, filename) net_out = pp.from_json(filename) assert_net_equal(net_geo, net_out) # assert isinstance(net_out.line_geodata, gpd.GeoDataFrame) # assert isinstance(net_out.bus_geodata, gpd.GeoDataFrame) assert isinstance(net_out.bus_geodata.geometry.iat[0], Point) assert isinstance(net_out.line_geodata.geometry.iat[0], LineString) except (NameError, ImportError): pass # check if restore_all_dtypes works properly: net_in.line['test'] = 123 net_in.res_line['test'] = 123 pp.to_json(net_in, filename) net_out = pp.from_json(filename) assert_net_equal(net_in, net_out)
def _reset_to_orig_state(self): """ reset this "environment" to the state it should be """ self.backend.set_thermal_limit(self._thermal_limit_a) self.gen_activeprod_t[:] = self.gen_activeprod_t_init self.gen_activeprod_t_redisp[:] = self.gen_activeprod_t_redisp_init self.times_before_line_status_actionable[:] = self.times_before_line_status_actionable_init self.times_before_topology_actionable[:] = self.times_before_topology_actionable_init self.time_next_maintenance[:] = self.time_next_maintenance_init self.duration_next_maintenance[:] = self.duration_next_maintenance_init self.target_dispatch[:] = self.target_dispatch_init self.actual_dispatch[:] = self.actual_dispatch_init self.last_bus_line_or[:] = self.last_bus_line_or_init self.last_bus_line_ex[:] = self.last_bus_line_ex_init new = True save = False if new: self._backend_action_set.all_changed() # self.backend.apply_action(None, self._backend_action_set) self._backend_action = copy.deepcopy(self._backend_action_set) if save: import pandapower as pp pp.to_json(self.backend._grid, "test_action2.json") else: self.backend.apply_action(self._action) if save: import pandapower as pp pp.to_json(self.backend._grid, "test_action1.json")
def test_store_and_load(simple_test_net): net = simple_test_net n_timesteps = 2 profiles, ds = create_data_source(n_timesteps) ConstControl(net, element='load', variable='p_mw', element_index=[0, 1, 2], data_source=ds, profile_name=["load1", "load2_mv_p", "load3_hv_p"]) dirname = tempfile.gettempdir() ow = OutputWriter(net, output_path=dirname, output_file_type=".json") ow.remove_log_variable("res_bus") tmp_file = os.path.join(dirname, "net.json") pp.to_json(net, tmp_file) del net del ow res_line_file = os.path.join(dirname, "res_line", "loading_percent.json") # del result file is one is present if os.path.isfile(res_line_file): os.remove(res_line_file) net = pp.from_json(tmp_file) ow = net.output_writer.iat[0, 0] assert len(ow.log_variables) == 1 assert ow.output_path == dirname time_steps = range(0, n_timesteps) run_timeseries(net, time_steps=time_steps, verbose=False) # check if results were written assert os.path.isfile(res_line_file)
def save_file(self, full_path): """ Save the file to json. :param full_path: :return: """ pp.to_json(self._grid, full_path)
def test_json(net_in, tempdir): filename = os.path.join(tempdir, "testfile.json") try: net_geo = copy.deepcopy(net_in) # make GeodataFrame from shapely.geometry import Point, LineString from fiona.crs import from_epsg import geopandas as gpd for tab in ('bus_geodata', 'line_geodata'): net_geo[tab]['geometry'] = None net_geo[tab] = gpd.GeoDataFrame(net_geo[tab], geometry='geometry', crs=from_epsg(4326)) for idx, row in net_geo.bus_geodata.iterrows(): net_geo.bus_geodata.at[idx, 'geometry'] = Point(row.x, row.y) for idx, row in net_geo.line_geodata.iterrows(): net_geo.line_geodata.at[idx, 'geometry'] = LineString(row.coords) pp.to_json(net_geo, filename) net_out = pp.from_json(filename) assert_net_equal(net_geo, net_out) except (NameError, ImportError): pass # check if restore_all_dtypes works properly: net_in.line['test'] = 123 # this will not work: # net_in.res_line['test'] = 123 pp.to_json(net_in, filename) net_out = pp.from_json(filename) assert_net_equal(net_in, net_out)
def test_json(): net_in = create_test_network() net_in.line_geodata.loc[0, "coords"] = [(1.1, 2.2), (3.3, 4.4)] net_in.line_geodata.loc[1, "coords"] = [(5.5, 5.5), (6.6, 6.6), (7.7, 7.7)] pp.to_json(net_in, "testfile.json") net_out = pp.from_json("testfile.json") assert_net_equal(net_in, net_out, reindex=True) os.remove('testfile.json')
def save_net(best_net, path: str, format_='pickle'): """ Save pandapower network to some format. """ filename = 'best_net' if format_ == 'pickle': pp.to_pickle(best_net, path + filename + '.p') elif format_ == 'json': pp.to_json(best_net, path + filename + '.json') else: print(f'File format "{format_}" not implemented yet!')
def test_encrypted_json(net_in, tmp_path): import cryptography.fernet filename = os.path.abspath(str(tmp_path)) + "testfile.json" pp.to_json(net_in, filename, encryption_key="verysecret") with pytest.raises(json.JSONDecodeError): pp.from_json(filename) with pytest.raises(cryptography.fernet.InvalidToken): pp.from_json(filename, encryption_key="wrong") net_out = pp.from_json(filename, encryption_key="verysecret") assert_net_equal(net_in, net_out)
def test_json_io_same_net(net_in, tempdir): pp.control.ConstControl(net_in, 'load', 'p_mw', 0) s = pp.to_json(net_in) net1 = pp.from_json_string(s) assert net1.controller.object.at[0].net is net1 filename = os.path.join(tempdir, "testfile.json") pp.to_json(net_in, filename) net2 = pp.from_json(filename) assert net2.controller.object.at[0].net is net2
def save_file(self, full_path): """ .. warning:: /!\\\\ Internal, do not use unless you know what you are doing /!\\\\ You might want to use it for debugging purpose only, and only if you develop yourself a backend. Save the file to json. :param full_path: :return: """ pp.to_json(self._grid, full_path)
def test_json_io_same_net(net_in, tmp_path): control.ConstControl(net_in, 'load', 'p_mw', 0) s = pp.to_json(net_in) net1 = pp.from_json_string(s) assert isinstance(net1.controller.object.at[0], control.ConstControl) filename = os.path.abspath(str(tmp_path)) + "testfile.json" pp.to_json(net_in, filename) net2 = pp.from_json(filename) assert isinstance(net2.controller.object.at[0], control.ConstControl)
def test_to_json_dtypes(tempdir): filename = os.path.join(tempdir, "testfile.json") net = create_test_network() pp.runpp(net) net['res_test'] = pd.DataFrame(columns=['test'], data=[1, 2, 3]) net['test'] = pd.DataFrame(columns=['test'], data=[1, 2, 3]) net.line['test'] = 123 net.res_line['test'] = 123 net.bus['test'] = 123 net.res_bus['test'] = 123 net.res_load['test'] = 123 pp.to_json(net, filename) net1 = pp.from_json(filename)
def test_to_json_dtypes(tmp_path): filename = os.path.abspath(str(tmp_path)) + "testfile.json" net = create_test_network() pp.runpp(net) net['res_test'] = pd.DataFrame(columns=['test'], data=[1, 2, 3]) net['test'] = pd.DataFrame(columns=['test'], data=[1, 2, 3]) net.line['test'] = 123 net.res_line['test'] = 123 net.bus['test'] = 123 net.res_bus['test'] = 123 net.res_load['test'] = 123 pp.to_json(net, filename) net1 = pp.from_json(filename) assert_net_equal(net, net1)
def w_pp_net(self, env): pp_network = dict() arg = env.get_config() #use if pandapower net obj is exported: pp_network['file_path'] = arg['net_fp'] #use if you want to use in-built network pp_network['pp_name'] = arg['net_id'] if not os.path.isdir('./loc_data'): os.system('mkdir ./loc_data') if not os.path.isfile('./loc_data/pp_net.json'): os.system('touch ./loc_data/pp_net.json') pp.to_json(arg['net'], arg['net_fp']) return (pp_network)
def test_empty_geo_dataframe(): net = pp.create_empty_network() net.bus_geodata['geometry'] = None net.bus_geodata = gpd.GeoDataFrame(net.bus_geodata) s = pp.to_json(net) net1 = pp.from_json_string(s) assert assert_net_equal(net, net1)
def create_pp_from_ppc(): # create ppc ppc = create_ppc() # convert it to a pandapower net net = cv.from_ppc(ppc, validate_conversion=False) # run a power flow pp.runpp(net) vm_pu_before = net.res_bus.vm_pu.values # manual corrections and additional information such as line length in km and names net = add_additional_information(net) # run power flow again and validate results pp.runpp(net) vm_pu_after = net.res_bus.vm_pu.values # power flow results should not change assert np.allclose(vm_pu_after, vm_pu_before) # save it pp.to_json(net, "pandapower_net.json") # plot it :) plot_net(net)
def test_type_casting_json(net_in, tmp_path): filename = os.path.abspath(str(tmp_path)) + "testfile.json" net_in.sn_kva = 1000 pp.to_json(net_in, filename) net = pp.from_json(filename) assert_net_equal(net_in, net)
'maroon', 'olive', 'deeppink', 'blueviolet', 'darkturquoise', 'darkorange' ] f, ax = plt.subplots() for i, f in enumerate(fs): if f[0] == 'F': plot_lines(lines[lines.Feeder == f], color=colors[i % len(colors)], linewidth=load_pv_feeder.PV_gen[f] / 1, label=f, col='ShapeGPS', ax=ax) plt.legend() ## Saving grids v = util.input_y_n('Do you want to save grids created grids?') if v in ['Y', 'y', True]: pp.to_json(net, folder + r'PPGrid/base_grid.json') pp.to_json(net_res, folder + r'PPGrid/res_grid_voltvar.json') #%% Run base grid time series v = util.input_y_n('Run base grid time series?') if v in ['Y', 'y', True]: # Creating profiler profiler = Profiler(net=net, profiles_db=profiles_load) for n in net.load.zone.unique(): if not n is None: profiler.add_profile_idx('load', net.load[net.load.zone == n].index, variable='scaling', profile=str(n)) # Setting iterator time_steps = profiler.profiles_db.index
def test_json(net_in, tempdir): filename = os.path.join(tempdir, "testfile.json") pp.to_json(net_in, filename) net_out = pp.from_json(filename) assert_net_equal(net_in, net_out)
if isclass(class_) and issubclass(class_, Component): return class_ else: # for non-pp objects, e.g. tuple return class_(self.obj, **self.d) @to_serializable.register(pandapipesNet) def json_net(obj): net_dict = {k: item for k, item in obj.items() if not k.startswith("_")} d = with_signature(obj, net_dict) return d @to_serializable.register(type) def json_component(class_): if issubclass(class_, Component): d = with_signature(class_(), str(class_().__dict__)) return d else: raise (UserWarning('with_signature needs to be defined for ' 'class %s in @to_serializable.register(type)!' % class_)) if __name__ == '__main__': ntw = create_fluid_network() import pandapipes as pp pp.to_json(ntw, 'test.json') ntw = pp.from_json('test.json')
''' Define, save & load power grid ''' import yaml import pandapower as pp import pandapower.networks as pn import pandapower.plotting as ppl with open('grid.yaml') as file: d = yaml.load(file) if d['EXISTED_IN_PP']: sentence = f"pn.{d['PP_NAME']}()" print(sentence) net = eval(sentence) print(net) pp.to_json(net, filename=f"grid/{d['GRID_NAME']}/{d['FILE_NAME']}") ppl.to_html(net, filename=f"grid/{d['GRID_NAME']}/info.html")
def __batch_save_net(self, batch, logs): if not os.path.isdir('./nets'): os.system('mkdir nets') save_id = './nets/net{}.json'.format(batch) pp.to_json(self.env.env.net.net, save_id)
# -*- coding: utf-8 -*- # Copyright (c) 2016-2021 by University of Kassel and Fraunhofer Institute for Energy Economics # and Energy System Technology (IEE), Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. import pandapower.networks as nw import pandapower as pp import pandapower.control as control import os net = nw.example_multivoltage() control.DiscreteTapControl(net, 1, 1.02, 1.03) pp.runpp(net, run_control=True) pp.to_json(net, os.path.join("old_versions", "example_%s.json" % pp.__version__))
def from_pfd(app, prj_name: str, path_dst=None, pv_as_slack=False, pf_variable_p_loads='plini', pf_variable_p_gen='pgini', flag_graphics='GPS', tap_opt='nntap', export_controller=True, handle_us="Deactivate", is_unbalanced=False): """ Args: prj_name: Name (”Project”), full qualified name (”Project.IntPrj”) or full qualified path (”nUsernProject.IntPrj”) of a project. path_dst: Destination for the export of .p file (full file path) pv_as_slack: whether "PV" nodes are imported as "Slack" nodes pf_variable_p_loads: PowerFactory variable for generators: "plini", "plini_a", "m:P:bus1" pf_variable_p_gen: PowerFactory variable for generators: "pgini", "pgini_a", "m:P:bus1" flag_graphics: whether geodata comes from graphic objects (*.IntGrf) or GPS tap_opt: PowerFactory variable for tap position: "nntap" or "c:nntap" export_controller: whether to create and export controllers handle_us (str, "Deactivate"): What to do with unsupplied buses -> Can be "Deactivate", "Drop" or "Nothing" Returns: pandapower network "net" and controller, saves pp-network as .p file at path_dst """ logger.debug('started') echo_off(app) user = app.GetCurrentUser() logger.debug('user: %s' % user) res = app.ActivateProject(prj_name) if res == 1: raise RuntimeError('Project %s could not be found or activated' % prj_name) prj = app.GetActiveProject() logger.info('gathering network elements') dict_net = create_network_dict(app, flag_graphics) pf_load_flow_failed = run_load_flow(app) logger.info('exporting network to pandapower') app.SetAttributeModeInternal(1) net = from_pf(dict_net=dict_net, pv_as_slack=pv_as_slack, pf_variable_p_loads=pf_variable_p_loads, pf_variable_p_gen=pf_variable_p_gen, flag_graphics=flag_graphics, tap_opt=tap_opt, export_controller=export_controller, handle_us=handle_us, is_unbalanced=is_unbalanced) # save a flag, whether the PowerFactory load flow failed app.SetAttributeModeInternal(0) net["pf_converged"] = not pf_load_flow_failed logger.info(net) prj.Deactivate() echo_on(app) if path_dst is not None: pp.to_json(net, path_dst) logger.info('saved net as %s', path_dst) return net
GRID_NAME = "14nodes" grid_path = f"grid\\{GRID_NAME}\\{GRID_NAME}.json" data_path = f"data\\{GRID_NAME}" # read infos with open('config.yaml') as file: d = yaml.load(file) load_fluc = d['LOAD_FLUCTUATION'] if load_fluc: load_fluc_bot = d['LOAD_FLUCTUATION_BOTTOM'] load_fluc_top = d['LOAD_FLUCTUATION_TOP'] net = pp.from_json(grid_path) # generating cases for num in range(d['CASE_NUM']): print(num) # set network's deepcopy net_copy = copy.deepcopy(net) # load_fluc = False if load_fluc: # creatifng new load values loads = net_copy['load']['p_mw'] ratios = np.random.random_sample(size=loads.shape[0]) ratios = load_fluc_bot + ratios * (load_fluc_top - load_fluc_bot) net_copy['load']['p_mw'] = loads * ratios net_copy_path = f"{data_path}\\{num}.json" pp.to_json(net_copy, net_copy_path)
def test_type_casting_json(net_in, tempdir): filename = os.path.join(tempdir, "testfile.json") net_in.sn_kva = 1000 pp.to_json(net_in, filename) net = pp.from_json(filename) assert_net_equal(net_in, net)
def _aux_test(self, pn_net): with tempfile.TemporaryDirectory() as path: case_name = os.path.join(path, "this_case.json") pp.to_json(pn_net, case_name) real_init_file = pp.from_json(case_name) backend = LightSimBackend() with warnings.catch_warnings(): warnings.filterwarnings("ignore") backend.load_grid(case_name) nb_sub = backend.n_sub pp_net = backend.init_pp_backend._grid # first i deactivate all slack bus in pp that are connected but not handled in ls pp_net.ext_grid["in_service"].loc[:] = False pp_net.ext_grid["in_service"].iloc[0] = True conv = backend.runpf() conv_pp = backend.init_pp_backend.runpf() assert conv_pp, "Error: pandapower do not converge, impossible to perform the necessary checks" assert conv, "Error: lightsim do not converge" por_pp, qor_pp, vor_pp, aor_pp = copy.deepcopy( backend.init_pp_backend.lines_or_info()) pex_pp, qex_pp, vex_pp, aex_pp = copy.deepcopy( backend.init_pp_backend.lines_ex_info()) # I- Check for divergence and equality of flows" por_ls, qor_ls, vor_ls, aor_ls = backend.lines_or_info() max_mis = np.max(np.abs(por_ls - por_pp)) assert max_mis <= self.tol, f"Error: por do not match, maximum absolute error is {max_mis:.5f} MW" max_mis = np.max(np.abs(qor_ls - qor_pp)) assert max_mis <= self.tol, f"Error: qor do not match, maximum absolute error is {max_mis:.5f} MVAr" max_mis = np.max(np.abs(vor_ls - vor_pp)) assert max_mis <= self.tol, f"Error: vor do not match, maximum absolute error is {max_mis:.5f} kV" max_mis = np.max(np.abs(aor_ls - aor_pp)) assert max_mis <= self.tol, f"Error: aor do not match, maximum absolute error is {max_mis:.5f} A" # "II - Check for possible solver issues" with warnings.catch_warnings(): warnings.filterwarnings("ignore") pp.runpp(backend.init_pp_backend._grid, v_debug=True) v_tmp = backend.init_pp_backend._grid.res_bus[ "vm_pu"].values[:nb_sub] + 0j v_tmp *= np.exp( 1j * np.pi / 180. * backend.init_pp_backend._grid.res_bus["va_degree"].values[:nb_sub]) v_tmp = np.concatenate((v_tmp, v_tmp)) backend._grid.ac_pf(v_tmp, 1000, 1e-5) Y_pp = backend.init_pp_backend._grid._ppc["internal"]["Ybus"] Sbus = backend.init_pp_backend._grid._ppc["internal"]["Sbus"] pv_ = backend.init_pp_backend._grid._ppc["internal"]["pv"] pq_ = backend.init_pp_backend._grid._ppc["internal"]["pq"] max_iter = 10 tol_this = 1e-8 All_Vms = backend.init_pp_backend._grid._ppc["internal"]["Vm_it"] AllVas = backend.init_pp_backend._grid._ppc["internal"]["Va_it"] for index_V in range(All_Vms.shape[1] - 1, -1, -1): nb_iter = All_Vms.shape[1] - 1 # i check from easiest to hardest, so from the last iteartion of pandapower to the first iteration of pandapower # take the same V as pandapower V_init = All_Vms[:, index_V] * (np.cos(AllVas[:, index_V]) + 1j * np.sin(AllVas[:, index_V])) # V_init *= np.exp(1j * AllVas[:, 0]) V_init_ref = copy.deepcopy(V_init) solver = ClassSolver() solver.solve(scipy.sparse.csc_matrix(Y_pp), V_init, Sbus, pv_, pq_, max_iter, tol_this) time_for_nr = solver.get_timers()[3] if TIMER_INFO: print( f"\t Info: Time to perform {nb_iter - index_V} NR iterations for a grid with {nb_sub} " f"buses: {1000. * time_for_nr:.2f}ms") error_va = np.abs( solver.get_Va() - np.angle(backend.init_pp_backend._grid._ppc["internal"]["V"])) assert np.max(error_va) <= self.tol, f"Error: VA do not match for iteration {index_V}, maximum absolute " \ f"error is {np.max(error_va):.5f} rad" error_vm = np.abs( np.abs(solver.get_Vm() - np.abs( backend.init_pp_backend._grid._ppc["internal"]["V"]))) assert np.max(error_vm) <= self.tol, f"\t Error: VM do not match for iteration {index_V}, maximum absolute " \ f"error is {np.max(error_vm):.5f} pu" solver.reset() if TIMER_INFO: print("") # 'III - Check the data conversion' pp_vect_converter = backend.init_pp_backend._grid._pd2ppc_lookups[ "bus"][:nb_sub] pp_net = backend.init_pp_backend._grid # 1) Checking Sbus conversion Sbus_pp = backend.init_pp_backend._grid._ppc["internal"]["Sbus"] Sbus_pp_right_order = Sbus_pp[pp_vect_converter] Sbus_me = backend._grid.get_Sbus() error_p = np.abs(np.real(Sbus_me) - np.real(Sbus_pp_right_order)) assert np.max(error_p) <= self.tol, f"\t Error: P do not match for Sbus, maximum absolute error is " \ f"{np.max(error_p):.5f} MW, \t Error: significative difference for bus " \ f"index (lightsim): {np.where(error_p > self.tol)[0]}" error_q = np.abs(np.imag(Sbus_me) - np.imag(Sbus_pp_right_order)) assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Sbus, maximum absolute error is " \ f"{np.max(error_q):.5f} MVAr, \t Error: significative difference for bus " \ f"index (lightsim): {np.where(error_q > self.tol)[0]}" # 2) Checking Ybus conversion" Y_me = backend._grid.get_Ybus() Y_pp = backend.init_pp_backend._grid._ppc["internal"]["Ybus"] Y_pp_right_order = Y_pp[pp_vect_converter.reshape(nb_sub, 1), pp_vect_converter.reshape(1, nb_sub)] error_p = np.abs(np.real(Y_me) - np.real(Y_pp_right_order)) assert np.max(error_p) <= self.tol, f"Error: P do not match for Ybus, maximum absolute error " \ f"is {np.max(error_p):.5f}" error_q = np.abs(np.imag(Y_me) - np.imag(Y_pp_right_order)) assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Ybus, maximum absolute error is " \ f"{np.max(error_q):.5f}" # "IV - Check for the initialization (dc powerflow)" # 1) check that the results are same for dc lightsim and dc pandapower Vinit = np.ones(backend.nb_bus_total, dtype=np.complex_) * pp_net["_options"]["init_vm_pu"] backend._grid.deactivate_result_computation() Vdc = backend._grid.dc_pf(Vinit, max_iter, tol_this) backend._grid.reactivate_result_computation() Ydc_me = backend._grid.get_Ybus() Sdc_me = backend._grid.get_Sbus() assert np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])) <= 100.*self.tol,\ f"\t Error for the DC approximation: resulting voltages are different " \ f"{np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])):.5f}pu" if np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])) >= self.tol: warnings.warn( "\t Warning: maximum difference after DC approximation is " "{np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])):.5f} which is higher than " "the tolerance (this is just a warning because we noticed this could happen even if the " "results match perfectly. Probably some conversion issue with complex number and " "radian / degree.") # "2) check that the Sbus vector is same for PP and lightisim in DC" from pandapower.pd2ppc import _pd2ppc from pandapower.pf.run_newton_raphson_pf import _get_pf_variables_from_ppci from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_X, TAP, SHIFT, BR_STATUS from pandapower.pypower.idx_bus import VA, GS from pandapower.pypower.makeBdc import makeBdc from pandapower.pypower.makeSbus import makeSbus pp_net._pd2ppc_lookups = { "bus": np.array([], dtype=int), "ext_grid": np.array([], dtype=int), "gen": np.array([], dtype=int), "branch": np.array([], dtype=int) } # convert pandapower net to ppc ppc, ppci = _pd2ppc(pp_net) baseMVA, bus, gen, branch, ref, pv, pq, on, gbus, _, refgen = _get_pf_variables_from_ppci( ppci) Va0 = bus[:, VA] * (np.pi / 180.) B, Bf, Pbusinj, Pfinj = makeBdc(bus, branch) Pbus = makeSbus(baseMVA, bus, gen) - Pbusinj - bus[:, GS] / baseMVA Pbus_pp_ro = Pbus[pp_vect_converter] error_p = np.abs(np.real(Sdc_me) - np.real(Pbus_pp_ro)) test_ok = True #### pandapower DC algo (yet another one) Va = copy.deepcopy(Va0) pvpq = np.r_[pv, pq] pvpq_matrix = B[pvpq.T, :].tocsc()[:, pvpq] ref_matrix = np.transpose(Pbus[pvpq] - B[pvpq.T, :].tocsc()[:, ref] * Va0[ref]) Va[pvpq] = np.real(scipy.sparse.linalg.spsolve(pvpq_matrix, ref_matrix)) #### assert np.max(error_p) <= self.tol, f"\t Error: P do not match for Sbus (dc), maximum absolute error is " \ f"{np.max(error_p):.5f} MW, \nError: significative difference for bus " \ f"index (lightsim): {np.where(error_p > self.tol)[0]}" error_q = np.abs(np.imag(Sdc_me) - np.imag(Pbus_pp_ro)) assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Sbus (dc), maximum absolute error is " \ f"{np.max(error_q):.5f} MVAr, \n\t Error: significative difference for " \ f"bus index (lightsim): {np.where(error_q > self.tol)[0]}" # "3) check that the Ybus matrix is same for PP and lightisim in DC" with warnings.catch_warnings(): warnings.filterwarnings("ignore") pp.rundcpp(pp_net) Ydc_pp = backend.init_pp_backend._grid._ppc["internal"]["Bbus"] Ydc_pp_right_order = Ydc_pp[pp_vect_converter.reshape(nb_sub, 1), pp_vect_converter.reshape(1, nb_sub)] error_p = np.abs(np.real(Ydc_me) - np.real(Ydc_pp_right_order)) assert np.max(error_p) <= self.tol, f"Error: P do not match for Ybus (dc mode), maximum absolute error " \ f"is {np.max(error_p):.5f}" error_q = np.abs(np.imag(Ydc_me) - np.imag(Ydc_pp_right_order)) assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Ybus (dc mdoe), maximum absolute error " \ f"is {np.max(error_q):.5f}" # "3) check that lightsim ac pf init with pp dc pf give same results (than pp)" Vinit = np.ones(backend.nb_bus_total, dtype=np.complex_) * pp_net["_options"]["init_vm_pu"] Vinit[:nb_sub] = V_init_ref[pp_vect_converter] conv = backend._grid.ac_pf(Vinit, max_iter, tol_this) assert conv.shape[ 0] > 0, "\t Error: the lightsim diverge when initialized with pandapower Vinit_dc" lpor, lqor, lvor, laor = backend._grid.get_lineor_res() tpor, tqor, tvor, taor = backend._grid.get_trafohv_res() tpex, tqex, tvex, taex = backend._grid.get_trafolv_res() nb_trafo = tpor.shape[0] nb_powerline = lpor.shape[0] p_or_me2 = np.concatenate((lpor, tpor)) q_or_me2 = np.concatenate((lqor, tqor)) v_or_me2 = np.concatenate((lvor, tvor)) a_or_me2 = 1000. * np.concatenate((laor, taor)) test_ok = True # pdb.set_trace() max_mis = np.max(np.abs(p_or_me2 - por_pp)) assert np.max( error_q ) <= self.tol, f"\t Error: por do not match, maximum absolute error is {max_mis:.5f} MW" max_mis = np.max(np.abs(q_or_me2 - qor_pp)) assert np.max( error_q ) <= self.tol, f"\t Error: qor do not match, maximum absolute error is {max_mis:.5f} MVAr" max_mis = np.max(np.abs(v_or_me2 - vor_pp)) assert np.max( error_q ) <= self.tol, f"\t Error: vor do not match, maximum absolute error is {max_mis:.5f} kV" max_mis = np.max(np.abs(a_or_me2 - aor_pp)) assert np.max( error_q ) <= self.tol, f"\t Error: aor do not match, maximum absolute error is {max_mis:.5f} A" # "V - Check trafo proper conversion to r,x, b" from lightsim2grid_cpp import GridModel, PandaPowerConverter, SolverType from pandapower.build_branch import _calc_branch_values_from_trafo_df, get_trafo_values from pandapower.build_branch import _calc_nominal_ratio_from_dataframe, _calc_r_x_y_from_dataframe from pandapower.build_branch import _calc_tap_from_dataframe, BASE_KV, _calc_r_x_from_dataframe # my trafo parameters converter = PandaPowerConverter() converter.set_sn_mva(pp_net.sn_mva) converter.set_f_hz(pp_net.f_hz) tap_neutral = 1.0 * pp_net.trafo["tap_neutral"].values tap_neutral[~np.isfinite(tap_neutral)] = 0. if np.any(tap_neutral != 0.): raise RuntimeError( "lightsim converter supposes that tap_neutral is 0 for the transformers" ) tap_step_pct = 1.0 * pp_net.trafo["tap_step_percent"].values tap_step_pct[~np.isfinite(tap_step_pct)] = 0. tap_pos = 1.0 * pp_net.trafo["tap_pos"].values tap_pos[~np.isfinite(tap_pos)] = 0. shift_ = 1.0 * pp_net.trafo["shift_degree"].values shift_[~np.isfinite(shift_)] = 0. is_tap_hv_side = pp_net.trafo["tap_side"].values == "hv" is_tap_hv_side[~np.isfinite(is_tap_hv_side)] = True if np.any(pp_net.trafo["tap_phase_shifter"].values): raise RuntimeError( "ideal phase shifter are not modeled. Please remove all trafo with " "pp_net.trafo[\"tap_phase_shifter\"] set to True.") tap_angles_ = 1.0 * pp_net.trafo["tap_step_degree"].values tap_angles_[~np.isfinite(tap_angles_)] = 0. tap_angles_ = np.deg2rad(tap_angles_) trafo_r, trafo_x, trafo_b = \ converter.get_trafo_param(tap_step_pct, tap_pos, tap_angles_, # in radian ! is_tap_hv_side, pp_net.bus.loc[pp_net.trafo["hv_bus"]]["vn_kv"], pp_net.bus.loc[pp_net.trafo["lv_bus"]]["vn_kv"], pp_net.trafo["vk_percent"].values, pp_net.trafo["vkr_percent"].values, pp_net.trafo["sn_mva"].values, pp_net.trafo["pfe_kw"].values, pp_net.trafo["i0_percent"].values, ) # pandapower trafo parameters ppc = copy.deepcopy(pp_net._ppc) bus_lookup = pp_net["_pd2ppc_lookups"]["bus"] trafo_df = pp_net["trafo"] lv_bus = get_trafo_values(trafo_df, "lv_bus") vn_lv = ppc["bus"][bus_lookup[lv_bus], BASE_KV] vn_trafo_hv, vn_trafo_lv, shift_pp = _calc_tap_from_dataframe( pp_net, trafo_df) ratio = _calc_nominal_ratio_from_dataframe(ppc, trafo_df, vn_trafo_hv, vn_trafo_lv, bus_lookup) r_t, x_t, b_t = _calc_r_x_y_from_dataframe(pp_net, trafo_df, vn_trafo_lv, vn_lv, pp_net.sn_mva) # check where there are mismatch if any val_r_pp = r_t val_r_me = trafo_r all_equals_r = np.abs(val_r_pp - val_r_me) <= self.tol if not np.all(all_equals_r): test_ok = False print( f"\t Error: some trafo resistance are not equal, max error: {np.max(np.abs(val_r_pp - val_r_me)):.5f}" ) val_x_pp = x_t val_x_me = trafo_x all_equals_x = np.abs(val_x_pp - val_x_me) <= self.tol assert np.all(all_equals_x), f"\t Error: some trafo x are not equal, max error: " \ f"{np.max(np.abs(val_x_pp - val_x_me)):.5f}" val_ib_pp = np.imag(b_t) val_ib_me = np.imag(trafo_b) all_equals_imag_b = np.abs(val_ib_pp - val_ib_me) <= self.tol assert np.all(all_equals_imag_b), f"\t Error: some trafo (imag) b are not equal, max error: " \ f"{np.max(np.abs(val_ib_pp - val_ib_me)):.5f}" val_reb_pp = np.real(b_t) val_reb_me = np.real(trafo_b) all_equals_real_b = np.abs(val_reb_pp - val_reb_me) <= self.tol assert np.all(all_equals_real_b), f"\t Error: some trafo (real) b are not equal, max error: " \ f"{np.max(np.abs(val_reb_pp - val_reb_me)):.5f}"