def setUp(self) -> None: with warnings.catch_warnings(): warnings.filterwarnings("ignore") self.env = grid2op.make("rte_case118_example", backend=LightSimBackend(), test=True) self.nb_bus = self.env.n_sub
def setUp(self) -> None: with warnings.catch_warnings(): warnings.filterwarnings("ignore") self.env = grid2op.make("l2rpn_neurips_2020_track2", backend=LightSimBackend(), test=True) self.nb_bus = self.env.n_sub
def make_env(): env_name = "l2rpn_icaps_2021" with warnings.catch_warnings(): warnings.filterwarnings("ignore") fake_env = grid2op.make(env_name, test=True) param = fake_env.parameters param.NO_OVERFLOW_DISCONNECTION = True env = grid2op.make(env_name + "_small", backend=LightSimBackend(), param=param) return env
def create_env(env, seed): environment = grid2op.make(env, reward_class=ConstantReward, backend=LightSimBackend()) # for mix in list(environment.keys()): # cr = environment[mix].get_reward_instance() # cr.addReward("redisp", RedispReward(), 0.1) # cr.addReward("economic", EconomicReward(), 0.1) # cr.addReward("overflow", CloseToOverflowReward(), 0.1) # cr.addReward("gameplay", GameplayReward(), 0.1) # cr.addReward("recolines", LinesReconnectedReward(), 0.1) # cr.addReward("l2rpn", L2RPNReward(), .6 / float(environment.n_line)) # Initialize custom rewards # cr.set_range(-1.0, 1.0) # cr.initialize(environment[mix]) environment.seed(seed) return environment
if __name__ == "__main__": # hyper-parameters DATA_PATH = '../training_data_track1' # for demo only, use your own dataset 即使用的环境 SCENARIO_PATH = '../training_data_track1/chronics' SAVE_PATH = './' LINES2ATTACK = [45, 56, 0, 9, 13, 14, 18, 23, 27, 39] NUM_EPISODES = 1000 # each scenario runs 100 times for each attack (or to say, sample 100 points) for episode in range(NUM_EPISODES): # traverse all attacks for line_to_disconnect in LINES2ATTACK: try: # if lightsim2grid is available, use it. from lightsim2grid import LightSimBackend backend = LightSimBackend() env = grid2op.make(dataset=DATA_PATH, chronics_path=SCENARIO_PATH, backend=backend) except: env = grid2op.make(dataset=DATA_PATH, chronics_path=SCENARIO_PATH) # env.chronics_handler.shuffle(shuffler=lambda x: x[np.random.choice(len(x), size=len(x), replace=False)]) #太麻烦了 env.chronics_handler.shuffle() # traverse all scenarios for chronic in range(len(os.listdir(SCENARIO_PATH))): env.reset() dst_step = episode * 72 + random.randint( 0, 72) # a random sampling every 6 hours print( '\n\n' + '*' * 50 +
def main(): args = cli() # read arguments input_dir = args.input_path output_dir = args.output_path program_dir = args.program_path submission_dir = args.submission_path config_file = args.config_in with open(config_file, "r") as f: config = json.load(f) # create output dir if not existing if not os.path.exists(output_dir): os.makedirs(output_dir) if DEBUG: print("input dir: {}".format(input_dir)) print("output dir: {}".format(output_dir)) print("program dir: {}".format(program_dir)) print("submission dir: {}".format(submission_dir)) print("input content", os.listdir(input_dir)) print("output content", os.listdir(output_dir)) print("program content", os.listdir(program_dir)) print("Content received by codalab: {}".format( sorted(os.listdir(submission_dir)))) submission_location = os.path.join(submission_dir, "submission") if not os.path.exists(submission_location): print(SUBMISSION_DIR_ERR) raise RuntimeError(SUBMISSION_DIR_ERR) # add proper directories to path sys.path.append(program_dir) sys.path.append(submission_dir) try: from submission import make_agent except Exception as exc_: print(MAKE_AGENT_ERR) print("The error was: {}".format(exc_)) raise RuntimeError(MAKE_AGENT_ERR) try: with warnings.catch_warnings(): warnings.filterwarnings("ignore") env_template = grid2op.make(input_dir, chronics_class=ChangeNothing, action_class=TopologyAndDispatchAction) except Exception as exc_: print(ENV_TEMPLATE_ERR) print("The error was: {}".format(exc_)) raise RuntimeError(ENV_TEMPLATE_ERR) try: submitted_agent = make_agent(env_template, submission_location) except Exception as exc_: print(MAKE_AGENT_ERR2) print("The error was: {}".format(exc_)) raise RuntimeError(MAKE_AGENT_ERR2) if not isinstance(submitted_agent, BaseAgent): print(BASEAGENT_ERR) raise RuntimeError(BASEAGENT_ERR) try: from submission import reward except: print(INFO_CUSTOM_REWARD) reward = RedispReward if not isinstance(reward, type): raise RuntimeError(REWARD_ERR) if not issubclass(reward, BaseReward): raise RuntimeError(REWARD_ERR2) try: from submission import other_rewards except: print(INFO_CUSTOM_OTHER) other_rewards = {} if args.key_score in other_rewards: print(KEY_OVERLOAD_WARN.format(args.key_score)) other_rewards[args.key_score] = L2RPNSandBoxScore # create the backend try: from lightsim2grid.LightSimBackend import LightSimBackend backend = LightSimBackend() except: print(BACKEND_WARN) from grid2op.Backend import PandaPowerBackend backend = PandaPowerBackend() real_env = grid2op.make(input_dir, reward_class=reward, other_rewards=other_rewards, backend=backend) runner = Runner(**real_env.get_params_for_runner(), agentClass=None, agentInstance=submitted_agent) # this is called after, so that no one can change this sequence np.random.seed(int(config["seed"])) max_int = np.iinfo(dt_int).max env_seeds = list(np.random.randint(max_int, size=int(args.nb_episode))) agent_seeds = list(np.random.randint(max_int, size=int(args.nb_episode))) path_save = os.path.abspath(output_dir) runner.run( nb_episode=args.nb_episode, path_save=path_save, max_iter=-1, env_seeds=env_seeds, agent_seeds=agent_seeds, ) real_env.close() # Generate a gif if enabled if args.gif_episode is not None: gif_input = os.path.join(output_dir) write_gif(output_dir, gif_input, args.gif_episode, args.gif_start, args.gif_end) if args.cleanup: cmds = [ "find {} -name '*.npz' | xargs -i rm -rf {}", "find {} -name 'dict_*.json' | xargs -i rm -rf {}", "find {} -name '_parameters.json' | xargs -i rm -rf {}" ] for cmd in cmds: os.system(cmd.format(output_dir, "{}")) print("Done and data saved in : \"{}\"".format(path_save))
def setUp(self) -> None: with warnings.catch_warnings(): warnings.filterwarnings("ignore") self.env = grid2op.make(backend=LightSimBackend(), test=True)
this_epi_scores = json.load(f) score_this_ep, nb_ts_survived, total_ts_tmp = \ self._compute_episode_score(ep_id, meta=this_epi_meta, other_rewards=this_epi_scores, dn_metadata=meta_data_dn, no_ov_metadata=no_ov_metadata) all_scores.append(score_this_ep) ts_survived.append(nb_ts_survived) total_ts.append(total_ts_tmp) if need_delete: dir_tmp.cleanup() return all_scores, ts_survived, total_ts if __name__ == "__main__": import grid2op from lightsim2grid import LightSimBackend from grid2op.Agent import RandomAgent, DoNothingAgent env = grid2op.make("l2rpn_case14_sandbox", backend=LightSimBackend()) nb_scenario = 16 my_score = ScoreL2RPN2020(env, nb_scenario=nb_scenario, env_seeds=[0 for _ in range(nb_scenario)], agent_seeds=[0 for _ in range(nb_scenario)]) my_agent = RandomAgent(env.action_space) my_agent = DoNothingAgent(env.action_space) print(my_score.get(my_agent))
# nb_sub = 6495 # case_name = "test_case2848rte.json" # nb_sub = 2848 # case_name = "test_case118.json" # nb_sub = 118 # case_name = "test_case14.json" # nb_sub = 14 tol = 1e-4 # results are equal if they match up to tol good_working_case = pn.case118() good_working_case = pn.case14() #### test if it works print(f"Basic check for {case_name}") real_init_file = pp.from_json(case_name) backend = LightSimBackend() backend.load_grid(case_name) 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() if not conv_pp: print( "Error: pandapower do not converge, impossible to perform the necessary checks" ) sys.exit() por_pp, qor_pp, vor_pp, aor_pp = copy.deepcopy( backend.init_pp_backend.lines_or_info())
# start the runner res = runner.run(path_save=save_path, nb_episode=nb_episode, nb_process=nb_process, max_iter=max_steps, pbar=False) # Print summary print("Evaluation summary:") for _, chron_name, cum_reward, nb_time_step, max_ts in res: msg_tmp = "\tFor chronics located at {}\n".format(chron_name) msg_tmp += "\t\t - cumulative reward: {:.6f}\n".format(cum_reward) msg_tmp += "\t\t - number of time steps completed: {:.0f} / {:.0f}".format( nb_time_step, max_ts) print(msg_tmp) if __name__ == "__main__": env = grid2op.make("data/input_data_local", backend=LightSimBackend()) evaluate(env, model_name="beu", save_path="eval_results", logs_path="logs-train", nb_episode=24, nb_process=1, max_steps=2016, verbose=True, save_gif="eval_results")
env_name = ENV_CASE[args.case] env_path = os.path.join(DATA_DIR, env_name) chronics_path = os.path.join(env_path, 'chronics') train_chronics, valid_chronics, test_chronics = DATA_SPLIT[args.case] dn_json_path = os.path.join(env_path, 'json') # select chronics dn_ffw = read_ffw_json(dn_json_path, train_chronics + valid_chronics, args.case) ep_infos = {} if os.path.exists(dn_json_path): for i in list(set(train_chronics+valid_chronics)): with open(os.path.join(dn_json_path, f'{i}.json'), 'r', encoding='utf-8') as f: ep_infos[i] = json.load(f) env = grid2op.make(env_path, test=True, reward_class=L2RPNSandBoxScore, backend=LightSimBackend(), other_rewards={'loss': LossReward}) test_env = grid2op.make(env_path, test=True, reward_class=L2RPNSandBoxScore, backend=LightSimBackend(), other_rewards={'loss': LossReward}) env.deactivate_forecast() test_env.deactivate_forecast() env.seed(args.seed) test_env.parameters.NB_TIMESTEP_OVERFLOW_ALLOWED = env.parameters.NB_TIMESTEP_OVERFLOW_ALLOWED = 3 test_env.parameters.NB_TIMESTEP_RECONNECTION = env.parameters.NB_TIMESTEP_RECONNECTION = 12 test_env.parameters.NB_TIMESTEP_COOLDOWN_LINE = env.parameters.NB_TIMESTEP_COOLDOWN_LINE = 3 test_env.parameters.NB_TIMESTEP_COOLDOWN_SUB = env.parameters.NB_TIMESTEP_COOLDOWN_SUB = 3 test_env.parameters.HARD_OVERFLOW_THRESHOLD = env.parameters.HARD_OVERFLOW_THRESHOLD = 200.0 test_env.seed(59) chronic_num = len(test_chronics) print(env.parameters.__dict__)
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}"