diff --git a/lightsim2grid/gridmodel/from_pypowsybl.py b/lightsim2grid/gridmodel/from_pypowsybl.py index b82a269..ef7a856 100644 --- a/lightsim2grid/gridmodel/from_pypowsybl.py +++ b/lightsim2grid/gridmodel/from_pypowsybl.py @@ -38,7 +38,7 @@ def init(net : pypo.network, slack_bus_id: int = None, sn_mva = 100., sort_index=True, - f_hz = 50., + f_hz = 50., # unused only_main_component=True): model = GridModel() # model.set_f_hz(f_hz) @@ -89,8 +89,8 @@ def init(net : pypo.network, for gen_id, is_disco in enumerate(gen_disco): if is_disco: model.deactivate_gen(gen_id) - model.set_gen_names(df_gen.index) - + model.set_gen_names(df_gen.index) + # for loads if sort_index: df_load = net.get_loads().sort_index() @@ -104,7 +104,7 @@ def init(net : pypo.network, for load_id, is_disco in enumerate(load_disco): if is_disco: model.deactivate_load(load_id) - model.set_load_names(df_load.index) + model.set_load_names(df_load.index) # for lines if sort_index: @@ -148,7 +148,7 @@ def init(net : pypo.network, for line_id, (is_or_disc, is_ex_disc) in enumerate(zip(lor_disco, lex_disco)): if is_or_disc or is_ex_disc: model.deactivate_powerline(line_id) - model.set_line_names(df_line.index) + model.set_line_names(df_line.index) # for trafo if sort_index: @@ -184,7 +184,7 @@ def init(net : pypo.network, for t_id, (is_or_disc, is_ex_disc) in enumerate(zip(tor_disco, tex_disco)): if is_or_disc or is_ex_disc: model.deactivate_trafo(t_id) - model.set_trafo_names(df_trafo.index) + model.set_trafo_names(df_trafo.index) # for shunt if sort_index: @@ -201,7 +201,7 @@ def init(net : pypo.network, for shunt_id, disco in enumerate(sh_disco): if disco: model.deactivate_shunt(shunt_id) - model.set_shunt_names(df_trafo.index) + model.set_shunt_names(df_trafo.index) # for hvdc (TODO not tested yet) df_dc = net.get_hvdc_lines().sort_index() @@ -228,7 +228,7 @@ def init(net : pypo.network, for hvdc_id, (is_or_disc, is_ex_disc) in enumerate(zip(hvdc_from_disco, hvdc_to_disco)): if is_or_disc or is_ex_disc: model.deactivate_hvdc(hvdc_id) - model.set_dcline_names(df_sations.index) + model.set_dcline_names(df_sations.index) # storage units (TODO not tested yet) if sort_index: @@ -243,7 +243,7 @@ def init(net : pypo.network, for batt_id, disco in enumerate(batt_disco): if disco: model.deactivate_storage(batt_id) - model.set_storage_names(df_batt.index) + model.set_storage_names(df_batt.index) # TODO dist slack if gen_slack_id is None and slack_bus_id is None: @@ -262,8 +262,8 @@ def init(net : pypo.network, raise RuntimeError(f"There is no generator connected to bus {slack_bus_id}. It cannot be the slack") for gen_id, is_slack in enumerate(gen_is_conn_slack): if is_slack: - model.add_gen_slackbus(gen_id, 1. / nb_conn) - + model.add_gen_slackbus(gen_id, 1. / nb_conn) + # TODO # sgen => regular gen (from net.get_generators()) with voltage_regulator off TODO diff --git a/lightsim2grid/lightSimBackend.py b/lightsim2grid/lightSimBackend.py index 6b068e4..cf81459 100644 --- a/lightsim2grid/lightSimBackend.py +++ b/lightsim2grid/lightSimBackend.py @@ -446,7 +446,6 @@ def make_complete_path(path, filename): raise Grid2OpException('There is no powergrid at "{}"'.format(full_path)) return full_path full_path = make_complete_path(path, filename) - grid_tmp = pypow_net.load(full_path) gen_slack_id = None if "gen_slack_id" in loader_kwargs: diff --git a/lightsim2grid/tests/test_backend_pypowsybl.py b/lightsim2grid/tests/test_backend_pypowsybl.py index bce90c2..1390698 100644 --- a/lightsim2grid/tests/test_backend_pypowsybl.py +++ b/lightsim2grid/tests/test_backend_pypowsybl.py @@ -92,7 +92,8 @@ def test_init(self): grid.ac_pf(np.ones(14, dtype=np.complex128), 10, 1e-6) def test_runpf(self): - backend = LightSimBackend(loader_method="pypowsybl", loader_kwargs=_aux_get_loader_kwargs()) + backend = LightSimBackend(loader_method="pypowsybl", + loader_kwargs=_aux_get_loader_kwargs()) self._aux_prep_backend(backend) # AC powerflow conv, exc_ = backend.runpf() diff --git a/src/GridModel.cpp b/src/GridModel.cpp index 0c13b70..edce0ec 100644 --- a/src/GridModel.cpp +++ b/src/GridModel.cpp @@ -1002,20 +1002,25 @@ void GridModel::consider_only_main_component(){ // TODO copy paste from SecurityAnalysis std::queue neighborhood; for(const auto & el : slack_buses_id) neighborhood.push(el); + if(neighborhood.empty()){ + throw std::runtime_error("There is no slack buses defined in your grid. You cannot isolate the main component."); + } std::vector visited(nb_busbars, false); + std::vector already_added(nb_busbars, false); while (true) { const Eigen::Index col_id = neighborhood.front(); + neighborhood.pop(); visited[col_id] = true; for (Eigen::SparseMatrix::InnerIterator it(graph, col_id); it; ++it) { // add in the queue all my neighbor (if the coefficient is big enough) - if(!visited[it.row()] ){ // && abs(it.value()) > 1e-8 + if(!visited[it.row()] && !already_added[it.row()]){ // && abs(it.value()) > 1e-8 neighborhood.push(it.row()); + already_added[it.row()] = true; } } if(neighborhood.empty()) break; - neighborhood.pop(); } // disconnected elements not in main component @@ -1027,7 +1032,6 @@ void GridModel::consider_only_main_component(){ storages_.disconnect_if_not_in_main_component(visited); generators_.disconnect_if_not_in_main_component(visited); dc_lines_.disconnect_if_not_in_main_component(visited); - // and finally deal with the buses init_bus_status(); } \ No newline at end of file diff --git a/src/SecurityAnalysis.cpp b/src/SecurityAnalysis.cpp index 0b9fd57..f4d5c9a 100644 --- a/src/SecurityAnalysis.cpp +++ b/src/SecurityAnalysis.cpp @@ -12,6 +12,7 @@ bool SecurityAnalysis::check_invertible(const Eigen::SparseMatrix & Ybus) const{ std::vector visited(Ybus.cols(), false); + std::vector already_added(Ybus.cols(), false); std::queue neighborhood; Eigen::Index col_id = 0; // start by node 0, why not while (true) @@ -20,8 +21,9 @@ bool SecurityAnalysis::check_invertible(const Eigen::SparseMatrix & Y for (Eigen::SparseMatrix::InnerIterator it(Ybus, col_id); it; ++it) { // add in the queue all my neighbor (if the coefficient is big enough) - if(!visited[it.row()] && abs(it.value()) > 1e-8){ + if(!visited[it.row()] && !already_added[it.row()] && abs(it.value()) > 1e-8){ neighborhood.push(it.row()); + already_added[it.row()] = true; } } if(neighborhood.empty()) break;