From c5e2b540fbc28b478808c77b1156e5143754b952 Mon Sep 17 00:00:00 2001 From: "Engr. Ahmad Furqan" <40142397+furqan463@users.noreply.github.com> Date: Sun, 24 Aug 2025 11:55:09 +0500 Subject: [PATCH 01/28] fix/ PandaPower Transformer Loading In case of trafo_loading="current", a value error is generated while calculating "ui" from "i" and "u" because "i" is (n,3) array while "u" is (n,) array. fixed it by converted "u" to (n,3) array. Moreover, for phase wise loading, since "u" is line-to-line voltage, it needs to be converted to "line-to-ground" before multiplying, moreover to calculated loading percent, phase_power is to be divided by "sn_ph" instead of "sn" where "sn_ph" = "sn" / 3. Signed-off-by: Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com> --- .../converters/pandapower_converter.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 76b4ad4a..476950c8 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2017,12 +2017,21 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements # Only derating factor used here. Sn is already being multiplied by parallel loading_multiplier = pp_input_transformers["df"] * 1e2 if self.trafo_loading == "current": - ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"] - ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"] - loading_a_percent = np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] - loading_b_percent = np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] - loading_c_percent = np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] - loading = np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1)) / pgm_input_transformers["sn"] + # ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"] + # ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"] + # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, valueError is generated during broadcost + ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1,3)) + ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1,3)) + #loading_a_percent = np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] + #loading_b_percent = np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] + #loading_c_percent = np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] + #loading = np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1)) / pgm_input_transformers["sn"] + # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) --> sqrt(3) * i * u / sn + loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] + loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] + loading_c_percent = np.sqrt(3) * np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] + # for total loading, phase wise powers are be calculated using v_n instead of v. + loading = (np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1))/np.sqrt(3)) / pgm_input_transformers["sn"] elif self.trafo_loading == "power": loading_a_percent = ( np.maximum( From 9902db6ce7420248c0cf2281b1b89a965454bc85 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 25 Aug 2025 09:25:31 +0200 Subject: [PATCH 02/28] Apply suggestion from @mgovers Signed-off-by: Martijn Govers Signed-off-by: Martijn Govers --- src/power_grid_model_io/converters/pandapower_converter.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 476950c8..9b636475 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2022,10 +2022,6 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, valueError is generated during broadcost ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1,3)) ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1,3)) - #loading_a_percent = np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] - #loading_b_percent = np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] - #loading_c_percent = np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] - #loading = np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1)) / pgm_input_transformers["sn"] # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) --> sqrt(3) * i * u / sn loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] From daa8a57b5a5681c6ecbc9d08366ba2a49cd0260a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 25 Aug 2025 09:25:51 +0200 Subject: [PATCH 03/28] Apply suggestion from @mgovers Signed-off-by: Martijn Govers Signed-off-by: Martijn Govers --- src/power_grid_model_io/converters/pandapower_converter.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 9b636475..b808af2b 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2017,8 +2017,6 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements # Only derating factor used here. Sn is already being multiplied by parallel loading_multiplier = pp_input_transformers["df"] * 1e2 if self.trafo_loading == "current": - # ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"] - # ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"] # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, valueError is generated during broadcost ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1,3)) ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1,3)) From a1c585aee74fce050ffed0b261a280768a5908e3 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 25 Aug 2025 09:32:50 +0200 Subject: [PATCH 04/28] reformat Signed-off-by: Martijn Govers --- .../converters/pandapower_converter.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index b808af2b..92e6388b 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2018,14 +2018,16 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements loading_multiplier = pp_input_transformers["df"] * 1e2 if self.trafo_loading == "current": # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, valueError is generated during broadcost - ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1,3)) - ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1,3)) + ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1, 3)) + ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1, 3)) # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) --> sqrt(3) * i * u / sn loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] loading_c_percent = np.sqrt(3) * np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] # for total loading, phase wise powers are be calculated using v_n instead of v. - loading = (np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1))/np.sqrt(3)) / pgm_input_transformers["sn"] + loading = ( + np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1)) / np.sqrt(3) + ) / pgm_input_transformers["sn"] elif self.trafo_loading == "power": loading_a_percent = ( np.maximum( From 97a55a94c4ed5b0b5c5da4ec625491195d99a8b0 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 25 Aug 2025 09:34:21 +0200 Subject: [PATCH 05/28] fix typos Signed-off-by: Martijn Govers --- src/power_grid_model_io/converters/pandapower_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 92e6388b..ee41762d 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2017,7 +2017,7 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements # Only derating factor used here. Sn is already being multiplied by parallel loading_multiplier = pp_input_transformers["df"] * 1e2 if self.trafo_loading == "current": - # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, valueError is generated during broadcost + # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, ValueError is generated during broadcast ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1, 3)) ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1, 3)) # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) --> sqrt(3) * i * u / sn From 9929f27e35980107ac2206611b686ede827ba75c Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 25 Aug 2025 09:35:38 +0200 Subject: [PATCH 06/28] fix line lengths Signed-off-by: Martijn Govers --- src/power_grid_model_io/converters/pandapower_converter.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index ee41762d..a223aecd 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2017,10 +2017,12 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements # Only derating factor used here. Sn is already being multiplied by parallel loading_multiplier = pp_input_transformers["df"] * 1e2 if self.trafo_loading == "current": - # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, ValueError is generated during broadcast + # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, ValueError is generated + # during broadcast ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1, 3)) ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1, 3)) - # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) --> sqrt(3) * i * u / sn + # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) + # ==> sqrt(3) * i * u / sn loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] loading_c_percent = np.sqrt(3) * np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] From e43a8f6aa56e1870fb1c7f92ce5fecdc7a9c1c34 Mon Sep 17 00:00:00 2001 From: "Engr. Ahmad Furqan" <40142397+furqan463@users.noreply.github.com> Date: Mon, 25 Aug 2025 16:05:18 +0500 Subject: [PATCH 07/28] Removed tiling, using array broadcast instead. Signed-off-by: Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com> --- src/power_grid_model_io/converters/pandapower_converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index a223aecd..87446705 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2019,8 +2019,8 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements if self.trafo_loading == "current": # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, ValueError is generated # during broadcast - ui_from = pgm_output_transformers["i_from"] * np.tile(pgm_input_transformers["u1"][:, None], (1, 3)) - ui_to = pgm_output_transformers["i_to"] * np.tile(pgm_input_transformers["u2"][:, None], (1, 3)) + ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"][:, None] + ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"][:, None] # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) # ==> sqrt(3) * i * u / sn loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] From ebb154a8c69d2bab48764e527aaa4165fefc3210 Mon Sep 17 00:00:00 2001 From: "Engr. Ahmad Furqan" <40142397+furqan463@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:16:43 +0500 Subject: [PATCH 08/28] Total Loading is max of phase wise loading Aligned with PandaPower code. Signed-off-by: Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com> --- src/power_grid_model_io/converters/pandapower_converter.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 87446705..7717f95c 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2026,10 +2026,8 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] loading_c_percent = np.sqrt(3) * np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] - # for total loading, phase wise powers are be calculated using v_n instead of v. - loading = ( - np.maximum(np.sum(ui_from, axis=1), np.sum(ui_to, axis=1)) / np.sqrt(3) - ) / pgm_input_transformers["sn"] + # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. + loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) elif self.trafo_loading == "power": loading_a_percent = ( np.maximum( From 1954ccd797443f2eec0b423ff0aeb03585567547 Mon Sep 17 00:00:00 2001 From: "Engr. Ahmad Furqan" <40142397+furqan463@users.noreply.github.com> Date: Mon, 25 Aug 2025 23:32:12 +0500 Subject: [PATCH 09/28] Highlight a bug in Pandapower_Converter validation test Signed-off-by: Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com> --- .../validation/converters/test_pandapower_converter_output.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index 808d5df8..92cf9667 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -163,7 +163,9 @@ def test_attributes(output_data: Tuple[PandaPowerData, PandaPowerData], componen # Assert pd.testing.assert_series_equal(actual_values, expected_values, atol=5e-4, rtol=1e-4) - +# The following test only works for those components where valid data is returned by +# load_and_convert_pgm_data_3ph. since this is failing for trafo_output_3ph (returning +# from first "if", this function's output is not being tested currently. @pytest.mark.parametrize(("component", "attribute"), component_attributes_df(load_and_convert_pgm_data_3ph())) def test_attributes_3ph(output_data_3ph: Tuple[PandaPowerData, PandaPowerData], component: str, attribute: str): """ From e82714c21f2ba6be88427ef07f4ec87bcec90b1b Mon Sep 17 00:00:00 2001 From: furqan463 Date: Tue, 26 Aug 2025 20:10:04 +0500 Subject: [PATCH 10/28] PandaPower_Converter: Fix Transformer Loading Calculation by current and power and updating of validation tests Signed-off-by: furqan463 --- .../converters/pandapower_converter.py | 9 +++++---- .../converters/test_pandapower_converter_output.py | 7 +++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 7717f95c..b38884d9 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2034,23 +2034,24 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements pgm_output_transformers["s_from"][:, 0], pgm_output_transformers["s_to"][:, 0], ) - / pgm_output_transformers["s_n"] + / (pgm_input_transformers["sn"] / 3) ) loading_b_percent = ( np.maximum( pgm_output_transformers["s_from"][:, 1], pgm_output_transformers["s_to"][:, 1], ) - / pgm_output_transformers["s_n"] + / (pgm_input_transformers["sn"] / 3) ) loading_c_percent = ( np.maximum( pgm_output_transformers["s_from"][:, 2], pgm_output_transformers["s_to"][:, 2], ) - / pgm_output_transformers["s_n"] + / (pgm_input_transformers["sn"] / 3) ) - loading = pgm_output_transformers["loading"] + # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. + loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) else: raise ValueError(f"Invalid transformer loading type: {str(self.trafo_loading)}") diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index 92cf9667..0305c4f2 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -52,8 +52,11 @@ def load_and_convert_pgm_data_3ph() -> PandaPowerData: Load and convert the power_grid_model results """ data, extra_info = load_json_single_dataset(PGM_ASYM_OUTPUT_FILE, data_type="asym_output") - converter = PandaPowerConverter() - return converter.convert(data=data, extra_info=extra_info) + # trafo_loading = "power", as validation data is based on power based loading + converter = PandaPowerConverter(trafo_loading="power") + # if pp_input_data is not present in converter, some convert functions may fail. + converter.load_input_data(load_validation_data_3ph(), make_extra_info=False) + return converter.convert(data=data) @lru_cache From b0fa174a1245099869e9b3eefcc9e02977ab5ccd Mon Sep 17 00:00:00 2001 From: "Engr. Ahmad Furqan" <40142397+furqan463@users.noreply.github.com> Date: Tue, 26 Aug 2025 20:59:28 +0500 Subject: [PATCH 11/28] PandaPower_Converter: Fix Transformer Loading Calculation by current and power and updating of validation tests DCO Remediation Commit for Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com> I, Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 0e3f83884522868cf083428a27ef1265c79174de Signed-off-by: Engr. Ahmad Furqan <40142397+furqan463@users.noreply.github.com> From fe83bf2f86ce318635879daca9dba522c8ff8794 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Sep 2025 14:02:14 +0200 Subject: [PATCH 12/28] add new validation test + cleanup Signed-off-by: Martijn Govers --- .../converters/pandapower_converter.py | 41 ++++------ tests/data/pandapower/pp_validation.py | 45 +++++++++++ .../test_pandapower_converter_output.py | 5 +- .../test_pandapower_converter_output.py | 75 ++++++++++++++++++- 4 files changed, 136 insertions(+), 30 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index b38884d9..a617636a 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2026,35 +2026,26 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] loading_c_percent = np.sqrt(3) * np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] - # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. - loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) elif self.trafo_loading == "power": - loading_a_percent = ( - np.maximum( - pgm_output_transformers["s_from"][:, 0], - pgm_output_transformers["s_to"][:, 0], - ) - / (pgm_input_transformers["sn"] / 3) - ) - loading_b_percent = ( - np.maximum( - pgm_output_transformers["s_from"][:, 1], - pgm_output_transformers["s_to"][:, 1], - ) - / (pgm_input_transformers["sn"] / 3) - ) - loading_c_percent = ( - np.maximum( - pgm_output_transformers["s_from"][:, 2], - pgm_output_transformers["s_to"][:, 2], - ) - / (pgm_input_transformers["sn"] / 3) - ) - # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. - loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) + loading_a_percent = np.maximum( + pgm_output_transformers["s_from"][:, 0], + pgm_output_transformers["s_to"][:, 0], + ) / (pgm_input_transformers["sn"] / 3) + loading_b_percent = np.maximum( + pgm_output_transformers["s_from"][:, 1], + pgm_output_transformers["s_to"][:, 1], + ) / (pgm_input_transformers["sn"] / 3) + loading_c_percent = np.maximum( + pgm_output_transformers["s_from"][:, 2], + pgm_output_transformers["s_to"][:, 2], + ) / (pgm_input_transformers["sn"] / 3) else: raise ValueError(f"Invalid transformer loading type: {str(self.trafo_loading)}") + # PGM returns the average loading over the cable, but PandaPower returns the maximum of the per-phase loading. + # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. + loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) + pp_output_trafos_3ph = pd.DataFrame( columns=[ "p_a_hv_mw", diff --git a/tests/data/pandapower/pp_validation.py b/tests/data/pandapower/pp_validation.py index 4f6abf24..12e26f4b 100644 --- a/tests/data/pandapower/pp_validation.py +++ b/tests/data/pandapower/pp_validation.py @@ -192,3 +192,48 @@ def pp_net_3ph() -> pp.pandapowerNet: # ) return net + + +def pp_net_3ph_minimal_trafo(): + net = pp.create_empty_network("test", f_hz=50) + pp.create_bus(net, 11, "source") + pp.create_bus(net, 11, "TF_HT") + pp.create_bus(net, 0.4, "TF_LT") + + pp.create_ext_grid(net, 0, 1.0, 0, s_sc_max_mva=100, rx_max=0.1, x0x_max=1, r0x0_max=0.1) + pp.create_line_from_parameters( + net, + 0, + 1, + 2, + 0.33, + 0.34, + 0.001, + 600, + r0_ohm_per_km=0.66, + x0_ohm_per_km=0.65, + c0_nf_per_km=0.001, + g_us_per_km=0, + g0_us_per_km=0, + ) + pp.create_transformer_from_parameters( + net, + 1, + 2, + 1, + 11, + 0.415, + 0, + 4, + 0, + 0.01, + -30, + vector_group="Dyn", + vk0_percent=4, + vkr0_percent=0, + mag0_percent=100, + mag0_rx=0, + si0_hv_partial=0.9, + ) + pp.create_asymmetric_load(net, 2, 0.2, 0.19, 0.195, 0.05, 0.045, 0.035, 0, type="wye") + return net diff --git a/tests/unit/converters/test_pandapower_converter_output.py b/tests/unit/converters/test_pandapower_converter_output.py index 336b854d..a8b452dd 100644 --- a/tests/unit/converters/test_pandapower_converter_output.py +++ b/tests/unit/converters/test_pandapower_converter_output.py @@ -1034,7 +1034,10 @@ def test_output_trafos_3ph__power(converter): converter._pp_trafos_output_3ph() # retrieval - mock_pgm_array.__getitem__.assert_any_call("loading") + assert "loading" not in mock_pgm_array.__getitem__.call_args_list, ( + "The convention for loading differs between PGM and PP and the PGM loading therefore should not be used " + "for conversion to PP." + ) # result converter.pp_output_data.__setitem__.assert_called_once_with("res_trafo_3ph", mock_pp_df.return_value) diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index 0305c4f2..4198a556 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -15,7 +15,7 @@ from power_grid_model_io.converters import PandaPowerConverter from power_grid_model_io.converters.pandapower_converter import PandaPowerData -from ...data.pandapower.pp_validation import pp_net, pp_net_3ph +from ...data.pandapower.pp_validation import pp_net, pp_net_3ph, pp_net_3ph_minimal_trafo from ..utils import component_attributes_df, load_json_single_dataset pp = pytest.importorskip("pandapower", reason="pandapower is not installed") @@ -51,10 +51,8 @@ def load_and_convert_pgm_data_3ph() -> PandaPowerData: """ Load and convert the power_grid_model results """ - data, extra_info = load_json_single_dataset(PGM_ASYM_OUTPUT_FILE, data_type="asym_output") - # trafo_loading = "power", as validation data is based on power based loading + data, _ = load_json_single_dataset(PGM_ASYM_OUTPUT_FILE, data_type="asym_output") converter = PandaPowerConverter(trafo_loading="power") - # if pp_input_data is not present in converter, some convert functions may fail. converter.load_input_data(load_validation_data_3ph(), make_extra_info=False) return converter.convert(data=data) @@ -129,6 +127,74 @@ def test_generate_output_3ph(): # TODO: REMOVE THIS FUNCTION json_converter.save(data=output_data_asym, extra_info=extra_info) +def test_output_trafos_3ph__power__with_comparison(): + import numpy as np + + def check_result(net): + v_hv = net.trafo.vn_hv_kv + v_lv = net.trafo.vn_lv_kv + i_max_hv = np.divide(net.trafo.sn_mva, v_hv * np.sqrt(3)) * 1e3 + i_max_lv = np.divide(net.trafo.sn_mva, v_lv * np.sqrt(3)) * 1e3 + + i_a_hv = net.res_trafo_3ph.loc[:, "i_a_hv_ka"] * 1000 + i_b_hv = net.res_trafo_3ph.loc[:, "i_b_hv_ka"] * 1000 + i_c_hv = net.res_trafo_3ph.loc[:, "i_c_hv_ka"] * 1000 + + i_a_lv = net.res_trafo_3ph.loc[:, "i_a_lv_ka"] * 1000 + i_b_lv = net.res_trafo_3ph.loc[:, "i_b_lv_ka"] * 1000 + i_c_lv = net.res_trafo_3ph.loc[:, "i_c_lv_ka"] * 1000 + + np.testing.assert_allclose( + np.maximum(i_a_hv / i_max_hv, i_a_lv / i_max_lv) * 100, net.res_trafo_3ph.loading_a_percent + ) + np.testing.assert_allclose( + np.maximum(i_b_hv / i_max_hv, i_b_lv / i_max_lv) * 100, net.res_trafo_3ph.loading_b_percent + ) + np.testing.assert_allclose( + np.maximum(i_c_hv / i_max_hv, i_c_lv / i_max_lv) * 100, net.res_trafo_3ph.loading_c_percent + ) + + def compare_result(actual, expected, *, rtol): + np.testing.assert_allclose(actual.trafo.vn_hv_kv, expected.trafo.vn_hv_kv, rtol=rtol) + np.testing.assert_allclose(actual.trafo.vn_lv_kv, expected.trafo.vn_lv_kv, rtol=rtol) + np.testing.assert_allclose(actual.trafo.sn_mva, expected.trafo.sn_mva, rtol=rtol) + np.testing.assert_allclose( + actual.res_trafo_3ph.loc[:, "i_a_hv_ka"], expected.res_trafo_3ph.loc[:, "i_a_hv_ka"], rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loc[:, "i_b_hv_ka"], expected.res_trafo_3ph.loc[:, "i_b_hv_ka"], rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loc[:, "i_c_hv_ka"], expected.res_trafo_3ph.loc[:, "i_c_hv_ka"], rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loc[:, "i_a_lv_ka"], expected.res_trafo_3ph.loc[:, "i_a_lv_ka"], rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loc[:, "i_b_lv_ka"], expected.res_trafo_3ph.loc[:, "i_b_lv_ka"], rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loc[:, "i_c_lv_ka"], expected.res_trafo_3ph.loc[:, "i_c_lv_ka"], rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loading_a_percent, expected.res_trafo_3ph.loading_a_percent, rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loading_b_percent, expected.res_trafo_3ph.loading_b_percent, rtol=rtol + ) + np.testing.assert_allclose( + actual.res_trafo_3ph.loading_c_percent, expected.res_trafo_3ph.loading_c_percent, rtol=rtol + ) + + pgm_net = pp_net_3ph_minimal_trafo() + pp_net = pp_net_3ph_minimal_trafo() + pp.runpp_pgm(pgm_net, symmetric=False) + pp.runpp_3ph(pp_net) + check_result(pgm_net) + check_result(pp_net) + compare_result(pgm_net, pp_net, rtol=0.04) + + def test_output_data(output_data: Tuple[PandaPowerData, PandaPowerData]): """ Unit test to preload the expected and actual data @@ -166,6 +232,7 @@ def test_attributes(output_data: Tuple[PandaPowerData, PandaPowerData], componen # Assert pd.testing.assert_series_equal(actual_values, expected_values, atol=5e-4, rtol=1e-4) + # The following test only works for those components where valid data is returned by # load_and_convert_pgm_data_3ph. since this is failing for trafo_output_3ph (returning # from first "if", this function's output is not being tested currently. From 087a32ccefc601231382097a31410f7a441aff3c Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Sep 2025 14:10:29 +0200 Subject: [PATCH 13/28] Update src/power_grid_model_io/converters/pandapower_converter.py Signed-off-by: Martijn Govers Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Martijn Govers --- src/power_grid_model_io/converters/pandapower_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index a617636a..f57cd289 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2042,7 +2042,7 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements else: raise ValueError(f"Invalid transformer loading type: {str(self.trafo_loading)}") - # PGM returns the average loading over the cable, but PandaPower returns the maximum of the per-phase loading. + # PGM returns the average loading over the transformer, but PandaPower returns the maximum of the per-phase loading. # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) From 2fae6d09606d91025b64613e582e99afebf196df Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Sep 2025 14:12:15 +0200 Subject: [PATCH 14/28] ruff format Signed-off-by: Martijn Govers --- src/power_grid_model_io/converters/pandapower_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index f57cd289..8651bab4 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2042,7 +2042,7 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements else: raise ValueError(f"Invalid transformer loading type: {str(self.trafo_loading)}") - # PGM returns the average loading over the transformer, but PandaPower returns the maximum of the per-phase loading. + # PGM returns the average loading over the trafos, but PandaPower returns the maximum of the per-phase loading. # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) From c328ae895631bced0802ead7a35cef16505866cb Mon Sep 17 00:00:00 2001 From: furqan463 Date: Wed, 3 Sep 2025 00:34:29 +0500 Subject: [PATCH 15/28] Pandapower_Converter: corrected total 3ph_line loading with max of loading of 3 phases to align with pandapower. corrected line input producing NaN with c_nf_per_km=0, tan value should be 0 in this case Signed-off-by: furqan463 --- .../converters/pandapower_converter.py | 23 ++++++++++--------- tests/data/pandapower/pp_validation.py | 6 ++--- .../test_pandapower_converter_output.py | 9 +++++++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 8651bab4..88763233 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -422,11 +422,11 @@ def _create_pgm_input_lines(self): pgm_lines["x1"] = self._get_pp_attr("line", "x_ohm_per_km", expected_type="f8") * multiplier pgm_lines["c1"] = c_nf_per_km * length_km * parallel * 1e-9 # The formula for tan1 = R_1 / Xc_1 = (g * 1e-6) / (2 * pi * f * c * 1e-9) = g / (2 * pi * f * c * 1e-3) - pgm_lines["tan1"] = ( - self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0) - / c_nf_per_km - / (2 * np.pi * self.system_frequency * 1e-3) - ) + pgm_lines["tan1"] = np.divide( + self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0), + c_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), + where=np.not_equal(c_nf_per_km, 0.0)) + pgm_lines["tan1"][np.equal(c_nf_per_km, 0.0)] = 0.0 pgm_lines["i_n"] = ( (self._get_pp_attr("line", "max_i_ka", expected_type="f8", default=np.nan) * 1e3) * self._get_pp_attr("line", "df", expected_type="f8", default=1) @@ -435,11 +435,11 @@ def _create_pgm_input_lines(self): pgm_lines["r0"] = self._get_pp_attr("line", "r0_ohm_per_km", expected_type="f8", default=np.nan) * multiplier pgm_lines["x0"] = self._get_pp_attr("line", "x0_ohm_per_km", expected_type="f8", default=np.nan) * multiplier pgm_lines["c0"] = c0_nf_per_km * length_km * parallel * 1e-9 - pgm_lines["tan0"] = ( - self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0) - / c0_nf_per_km - / (2 * np.pi * self.system_frequency * 1e-3) - ) + pgm_lines["tan0"] = np.divide( + self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0), + c0_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3) + ,where=np.not_equal(c0_nf_per_km, 0.0)) + pgm_lines["tan0"][np.equal(c0_nf_per_km, 0.0)] = 0.0 assert ComponentType.line not in self.pgm_input_data self.pgm_input_data[ComponentType.line] = pgm_lines @@ -1942,7 +1942,8 @@ def _pp_lines_output_3ph(self): pp_output_lines_3ph["loading_c_percent"] = ( np.maximum(pp_output_lines_3ph["i_c_from_ka"], pp_output_lines_3ph["i_c_to_ka"]) / pgm_input_lines["i_n"] ) * 1e5 - pp_output_lines_3ph["loading_percent"] = pgm_output_lines["loading"] * 1e2 + pp_output_lines_3ph["loading_percent"] = np.maximum(np.maximum(pp_output_lines_3ph["loading_a_percent"], pp_output_lines_3ph["loading_b_percent"]), + pp_output_lines_3ph["loading_c_percent"]) assert "res_line_3ph" not in self.pp_output_data self.pp_output_data["res_line_3ph"] = pp_output_lines_3ph diff --git a/tests/data/pandapower/pp_validation.py b/tests/data/pandapower/pp_validation.py index 12e26f4b..c9767126 100644 --- a/tests/data/pandapower/pp_validation.py +++ b/tests/data/pandapower/pp_validation.py @@ -208,11 +208,11 @@ def pp_net_3ph_minimal_trafo(): 2, 0.33, 0.34, - 0.001, + 0.00, 600, r0_ohm_per_km=0.66, x0_ohm_per_km=0.65, - c0_nf_per_km=0.001, + c0_nf_per_km=0.00, g_us_per_km=0, g0_us_per_km=0, ) @@ -235,5 +235,5 @@ def pp_net_3ph_minimal_trafo(): mag0_rx=0, si0_hv_partial=0.9, ) - pp.create_asymmetric_load(net, 2, 0.2, 0.19, 0.195, 0.05, 0.045, 0.035, 0, type="wye") + pp.create_asymmetric_load(net, 2, 0.2, 0.2, 0.2, 0.05, 0.05, 0.05, 0, type="wye") return net diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index 4198a556..0471900c 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -153,6 +153,13 @@ def check_result(net): np.testing.assert_allclose( np.maximum(i_c_hv / i_max_hv, i_c_lv / i_max_lv) * 100, net.res_trafo_3ph.loading_c_percent ) + np.testing.assert_allclose( + np.maximum(np.maximum(net.res_trafo_3ph.loading_a_percent, net.res_trafo_3ph.loading_b_percent), + net.res_trafo_3ph.loading_c_percent), net.res_trafo_3ph.loading_percent) + np.testing.assert_allclose( + np.maximum(np.maximum(net.res_line_3ph.loading_a_percent, net.res_line_3ph.loading_b_percent), + net.res_line_3ph.loading_c_percent), net.res_line_3ph.loading_percent) + def compare_result(actual, expected, *, rtol): np.testing.assert_allclose(actual.trafo.vn_hv_kv, expected.trafo.vn_hv_kv, rtol=rtol) @@ -192,7 +199,7 @@ def compare_result(actual, expected, *, rtol): pp.runpp_3ph(pp_net) check_result(pgm_net) check_result(pp_net) - compare_result(pgm_net, pp_net, rtol=0.04) + compare_result(pgm_net, pp_net, rtol=0.004) def test_output_data(output_data: Tuple[PandaPowerData, PandaPowerData]): From aaf2e6644916cb21cb8044b784dc189e571c0f83 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 3 Sep 2025 08:27:31 +0200 Subject: [PATCH 16/28] format Signed-off-by: Martijn Govers --- .../converters/pandapower_converter.py | 14 +++++++++----- .../test_pandapower_converter_output.py | 17 ++++++++++++----- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 88763233..ed2b62df 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -425,7 +425,8 @@ def _create_pgm_input_lines(self): pgm_lines["tan1"] = np.divide( self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0), c_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where=np.not_equal(c_nf_per_km, 0.0)) + where=np.not_equal(c_nf_per_km, 0.0), + ) pgm_lines["tan1"][np.equal(c_nf_per_km, 0.0)] = 0.0 pgm_lines["i_n"] = ( (self._get_pp_attr("line", "max_i_ka", expected_type="f8", default=np.nan) * 1e3) @@ -437,8 +438,9 @@ def _create_pgm_input_lines(self): pgm_lines["c0"] = c0_nf_per_km * length_km * parallel * 1e-9 pgm_lines["tan0"] = np.divide( self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0), - c0_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3) - ,where=np.not_equal(c0_nf_per_km, 0.0)) + c0_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), + where=np.not_equal(c0_nf_per_km, 0.0), + ) pgm_lines["tan0"][np.equal(c0_nf_per_km, 0.0)] = 0.0 assert ComponentType.line not in self.pgm_input_data self.pgm_input_data[ComponentType.line] = pgm_lines @@ -1942,8 +1944,10 @@ def _pp_lines_output_3ph(self): pp_output_lines_3ph["loading_c_percent"] = ( np.maximum(pp_output_lines_3ph["i_c_from_ka"], pp_output_lines_3ph["i_c_to_ka"]) / pgm_input_lines["i_n"] ) * 1e5 - pp_output_lines_3ph["loading_percent"] = np.maximum(np.maximum(pp_output_lines_3ph["loading_a_percent"], pp_output_lines_3ph["loading_b_percent"]), - pp_output_lines_3ph["loading_c_percent"]) + pp_output_lines_3ph["loading_percent"] = np.maximum( + np.maximum(pp_output_lines_3ph["loading_a_percent"], pp_output_lines_3ph["loading_b_percent"]), + pp_output_lines_3ph["loading_c_percent"], + ) assert "res_line_3ph" not in self.pp_output_data self.pp_output_data["res_line_3ph"] = pp_output_lines_3ph diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index 0471900c..1d2eeebc 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -154,12 +154,19 @@ def check_result(net): np.maximum(i_c_hv / i_max_hv, i_c_lv / i_max_lv) * 100, net.res_trafo_3ph.loading_c_percent ) np.testing.assert_allclose( - np.maximum(np.maximum(net.res_trafo_3ph.loading_a_percent, net.res_trafo_3ph.loading_b_percent), - net.res_trafo_3ph.loading_c_percent), net.res_trafo_3ph.loading_percent) + np.maximum( + np.maximum(net.res_trafo_3ph.loading_a_percent, net.res_trafo_3ph.loading_b_percent), + net.res_trafo_3ph.loading_c_percent, + ), + net.res_trafo_3ph.loading_percent, + ) np.testing.assert_allclose( - np.maximum(np.maximum(net.res_line_3ph.loading_a_percent, net.res_line_3ph.loading_b_percent), - net.res_line_3ph.loading_c_percent), net.res_line_3ph.loading_percent) - + np.maximum( + np.maximum(net.res_line_3ph.loading_a_percent, net.res_line_3ph.loading_b_percent), + net.res_line_3ph.loading_c_percent, + ), + net.res_line_3ph.loading_percent, + ) def compare_result(actual, expected, *, rtol): np.testing.assert_allclose(actual.trafo.vn_hv_kv, expected.trafo.vn_hv_kv, rtol=rtol) From ba52c399fcfc720205401f2c90529fec5e8f6472 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Thu, 4 Sep 2025 01:16:45 +0500 Subject: [PATCH 17/28] update tests to cover both cases of trafo_loading options, added seperate test cases for balanced and un-balanced load for trafo_loading Signed-off-by: furqan463 --- tests/data/pandapower/pp_validation.py | 10 ++--- .../test_pandapower_converter_input.py | 7 +++- .../test_pandapower_converter_output.py | 39 ++++++++++++------- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/tests/data/pandapower/pp_validation.py b/tests/data/pandapower/pp_validation.py index c9767126..d032c20f 100644 --- a/tests/data/pandapower/pp_validation.py +++ b/tests/data/pandapower/pp_validation.py @@ -9,7 +9,7 @@ @lru_cache def pp_net() -> pp.pandapowerNet: - # (ext #1) shunt - [104] - 3w - [105] - sym_gen + # (ext #1) shunt - [104] - 3w - [105] - asym_gen, asym_load # | | # [101] ---OO- [102] ---------- [103] # | | @@ -109,7 +109,7 @@ def pp_net_3ph() -> pp.pandapowerNet: """ Creates a pandapower net used for validating 3 phase calculations - (ext #1) shunt - [104], sym_gen - [105], motor, ward, asym_load, asym_gen + (ext #1) sym_gen , asym_load, asym_gen | | [101] ---OO- [102] ---------- [103] | | @@ -208,11 +208,11 @@ def pp_net_3ph_minimal_trafo(): 2, 0.33, 0.34, - 0.00, + 0.001, 600, r0_ohm_per_km=0.66, x0_ohm_per_km=0.65, - c0_nf_per_km=0.00, + c0_nf_per_km=0.001, g_us_per_km=0, g0_us_per_km=0, ) @@ -235,5 +235,5 @@ def pp_net_3ph_minimal_trafo(): mag0_rx=0, si0_hv_partial=0.9, ) - pp.create_asymmetric_load(net, 2, 0.2, 0.2, 0.2, 0.05, 0.05, 0.05, 0, type="wye") + pp.create_asymmetric_load(net, 2, 0.2, 0.19, 0.21, 0.05, 0.049, 0.052, 0, type="wye") return net diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index 3aedaec6..da64613c 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -16,7 +16,7 @@ from power_grid_model_io.data_types import ExtraInfo from power_grid_model_io.utils.json import JsonEncoder -from ...data.pandapower.pp_validation import pp_net +from ...data.pandapower.pp_validation import pp_net, pp_net_3ph_minimal_trafo from ..utils import compare_extra_info, component_attributes, component_objects, load_json_single_dataset, select_values VALIDATION_FILE = Path(__file__).parents[2] / "data" / "pandapower" / "pgm_input_data.json" @@ -116,3 +116,8 @@ def test_extra_info__serializable(extra_info): # Assert json.dumps(actual, cls=JsonEncoder) # expect no exception + +def test_pgm_input_lines__cnf_zero(): + pp_net = pp_net_3ph_minimal_trafo() + pp_converter = PandaPowerConverter() + diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index 1d2eeebc..ecfb7a25 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -26,6 +26,7 @@ PGM_ASYM_OUTPUT_FILE = PGM_PP_TEST_DATA / "pgm_asym_output_data.json" PP_V2_NET_OUTPUT_FILE = PGM_PP_TEST_DATA / "pp_v2_net_output.json" PP_V2_NET_3PH_OUTPUT_FILE = PGM_PP_TEST_DATA / "pp_v2_net_3ph_output.json" +PP_V2_NET_3PH_OUTPUT_FILE_CURRENT_LOADING = PGM_PP_TEST_DATA / "pp_v2_net_3ph_output_current_loading.json" @contextmanager @@ -47,12 +48,12 @@ def load_and_convert_pgm_data() -> PandaPowerData: @lru_cache -def load_and_convert_pgm_data_3ph() -> PandaPowerData: +def load_and_convert_pgm_data_3ph(trafo_loading="power") -> PandaPowerData: """ Load and convert the power_grid_model results """ data, _ = load_json_single_dataset(PGM_ASYM_OUTPUT_FILE, data_type="asym_output") - converter = PandaPowerConverter(trafo_loading="power") + converter = PandaPowerConverter(trafo_loading=trafo_loading) converter.load_input_data(load_validation_data_3ph(), make_extra_info=False) return converter.convert(data=data) @@ -66,11 +67,14 @@ def load_validation_data() -> PandaPowerData: @lru_cache -def load_validation_data_3ph() -> PandaPowerData: +def load_validation_data_3ph(trafo_loading="power") -> PandaPowerData: """ Load the validation data from the pp file """ - return pp.file_io.from_json(PP_V2_NET_3PH_OUTPUT_FILE) + if trafo_loading == "power": + return pp.file_io.from_json(PP_V2_NET_3PH_OUTPUT_FILE) + else: + return pp.file_io.from_json(PP_V2_NET_3PH_OUTPUT_FILE_CURRENT_LOADING) @pytest.fixture @@ -83,13 +87,13 @@ def output_data() -> Tuple[PandaPowerData, PandaPowerData]: return actual, expected -@pytest.fixture -def output_data_3ph() -> Tuple[PandaPowerData, PandaPowerData]: +@pytest.fixture(params = ["power", "current"]) +def output_data_3ph(request) -> Tuple[PandaPowerData, PandaPowerData]: """ Load the pandapower network and the json file, and return the output_data """ - actual = load_and_convert_pgm_data_3ph() - expected = load_validation_data_3ph() + actual = load_and_convert_pgm_data_3ph(request.param) + expected = load_validation_data_3ph(request.param) return actual, expected @@ -202,11 +206,23 @@ def compare_result(actual, expected, *, rtol): pgm_net = pp_net_3ph_minimal_trafo() pp_net = pp_net_3ph_minimal_trafo() + # Asymmetric Load + pp.runpp_pgm(pgm_net, symmetric=False) + pp.runpp_3ph(pp_net) + check_result(pgm_net) + check_result(pp_net) + compare_result(pgm_net, pp_net, rtol=0.04) + + # Symmetric Load + pgm_net.asymmetric_load.loc[:, ['p_a_mw', 'p_b_mw', 'p_c_mw']] = 0.2 + pgm_net.asymmetric_load.loc[:, ['q_a_mvar', 'q_b_mvar', 'q_c_mar']] = 0.05 + pp_net.asymmetric_load.loc[:, ['p_a_mw', 'p_b_mw', 'p_c_mw']] = 0.2 + pp_net.asymmetric_load.loc[:, ['q_a_mvar', 'q_b_mvar', 'q_c_mar']] = 0.05 pp.runpp_pgm(pgm_net, symmetric=False) pp.runpp_3ph(pp_net) check_result(pgm_net) check_result(pp_net) - compare_result(pgm_net, pp_net, rtol=0.004) + compare_result(pgm_net, pp_net, rtol=0.005) def test_output_data(output_data: Tuple[PandaPowerData, PandaPowerData]): @@ -247,10 +263,7 @@ def test_attributes(output_data: Tuple[PandaPowerData, PandaPowerData], componen pd.testing.assert_series_equal(actual_values, expected_values, atol=5e-4, rtol=1e-4) -# The following test only works for those components where valid data is returned by -# load_and_convert_pgm_data_3ph. since this is failing for trafo_output_3ph (returning -# from first "if", this function's output is not being tested currently. -@pytest.mark.parametrize(("component", "attribute"), component_attributes_df(load_and_convert_pgm_data_3ph())) +@pytest.mark.parametrize(("component", "attribute"), component_attributes_df(load_and_convert_pgm_data_3ph())) def test_attributes_3ph(output_data_3ph: Tuple[PandaPowerData, PandaPowerData], component: str, attribute: str): """ For each attribute, check if the actual values are consistent with the expected values for asym From a398aa020d1c2304eefc4d79c6818f381c192248 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Thu, 4 Sep 2025 21:57:33 +0500 Subject: [PATCH 18/28] Validation tests for input_pgm_line Signed-off-by: furqan463 --- .../converters/test_pandapower_converter_input.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index da64613c..e5cbd9d9 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -9,7 +9,7 @@ import pandas as pd import pytest -from power_grid_model import DatasetType +from power_grid_model import DatasetType, ComponentType from power_grid_model.data_types import SingleDataset from power_grid_model_io.converters import PandaPowerConverter @@ -117,7 +117,15 @@ def test_extra_info__serializable(extra_info): # Assert json.dumps(actual, cls=JsonEncoder) # expect no exception +@pytest.mark.filterwarnings("error:.*invalid value encountered in divide.*:RuntimeWarning") def test_pgm_input_lines__cnf_zero(): - pp_net = pp_net_3ph_minimal_trafo() + pp_network = pp_net_3ph_minimal_trafo() pp_converter = PandaPowerConverter() + pp_network.line.c_nf_per_km = 0 + data, _ = pp_converter.load_input_data(pp_network) + assert data[ComponentType.line]["tan1"] == 0 + pp_network.line.c_nf_per_km = 0.001 + pp_network.line.c0_nf_per_km = 0 + data, _ = pp_converter.load_input_data(pp_network) + assert data[ComponentType.line]["tan0"] == 0 From 7b82673a3d4ef1cd39c74b4d011e25bd9c5200bd Mon Sep 17 00:00:00 2001 From: furqan463 Date: Thu, 4 Sep 2025 22:15:37 +0500 Subject: [PATCH 19/28] Remove resolved comments. Signed-off-by: furqan463 --- src/power_grid_model_io/converters/pandapower_converter.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index ed2b62df..9b07a7ac 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -2022,12 +2022,8 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements # Only derating factor used here. Sn is already being multiplied by parallel loading_multiplier = pp_input_transformers["df"] * 1e2 if self.trafo_loading == "current": - # since "i_from" and "i_to" are (n, 3) arrays while "u1" and "u2" are (n,) arrays, ValueError is generated - # during broadcast ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"][:, None] ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"][:, None] - # for phase wise loading, sn_ph = sn / 3, v_n = v / sqrt(3), so (i * u / sqrt(3)) / (sn / 3) - # ==> sqrt(3) * i * u / sn loading_a_percent = np.sqrt(3) * np.maximum(ui_from[:, 0], ui_to[:, 0]) / pgm_input_transformers["sn"] loading_b_percent = np.sqrt(3) * np.maximum(ui_from[:, 1], ui_to[:, 1]) / pgm_input_transformers["sn"] loading_c_percent = np.sqrt(3) * np.maximum(ui_from[:, 2], ui_to[:, 2]) / pgm_input_transformers["sn"] @@ -2047,8 +2043,6 @@ def _pp_trafos_output_3ph(self): # pylint: disable=too-many-statements else: raise ValueError(f"Invalid transformer loading type: {str(self.trafo_loading)}") - # PGM returns the average loading over the trafos, but PandaPower returns the maximum of the per-phase loading. - # To make it consistent with PandaPower, overall loading will be calculated as max of above 3. loading = np.maximum(np.maximum(loading_a_percent, loading_b_percent), loading_c_percent) pp_output_trafos_3ph = pd.DataFrame( From 1cecec4d8d23de4af8303abf1ad9452e44cbb249 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Thu, 4 Sep 2025 22:30:02 +0500 Subject: [PATCH 20/28] Formatting. Signed-off-by: furqan463 --- .../converters/test_pandapower_converter_input.py | 2 +- .../converters/test_pandapower_converter_output.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index e5cbd9d9..1bd490fd 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -9,7 +9,7 @@ import pandas as pd import pytest -from power_grid_model import DatasetType, ComponentType +from power_grid_model import ComponentType, DatasetType from power_grid_model.data_types import SingleDataset from power_grid_model_io.converters import PandaPowerConverter diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index ecfb7a25..bca827ab 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -214,10 +214,10 @@ def compare_result(actual, expected, *, rtol): compare_result(pgm_net, pp_net, rtol=0.04) # Symmetric Load - pgm_net.asymmetric_load.loc[:, ['p_a_mw', 'p_b_mw', 'p_c_mw']] = 0.2 - pgm_net.asymmetric_load.loc[:, ['q_a_mvar', 'q_b_mvar', 'q_c_mar']] = 0.05 - pp_net.asymmetric_load.loc[:, ['p_a_mw', 'p_b_mw', 'p_c_mw']] = 0.2 - pp_net.asymmetric_load.loc[:, ['q_a_mvar', 'q_b_mvar', 'q_c_mar']] = 0.05 + pgm_net.asymmetric_load.loc[:, ["p_a_mw", "p_b_mw", "p_c_mw"]] = 0.2 + pgm_net.asymmetric_load.loc[:, ["q_a_mvar", "q_b_mvar", "q_c_mar"]] = 0.05 + pp_net.asymmetric_load.loc[:, ["p_a_mw", "p_b_mw", "p_c_mw"]] = 0.2 + pp_net.asymmetric_load.loc[:, ["q_a_mvar", "q_b_mvar", "q_c_mar"]] = 0.05 pp.runpp_pgm(pgm_net, symmetric=False) pp.runpp_3ph(pp_net) check_result(pgm_net) From 40d3a73ef2952819557ae21f16c47e841fccb172 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Fri, 5 Sep 2025 00:38:27 +0500 Subject: [PATCH 21/28] resolved test_pandapower_converter_ouput to completely test trafo and switch output, also corrected bugs in pp_trafo_output and pp_switch_output Signed-off-by: furqan463 --- .../converters/pandapower_converter.py | 14 +++++++++----- tests/data/pandapower/pp_v2_net_output.json | 2 +- .../test_pandapower_converter_output.py | 2 +- .../test_pandapower_converter_output.py | 15 ++++++++------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 9b07a7ac..ac0f016a 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -425,7 +425,7 @@ def _create_pgm_input_lines(self): pgm_lines["tan1"] = np.divide( self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0), c_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where=np.not_equal(c_nf_per_km, 0.0), + where= c_nf_per_km != 0.0, ) pgm_lines["tan1"][np.equal(c_nf_per_km, 0.0)] = 0.0 pgm_lines["i_n"] = ( @@ -439,7 +439,7 @@ def _create_pgm_input_lines(self): pgm_lines["tan0"] = np.divide( self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0), c0_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where=np.not_equal(c0_nf_per_km, 0.0), + where= c0_nf_per_km != 0.0, ) pgm_lines["tan0"][np.equal(c0_nf_per_km, 0.0)] = 0.0 assert ComponentType.line not in self.pgm_input_data @@ -1384,7 +1384,8 @@ def _pp_trafos_output(self): if self.trafo_loading == "current": ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"] ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"] - loading = np.maximum(ui_from, ui_to) / pgm_input_transformers["sn"] * loading_multiplier * 1e2 + loading = (np.sqrt(3) * np.maximum(ui_from, ui_to) / + pgm_input_transformers["sn"]) * loading_multiplier * 1e2 elif self.trafo_loading == "power": loading = pgm_output_transformers["loading"] * loading_multiplier * 1e2 else: @@ -1706,7 +1707,6 @@ def join_currents(table: str, bus_name: str, i_name: str) -> pd.DataFrame: ) pp_switches_output = pp_switches_output[["i_ka"]] pp_switches_output.set_index(pp_switches_output_index, inplace=True) - pp_switches_output["loading_percent"] = np.nan # For et=b, ie bus to bus switches, links are created. get result from them if not links_absent: @@ -1714,7 +1714,11 @@ def join_currents(table: str, bus_name: str, i_name: str) -> pd.DataFrame: # For links, i_from = i_to = i_ka / 1e3 link_ids = self._get_pp_ids("switch", links["id"], "b2b_switches") pp_switches_output.loc[link_ids, "i_ka"] = links["i_from"] * 1e-3 - + in_ka = self.pp_input_data["switch"]["in_ka"].values + pp_switches_output["loading_percent"] = np.nan + pp_switches_output["loading_percent"] = np.divide(pp_switches_output["i_ka"], + in_ka, where= in_ka != 0) + assert "res_switch" not in self.pp_output_data self.pp_output_data["res_switch"] = pp_switches_output diff --git a/tests/data/pandapower/pp_v2_net_output.json b/tests/data/pandapower/pp_v2_net_output.json index 477980a5..bbd8d3af 100644 --- a/tests/data/pandapower/pp_v2_net_output.json +++ b/tests/data/pandapower/pp_v2_net_output.json @@ -2708,7 +2708,7 @@ "res_switch": { "_module": "pandas.core.frame", "_class": "DataFrame", - "_object": "{\"columns\":[\"i_ka\",\"loading_percent\"],\"index\":[101,3021,321],\"data\":[[0.064048243266779,null],[null,null],[0.020545341606839,null]]}", + "_object": "{\"columns\":[\"i_ka\",\"loading_percent\"],\"index\":[101,3021,321],\"data\":[[0.064048243266779,null],[0.0,null],[0.020545341606839,null]]}", "orient": "split", "dtype": { "i_ka": "float64", diff --git a/tests/unit/converters/test_pandapower_converter_output.py b/tests/unit/converters/test_pandapower_converter_output.py index a8b452dd..0e21f8ea 100644 --- a/tests/unit/converters/test_pandapower_converter_output.py +++ b/tests/unit/converters/test_pandapower_converter_output.py @@ -770,6 +770,7 @@ def test_pp_switch_output(): "element": [10, 10, 10, 10, 10, 11, 11, 77, 88], "et": ["t", "t", "t3", "t3", "t3", "l", "l", "b", "b"], "closed": [True, True, True, True, True, True, True, True, True], + "in_ka": [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], }, index=[40, 41, 42, 43, 44, 45, 46, 47, 48], ), @@ -863,7 +864,6 @@ def test_output_line_3ph(converter): mock_pgm_array.__getitem__.assert_any_call("q_to") mock_pgm_array.__getitem__.assert_any_call("i_from") mock_pgm_array.__getitem__.assert_any_call("i_to") - mock_pgm_array.__getitem__.assert_any_call("loading") # assignment mock_pp_df.return_value.__setitem__.assert_any_call("p_a_from_mw", ANY) diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index bca827ab..bf8bdaef 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -38,13 +38,14 @@ def temporary_file_cleanup(file_path): @lru_cache -def load_and_convert_pgm_data() -> PandaPowerData: +def load_and_convert_pgm_data(trafo_loading="power") -> PandaPowerData: """ Load and convert the power_grid_model results """ - data, extra_info = load_json_single_dataset(PGM_OUTPUT_FILE, data_type="sym_output") - converter = PandaPowerConverter() - return converter.convert(data=data, extra_info=extra_info) + data, _ = load_json_single_dataset(PGM_OUTPUT_FILE, data_type="sym_output") + converter = PandaPowerConverter(trafo_loading=trafo_loading) + converter.load_input_data(load_validation_data(), make_extra_info=False) + return converter.convert(data=data) @lru_cache @@ -77,12 +78,12 @@ def load_validation_data_3ph(trafo_loading="power") -> PandaPowerData: return pp.file_io.from_json(PP_V2_NET_3PH_OUTPUT_FILE_CURRENT_LOADING) -@pytest.fixture -def output_data() -> Tuple[PandaPowerData, PandaPowerData]: +@pytest.fixture(params = ["power", "current"]) +def output_data(request) -> Tuple[PandaPowerData, PandaPowerData]: """ Load the pandapower network and the json file, and return the output_data """ - actual = load_and_convert_pgm_data() + actual = load_and_convert_pgm_data(request.param) expected = load_validation_data() return actual, expected From 6ce871a5fca3dfb2501cfafa8cf5d6d7638f767a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 4 Sep 2025 22:29:17 +0200 Subject: [PATCH 22/28] fix test Signed-off-by: Martijn Govers --- tests/unit/converters/test_pandapower_converter_input.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unit/converters/test_pandapower_converter_input.py b/tests/unit/converters/test_pandapower_converter_input.py index 2b4517de..d8903600 100644 --- a/tests/unit/converters/test_pandapower_converter_input.py +++ b/tests/unit/converters/test_pandapower_converter_input.py @@ -572,9 +572,11 @@ def test_create_pgm_input_lines(mock_init_array: MagicMock, two_pp_objs, convert ) pgm.assert_any_call( "tan1", - _get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0) - / _get_pp_attr("line", "c_nf_per_km", expected_type="f8") - / (np.pi / 10), + np.divide( + _get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0), + _get_pp_attr("line", "c_nf_per_km", expected_type="f8") * (np.pi / 10), + where=_get_pp_attr("line", "c_nf_per_km", expected_type="f8") != 0.0, + ), ) pgm.assert_any_call( "i_n", From 4c23843f135a25386f47e63e16c4472e043143b6 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 4 Sep 2025 22:30:17 +0200 Subject: [PATCH 23/28] format Signed-off-by: Martijn Govers --- .../converters/pandapower_converter.py | 14 +++++++------- .../converters/test_pandapower_converter_output.py | 2 +- .../converters/test_pandapower_converter_input.py | 2 +- .../converters/test_pandapower_converter_output.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index ac0f016a..d1b0f84c 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -425,7 +425,7 @@ def _create_pgm_input_lines(self): pgm_lines["tan1"] = np.divide( self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0), c_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where= c_nf_per_km != 0.0, + where=c_nf_per_km != 0.0, ) pgm_lines["tan1"][np.equal(c_nf_per_km, 0.0)] = 0.0 pgm_lines["i_n"] = ( @@ -439,7 +439,7 @@ def _create_pgm_input_lines(self): pgm_lines["tan0"] = np.divide( self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0), c0_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where= c0_nf_per_km != 0.0, + where=c0_nf_per_km != 0.0, ) pgm_lines["tan0"][np.equal(c0_nf_per_km, 0.0)] = 0.0 assert ComponentType.line not in self.pgm_input_data @@ -1384,8 +1384,9 @@ def _pp_trafos_output(self): if self.trafo_loading == "current": ui_from = pgm_output_transformers["i_from"] * pgm_input_transformers["u1"] ui_to = pgm_output_transformers["i_to"] * pgm_input_transformers["u2"] - loading = (np.sqrt(3) * np.maximum(ui_from, ui_to) / - pgm_input_transformers["sn"]) * loading_multiplier * 1e2 + loading = ( + (np.sqrt(3) * np.maximum(ui_from, ui_to) / pgm_input_transformers["sn"]) * loading_multiplier * 1e2 + ) elif self.trafo_loading == "power": loading = pgm_output_transformers["loading"] * loading_multiplier * 1e2 else: @@ -1716,9 +1717,8 @@ def join_currents(table: str, bus_name: str, i_name: str) -> pd.DataFrame: pp_switches_output.loc[link_ids, "i_ka"] = links["i_from"] * 1e-3 in_ka = self.pp_input_data["switch"]["in_ka"].values pp_switches_output["loading_percent"] = np.nan - pp_switches_output["loading_percent"] = np.divide(pp_switches_output["i_ka"], - in_ka, where= in_ka != 0) - + pp_switches_output["loading_percent"] = np.divide(pp_switches_output["i_ka"], in_ka, where=in_ka != 0) + assert "res_switch" not in self.pp_output_data self.pp_output_data["res_switch"] = pp_switches_output diff --git a/tests/unit/converters/test_pandapower_converter_output.py b/tests/unit/converters/test_pandapower_converter_output.py index 0e21f8ea..85d616f8 100644 --- a/tests/unit/converters/test_pandapower_converter_output.py +++ b/tests/unit/converters/test_pandapower_converter_output.py @@ -770,7 +770,7 @@ def test_pp_switch_output(): "element": [10, 10, 10, 10, 10, 11, 11, 77, 88], "et": ["t", "t", "t3", "t3", "t3", "l", "l", "b", "b"], "closed": [True, True, True, True, True, True, True, True, True], - "in_ka": [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + "in_ka": [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], }, index=[40, 41, 42, 43, 44, 45, 46, 47, 48], ), diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index 1bd490fd..eef953f9 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -117,6 +117,7 @@ def test_extra_info__serializable(extra_info): # Assert json.dumps(actual, cls=JsonEncoder) # expect no exception + @pytest.mark.filterwarnings("error:.*invalid value encountered in divide.*:RuntimeWarning") def test_pgm_input_lines__cnf_zero(): pp_network = pp_net_3ph_minimal_trafo() @@ -128,4 +129,3 @@ def test_pgm_input_lines__cnf_zero(): pp_network.line.c0_nf_per_km = 0 data, _ = pp_converter.load_input_data(pp_network) assert data[ComponentType.line]["tan0"] == 0 - diff --git a/tests/validation/converters/test_pandapower_converter_output.py b/tests/validation/converters/test_pandapower_converter_output.py index bf8bdaef..6916b133 100644 --- a/tests/validation/converters/test_pandapower_converter_output.py +++ b/tests/validation/converters/test_pandapower_converter_output.py @@ -78,7 +78,7 @@ def load_validation_data_3ph(trafo_loading="power") -> PandaPowerData: return pp.file_io.from_json(PP_V2_NET_3PH_OUTPUT_FILE_CURRENT_LOADING) -@pytest.fixture(params = ["power", "current"]) +@pytest.fixture(params=["power", "current"]) def output_data(request) -> Tuple[PandaPowerData, PandaPowerData]: """ Load the pandapower network and the json file, and return the output_data @@ -88,7 +88,7 @@ def output_data(request) -> Tuple[PandaPowerData, PandaPowerData]: return actual, expected -@pytest.fixture(params = ["power", "current"]) +@pytest.fixture(params=["power", "current"]) def output_data_3ph(request) -> Tuple[PandaPowerData, PandaPowerData]: """ Load the pandapower network and the json file, and return the output_data @@ -264,7 +264,7 @@ def test_attributes(output_data: Tuple[PandaPowerData, PandaPowerData], componen pd.testing.assert_series_equal(actual_values, expected_values, atol=5e-4, rtol=1e-4) -@pytest.mark.parametrize(("component", "attribute"), component_attributes_df(load_and_convert_pgm_data_3ph())) +@pytest.mark.parametrize(("component", "attribute"), component_attributes_df(load_and_convert_pgm_data_3ph())) def test_attributes_3ph(output_data_3ph: Tuple[PandaPowerData, PandaPowerData], component: str, attribute: str): """ For each attribute, check if the actual values are consistent with the expected values for asym From ec9ebeb9db4ba6aa367370f5177a19e0b14311fc Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 5 Sep 2025 08:38:46 +0200 Subject: [PATCH 24/28] catch warnings instead of filter warnings Signed-off-by: Martijn Govers --- .../test_pandapower_converter_input.py | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index eef953f9..71bb1f02 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -3,10 +3,12 @@ # SPDX-License-Identifier: MPL-2.0 import json +import warnings from functools import lru_cache from pathlib import Path from typing import List, Tuple +import numpy as np import pandas as pd import pytest from power_grid_model import ComponentType, DatasetType @@ -118,14 +120,17 @@ def test_extra_info__serializable(extra_info): json.dumps(actual, cls=JsonEncoder) # expect no exception -@pytest.mark.filterwarnings("error:.*invalid value encountered in divide.*:RuntimeWarning") def test_pgm_input_lines__cnf_zero(): - pp_network = pp_net_3ph_minimal_trafo() - pp_converter = PandaPowerConverter() - pp_network.line.c_nf_per_km = 0 - data, _ = pp_converter.load_input_data(pp_network) - assert data[ComponentType.line]["tan1"] == 0 - pp_network.line.c_nf_per_km = 0.001 - pp_network.line.c0_nf_per_km = 0 - data, _ = pp_converter.load_input_data(pp_network) - assert data[ComponentType.line]["tan0"] == 0 + with warnings.catch_warnings(): + warnings.simplefilter("error") + + pp_network = pp_net_3ph_minimal_trafo() + pp_converter = PandaPowerConverter() + pp_network.line.c_nf_per_km = 0 + data, _ = pp_converter.load_input_data(pp_network) + np.testing.assert_array_equal(data[ComponentType.line]["tan1"], 0) + + pp_network.line.c_nf_per_km = 0.001 + pp_network.line.c0_nf_per_km = 0 + data, _ = pp_converter.load_input_data(pp_network) + np.testing.assert_array_equal(data[ComponentType.line]["tan0"], 0) From 42cf4bc8aeb91160e032a680622869e7858e3d31 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 5 Sep 2025 09:44:07 +0200 Subject: [PATCH 25/28] actually resolve all warning messages Signed-off-by: Martijn Govers --- .../converters/pandapower_converter.py | 5 +- .../test_pandapower_converter_input.py | 384 +++++++++--------- .../test_pandapower_converter_input.py | 66 +-- 3 files changed, 245 insertions(+), 210 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index d1b0f84c..677e8bc4 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -757,7 +757,10 @@ def _create_pgm_input_transformers(self): # pylint: disable=too-many-statements valid = np.logical_and(np.not_equal(sn_mva, 0.0), np.isfinite(sn_mva)) mag_g = np.divide(pfe, sn_mva * 1000, where=valid) mag_g[np.logical_not(valid)] = np.nan - rx_mag = mag_g / np.sqrt(i_no_load * i_no_load * 1e-4 - mag_g * mag_g) + z_squared = i_no_load * i_no_load * 1e-4 - mag_g * mag_g + valid = np.logical_and(np.greater(z_squared, 0), np.isfinite(z_squared)) + rx_mag = np.divide(mag_g, np.sqrt(z_squared, where=valid), where=valid) + rx_mag[np.logical_not(valid)] = np.inf # positive and zero sequence magnetising impedance must be equal. # mag0_percent = z0mag / z0. checks = { diff --git a/tests/unit/converters/test_pandapower_converter_input.py b/tests/unit/converters/test_pandapower_converter_input.py index d8903600..4b6b8842 100644 --- a/tests/unit/converters/test_pandapower_converter_input.py +++ b/tests/unit/converters/test_pandapower_converter_input.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: MPL-2.0 +import warnings from importlib import metadata from typing import Callable, TypeAlias from unittest.mock import ANY, MagicMock, call, patch @@ -849,6 +850,7 @@ def test_create_pgm_input_shunts(mock_init_array: MagicMock, two_pp_objs, conver @patch("power_grid_model_io.converters.pandapower_converter.initialize_array") @patch("power_grid_model_io.converters.pandapower_converter.np.round", new=lambda x: x) +@patch("power_grid_model_io.converters.pandapower_converter.np.sqrt", new=lambda x, **kwargs: x) @patch("power_grid_model_io.converters.pandapower_converter.np.less", new=lambda x, _, **kwargs: x) @patch("power_grid_model_io.converters.pandapower_converter.np.divide", new=lambda x, _, **kwargs: x) @patch("power_grid_model_io.converters.pandapower_converter.np.bitwise_and", new=lambda x, _: x) @@ -958,57 +960,62 @@ def test_create_pgm_input_transformers(mock_init_array: MagicMock, two_pp_objs, new=MagicMock(return_value=pd.Series([0])), ) def test_create_pgm_input_transformers__default() -> None: - # Arrange - pp_net: PandaPowerNet = pp.create_empty_network() - pp.create_bus(net=pp_net, vn_kv=0.0) - args = [0, 0, 0, 0, 0, 0, 0, 0, 0] - pp.create_transformer_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="hv" - ) - pp.create_transformer_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="lv" - ) - pp.create_transformer_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side=None - ) - tap_pos_trafo = pp.create_transformer_from_parameters(pp_net, *args, tap_neutral=12.0, tap_size=1, tap_side="hv") - pp_net["trafo"].loc[tap_pos_trafo, "tap_pos"] = np.nan - pp.create_transformer_from_parameters(pp_net, *args, tap_neutral=np.nan, tap_pos=34.0, tap_side="hv") - pp.create_transformer_from_parameters( - pp_net, *args, tap_neutral=12, tap_step_percent=np.nan, tap_pos=34.0, tap_side="hv" - ) - pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=30) - pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=60) - pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=59) - pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=61) - - converter = PandaPowerConverter() - converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + pp_net: PandaPowerNet = pp.create_empty_network() + pp.create_bus(net=pp_net, vn_kv=0.0) + args = [0, 0, 1, 0, 0, 0, 0, 0, 0] + pp.create_transformer_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="hv" + ) + pp.create_transformer_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="lv" + ) + pp.create_transformer_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side=None + ) + tap_pos_trafo = pp.create_transformer_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_size=1, tap_side="hv" + ) + pp_net["trafo"].loc[tap_pos_trafo, "tap_pos"] = np.nan + pp.create_transformer_from_parameters(pp_net, *args, tap_neutral=np.nan, tap_pos=34.0, tap_side="hv") + pp.create_transformer_from_parameters( + pp_net, *args, tap_neutral=12, tap_step_percent=np.nan, tap_pos=34.0, tap_side="hv" + ) + pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=30) + pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=60) + pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=59) + pp.create_transformer_from_parameters(pp_net, *args, vector_group=None, shift_degree=61) - # Act - converter._create_pgm_input_transformers() - result = converter.pgm_input_data[ComponentType.transformer] + converter = PandaPowerConverter() + converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} - # Assert - assert result[0]["tap_side"] == BranchSide.from_side.value - assert result[1]["tap_side"] == BranchSide.to_side.value - assert result[2]["tap_side"] == BranchSide.from_side.value - assert result[3]["tap_side"] == BranchSide.from_side.value - assert result[4]["tap_side"] == BranchSide.from_side.value - assert result[0]["tap_pos"] == 34.0 != result[0]["tap_nom"] - assert result[1]["tap_pos"] == 34.0 != result[1]["tap_nom"] - assert result[2]["tap_pos"] == 0.0 == result[2]["tap_nom"] - assert result[3]["tap_pos"] == 0.0 == result[3]["tap_nom"] - assert result[4]["tap_pos"] == 0.0 == result[4]["tap_nom"] - assert result[5]["tap_size"] == 0.0 - - assert result[6]["winding_from"] == WindingType.delta - assert result[6]["winding_to"] == WindingType.wye_n - assert result[7]["winding_from"] == WindingType.wye_n - assert result[7]["winding_to"] == WindingType.wye_n - - assert result[8]["clock"] == 2 - assert result[9]["clock"] == 2 + # Act + converter._create_pgm_input_transformers() + result = converter.pgm_input_data[ComponentType.transformer] + + # Assert + assert result[0]["tap_side"] == BranchSide.from_side.value + assert result[1]["tap_side"] == BranchSide.to_side.value + assert result[2]["tap_side"] == BranchSide.from_side.value + assert result[3]["tap_side"] == BranchSide.from_side.value + assert result[4]["tap_side"] == BranchSide.from_side.value + assert result[0]["tap_pos"] == 34.0 != result[0]["tap_nom"] + assert result[1]["tap_pos"] == 34.0 != result[1]["tap_nom"] + assert result[2]["tap_pos"] == 0.0 == result[2]["tap_nom"] + assert result[3]["tap_pos"] == 0.0 == result[3]["tap_nom"] + assert result[4]["tap_pos"] == 0.0 == result[4]["tap_nom"] + assert result[5]["tap_size"] == 0.0 + + assert result[6]["winding_from"] == WindingType.delta + assert result[6]["winding_to"] == WindingType.wye_n + assert result[7]["winding_from"] == WindingType.wye_n + assert result[7]["winding_to"] == WindingType.wye_n + + assert result[8]["clock"] == 2 + assert result[9]["clock"] == 2 @patch("power_grid_model_io.converters.pandapower_converter.initialize_array") @@ -1087,21 +1094,24 @@ def test_create_pgm_input_sym_gens(mock_init_array: MagicMock, two_pp_objs, conv new=MagicMock(return_value=pd.Series([0])), ) def test_create_pgm_input_transformers__warnings(kwargs) -> None: - # Arrange - pp_net: PandaPowerNet = pp.create_empty_network() - pp.create_bus(net=pp_net, vn_kv=0.0) - args = [0, 0, 0, 0, 0, 0, 0, 0, 0] - if "pfe_kw" in kwargs: - args[-2] = kwargs["pfe_kw"] - kwargs = {} - pp.create_transformer_from_parameters(pp_net, *args, **kwargs) + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + pp_net: PandaPowerNet = pp.create_empty_network() + pp.create_bus(net=pp_net, vn_kv=0.0) + args = [0, 0, 1, 0, 0, 0, 0, 0, 0] + if "pfe_kw" in kwargs: + args[-2] = kwargs["pfe_kw"] + kwargs = {} + pp.create_transformer_from_parameters(pp_net, *args, **kwargs) - converter = PandaPowerConverter() - converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} + converter = PandaPowerConverter() + converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} - with patch("power_grid_model_io.converters.pandapower_converter.logger") as mock_logger: - converter._create_pgm_input_transformers() - mock_logger.warning.assert_called_once() + with patch("power_grid_model_io.converters.pandapower_converter.logger") as mock_logger: + converter._create_pgm_input_transformers() + mock_logger.warning.assert_called_once() @patch("power_grid_model_io.converters.pandapower_converter.initialize_array") @@ -1314,116 +1324,119 @@ def test_create_pgm_input_three_winding_transformers(mock_init_array: MagicMock, new=MagicMock(return_value=pd.Series([0])), ) def test_create_pgm_input_transformers3w__default() -> None: - # Arrange - pp_net: PandaPowerNet = pp.create_empty_network() - pp.create_bus(net=pp_net, vn_kv=0.0) - args = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="hv" - ) - pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="mv" - ) - pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="lv" - ) - pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side=None - ) - pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=np.nan, tap_pos=34.0, tap_step_percent=1, tap_side="hv" - ) - nan_trafo = pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_step_percent=1, tap_pos=np.nan, tap_side="hv" - ) - pp_net["trafo3w"].loc[nan_trafo, "tap_pos"] = np.nan - pp.create_transformer3w_from_parameters( - pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=np.nan, tap_side="hv" - ) - pp.create_transformer3w_from_parameters( - pp_net, - *args, - vector_group=None, - shift_mv_degree=30, - shift_lv_degree=30, - ) - pp.create_transformer3w_from_parameters( - pp_net, - *args, - vector_group=None, - shift_mv_degree=60, - shift_lv_degree=60, - ) - pp.create_transformer3w_from_parameters( - pp_net, - *args, - vector_group=None, - shift_mv_degree=60, - shift_lv_degree=30, - ) - pp.create_transformer3w_from_parameters( - pp_net, - *args, - vector_group=None, - shift_mv_degree=30, - shift_lv_degree=60, - ) - pp.create_transformer3w_from_parameters( - pp_net, - *args, - vector_group=None, - shift_mv_degree=58, - shift_lv_degree=62, - ) - pp.create_transformer3w_from_parameters( - pp_net, - *args, - vector_group=None, - shift_mv_degree=29, - shift_lv_degree=31, - ) - - converter = PandaPowerConverter() - converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + pp_net: PandaPowerNet = pp.create_empty_network() + pp.create_bus(net=pp_net, vn_kv=0.0) + args = [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0] + pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="hv" + ) + pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="mv" + ) + pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side="lv" + ) + pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=1, tap_side=None + ) + pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=np.nan, tap_pos=34.0, tap_step_percent=1, tap_side="hv" + ) + nan_trafo = pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_step_percent=1, tap_pos=np.nan, tap_side="hv" + ) + pp_net["trafo3w"].loc[nan_trafo, "tap_pos"] = np.nan + pp.create_transformer3w_from_parameters( + pp_net, *args, tap_neutral=12.0, tap_pos=34.0, tap_step_percent=np.nan, tap_side="hv" + ) + pp.create_transformer3w_from_parameters( + pp_net, + *args, + vector_group=None, + shift_mv_degree=30, + shift_lv_degree=30, + ) + pp.create_transformer3w_from_parameters( + pp_net, + *args, + vector_group=None, + shift_mv_degree=60, + shift_lv_degree=60, + ) + pp.create_transformer3w_from_parameters( + pp_net, + *args, + vector_group=None, + shift_mv_degree=60, + shift_lv_degree=30, + ) + pp.create_transformer3w_from_parameters( + pp_net, + *args, + vector_group=None, + shift_mv_degree=30, + shift_lv_degree=60, + ) + pp.create_transformer3w_from_parameters( + pp_net, + *args, + vector_group=None, + shift_mv_degree=58, + shift_lv_degree=62, + ) + pp.create_transformer3w_from_parameters( + pp_net, + *args, + vector_group=None, + shift_mv_degree=29, + shift_lv_degree=31, + ) - # Act - converter._create_pgm_input_three_winding_transformers() - result = converter.pgm_input_data[ComponentType.three_winding_transformer] + converter = PandaPowerConverter() + converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} - # Assert - assert result[0]["tap_side"] == Branch3Side.side_1.value - assert result[1]["tap_side"] == Branch3Side.side_2.value - assert result[2]["tap_side"] == Branch3Side.side_3.value - assert result[3]["tap_side"] == Branch3Side.side_1.value - assert result[4]["tap_side"] == Branch3Side.side_1.value - assert result[5]["tap_side"] == Branch3Side.side_1.value - assert result[0]["tap_pos"] == 34.0 != result[0]["tap_nom"] - assert result[1]["tap_pos"] == 34.0 != result[1]["tap_nom"] - assert result[2]["tap_pos"] == 34.0 != result[2]["tap_nom"] - assert result[3]["tap_pos"] == 0 == result[3]["tap_nom"] - assert result[4]["tap_pos"] == 0 == result[4]["tap_nom"] - assert result[5]["tap_pos"] == 0 == result[5]["tap_nom"] - assert result[6]["tap_size"] == 0 - - # Default yndd for odd clocks - assert result[7]["winding_1"] == WindingType.wye_n - assert result[7]["winding_2"] == WindingType.delta - assert result[7]["winding_3"] == WindingType.delta - # Default ynynyn for even clocks - assert result[8]["winding_1"] == WindingType.wye_n - assert result[8]["winding_2"] == WindingType.wye_n - assert result[8]["winding_3"] == WindingType.wye_n - # Default ynynd for clock_12 even clock_13 odd - assert result[9]["winding_1"] == WindingType.wye_n - assert result[9]["winding_2"] == WindingType.wye_n - assert result[9]["winding_3"] == WindingType.delta - # Default yndyn for clock_12 odd clock_13 even - assert result[10]["winding_1"] == WindingType.wye_n - assert result[10]["winding_2"] == WindingType.delta - assert result[10]["winding_3"] == WindingType.wye_n - - assert result[11]["clock_12"] == result[11]["clock_13"] == 2 - assert result[12]["clock_12"] == result[12]["clock_13"] == 1 + # Act + converter._create_pgm_input_three_winding_transformers() + result = converter.pgm_input_data[ComponentType.three_winding_transformer] + + # Assert + assert result[0]["tap_side"] == Branch3Side.side_1.value + assert result[1]["tap_side"] == Branch3Side.side_2.value + assert result[2]["tap_side"] == Branch3Side.side_3.value + assert result[3]["tap_side"] == Branch3Side.side_1.value + assert result[4]["tap_side"] == Branch3Side.side_1.value + assert result[5]["tap_side"] == Branch3Side.side_1.value + assert result[0]["tap_pos"] == 34.0 != result[0]["tap_nom"] + assert result[1]["tap_pos"] == 34.0 != result[1]["tap_nom"] + assert result[2]["tap_pos"] == 34.0 != result[2]["tap_nom"] + assert result[3]["tap_pos"] == 0 == result[3]["tap_nom"] + assert result[4]["tap_pos"] == 0 == result[4]["tap_nom"] + assert result[5]["tap_pos"] == 0 == result[5]["tap_nom"] + assert result[6]["tap_size"] == 0 + + # Default yndd for odd clocks + assert result[7]["winding_1"] == WindingType.wye_n + assert result[7]["winding_2"] == WindingType.delta + assert result[7]["winding_3"] == WindingType.delta + # Default ynynyn for even clocks + assert result[8]["winding_1"] == WindingType.wye_n + assert result[8]["winding_2"] == WindingType.wye_n + assert result[8]["winding_3"] == WindingType.wye_n + # Default ynynd for clock_12 even clock_13 odd + assert result[9]["winding_1"] == WindingType.wye_n + assert result[9]["winding_2"] == WindingType.wye_n + assert result[9]["winding_3"] == WindingType.delta + # Default yndyn for clock_12 odd clock_13 even + assert result[10]["winding_1"] == WindingType.wye_n + assert result[10]["winding_2"] == WindingType.delta + assert result[10]["winding_3"] == WindingType.wye_n + + assert result[11]["clock_12"] == result[11]["clock_13"] == 2 + assert result[12]["clock_12"] == result[12]["clock_13"] == 1 @pytest.mark.parametrize( @@ -1455,22 +1468,25 @@ def test_create_pgm_input_transformers3w__default() -> None: new=MagicMock(return_value=pd.Series([0])), ) def test_create_pgm_input_transformers3w__warnings(kwargs) -> None: - # Arrange - pp_net: PandaPowerNet = pp.create_empty_network() - pp.create_bus(net=pp_net, vn_kv=0.0) - args = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - if "pfe_kw" in kwargs: - args[-2] = kwargs["pfe_kw"] - kwargs = {} - pp.create_transformer3w_from_parameters(pp_net, *args, **kwargs) + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + pp_net: PandaPowerNet = pp.create_empty_network() + pp.create_bus(net=pp_net, vn_kv=0.0) + args = [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0] + if "pfe_kw" in kwargs: + args[-2] = kwargs["pfe_kw"] + kwargs = {} + pp.create_transformer3w_from_parameters(pp_net, *args, **kwargs) - converter = PandaPowerConverter() - converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} + converter = PandaPowerConverter() + converter.pp_input_data = {k: v for k, v in pp_net.items() if isinstance(v, pd.DataFrame)} - # Act - with patch("power_grid_model_io.converters.pandapower_converter.logger") as mock_logger: - converter._create_pgm_input_three_winding_transformers() - mock_logger.warning.assert_called_once() + # Act + with patch("power_grid_model_io.converters.pandapower_converter.logger") as mock_logger: + converter._create_pgm_input_three_winding_transformers() + mock_logger.warning.assert_called_once() def test_create_pgm_input_three_winding_transformers__tap_at_star_point() -> None: diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index 71bb1f02..55ad295e 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -40,7 +40,11 @@ def load_validation_data() -> Tuple[SingleDataset, ExtraInfo]: """ Load the validation data from the json file """ - data, extra_info = load_json_single_dataset(VALIDATION_FILE, data_type="input") + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + + data, extra_info = load_json_single_dataset(VALIDATION_FILE, data_type="input") + return data, extra_info @@ -68,11 +72,14 @@ def test_input_data(input_data: Tuple[SingleDataset, SingleDataset]): """ Unit test to preload the expected and actual data """ - # Arrange - actual, expected = input_data + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + actual, expected = input_data - # Assert - assert len(expected) <= len(actual) + # Assert + assert len(expected) <= len(actual) @pytest.mark.parametrize(("component", "attribute"), component_attributes(VALIDATION_FILE, data_type=DatasetType.input)) @@ -80,17 +87,20 @@ def test_attributes(input_data: Tuple[SingleDataset, SingleDataset], component: """ For each attribute, check if the actual values are consistent with the expected values """ - # Arrange - actual_data, expected_data = input_data + with warnings.catch_warnings(): + warnings.simplefilter("error") - # Act - actual_values, expected_values = select_values(actual_data, expected_data, component, attribute) + # Arrange + actual_data, expected_data = input_data - # Assert - if isinstance(actual_values, pd.Series) and isinstance(expected_values, pd.Series): - pd.testing.assert_series_equal(actual_values, expected_values) - else: - pd.testing.assert_frame_equal(actual_values, expected_values) + # Act + actual_values, expected_values = select_values(actual_data, expected_data, component, attribute) + + # Assert + if isinstance(actual_values, pd.Series) and isinstance(expected_values, pd.Series): + pd.testing.assert_series_equal(actual_values, expected_values) + else: + pd.testing.assert_frame_equal(actual_values, expected_values) @pytest.mark.parametrize( @@ -101,23 +111,29 @@ def test_extra_info(extra_info: Tuple[ExtraInfo, ExtraInfo], component: str, obj """ For each object, check if the actual extra info is consistent with the expected extra info """ - # Arrange - actual, expected = extra_info + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + actual, expected = extra_info - # Assert - errors = compare_extra_info(actual=actual, expected=expected, component=component, obj_ids=obj_ids) + # Assert + errors = compare_extra_info(actual=actual, expected=expected, component=component, obj_ids=obj_ids) - # Raise a value error, containing all the errors at once - if errors: - raise ValueError("\n" + "\n".join(errors)) + # Raise a value error, containing all the errors at once + if errors: + raise ValueError("\n" + "\n".join(errors)) def test_extra_info__serializable(extra_info): - # Arrange - actual, _expected = extra_info + with warnings.catch_warnings(): + warnings.simplefilter("error") + + # Arrange + actual, _expected = extra_info - # Assert - json.dumps(actual, cls=JsonEncoder) # expect no exception + # Assert + json.dumps(actual, cls=JsonEncoder) # expect no exception def test_pgm_input_lines__cnf_zero(): From 8ffafd193ab83899a9cb74db8fa35d28c577cf7f Mon Sep 17 00:00:00 2001 From: furqan463 Date: Fri, 5 Sep 2025 22:05:13 +0500 Subject: [PATCH 26/28] Upload data file Signed-off-by: furqan463 --- .../pp_v2_net_3ph_output_current_loading.json | 3161 +++++++++++++++++ 1 file changed, 3161 insertions(+) create mode 100644 tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json diff --git a/tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json b/tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json new file mode 100644 index 00000000..5c57a529 --- /dev/null +++ b/tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json @@ -0,0 +1,3161 @@ +{ + "_module": "pandapower.auxiliary", + "_class": "pandapowerNet", + "_object": { + "bus": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"vn_kv\",\"type\",\"zone\",\"in_service\"],\"index\":[101,102,103,106],\"data\":[[null,110.0,\"b\",null,true],[null,20.0,\"b\",null,true],[null,20.0,\"b\",null,true],[null,110.0,\"b\",null,true]]}", + "orient": "split", + "dtype": { + "name": "object", + "vn_kv": "float64", + "type": "object", + "zone": "object", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "load": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"p_mw\",\"q_mvar\",\"const_z_percent\",\"const_i_percent\",\"sn_mva\",\"scaling\",\"in_service\",\"type\"],\"index\":[101],\"data\":[[null,103,2.5,0.24,0.0,0.0,null,1.0,true,\"wye\"]]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "p_mw": "float64", + "q_mvar": "float64", + "const_z_percent": "float64", + "const_i_percent": "float64", + "sn_mva": "float64", + "scaling": "float64", + "in_service": "bool", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "sgen": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"p_mw\",\"q_mvar\",\"sn_mva\",\"scaling\",\"in_service\",\"type\",\"current_source\"],\"index\":[31],\"data\":[[null,103,1.21,0.81,null,1.0,true,\"wye\",true]]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "int64", + "p_mw": "float64", + "q_mvar": "float64", + "sn_mva": "float64", + "scaling": "float64", + "in_service": "bool", + "type": "object", + "current_source": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "motor": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"pn_mech_mw\",\"loading_percent\",\"cos_phi\",\"cos_phi_n\",\"efficiency_percent\",\"efficiency_n_percent\",\"lrc_pu\",\"vn_kv\",\"scaling\",\"in_service\",\"rx\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "int64", + "pn_mech_mw": "float64", + "loading_percent": "float64", + "cos_phi": "float64", + "cos_phi_n": "float64", + "efficiency_percent": "float64", + "efficiency_n_percent": "float64", + "lrc_pu": "float64", + "vn_kv": "float64", + "scaling": "float64", + "in_service": "bool", + "rx": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "asymmetric_load": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"p_a_mw\",\"q_a_mvar\",\"p_b_mw\",\"q_b_mvar\",\"p_c_mw\",\"q_c_mvar\",\"sn_mva\",\"scaling\",\"in_service\",\"type\"],\"index\":[33],\"data\":[[null,103,0.4,0.01,0.5,0.01,1.0,0.01,null,1.0,true,\"wye\"]]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "p_a_mw": "float64", + "q_a_mvar": "float64", + "p_b_mw": "float64", + "q_b_mvar": "float64", + "p_c_mw": "float64", + "q_c_mvar": "float64", + "sn_mva": "float64", + "scaling": "float64", + "in_service": "bool", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "asymmetric_sgen": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"p_a_mw\",\"q_a_mvar\",\"p_b_mw\",\"q_b_mvar\",\"p_c_mw\",\"q_c_mvar\",\"sn_mva\",\"scaling\",\"in_service\",\"type\",\"current_source\"],\"index\":[32],\"data\":[[null,103,0.1,0.01,0.2,0.01,3.0,0.01,null,1.0,true,\"wye\",null]]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "int64", + "p_a_mw": "float64", + "q_a_mvar": "float64", + "p_b_mw": "float64", + "q_b_mvar": "float64", + "p_c_mw": "float64", + "q_c_mvar": "float64", + "sn_mva": "float64", + "scaling": "float64", + "in_service": "bool", + "type": "object", + "current_source": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "storage": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"p_mw\",\"q_mvar\",\"sn_mva\",\"soc_percent\",\"min_e_mwh\",\"max_e_mwh\",\"scaling\",\"in_service\",\"type\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "int64", + "p_mw": "float64", + "q_mvar": "float64", + "sn_mva": "float64", + "soc_percent": "float64", + "min_e_mwh": "float64", + "max_e_mwh": "float64", + "scaling": "float64", + "in_service": "bool", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "gen": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"p_mw\",\"vm_pu\",\"sn_mva\",\"min_q_mvar\",\"max_q_mvar\",\"scaling\",\"slack\",\"in_service\",\"slack_weight\",\"type\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "p_mw": "float64", + "vm_pu": "float64", + "sn_mva": "float64", + "min_q_mvar": "float64", + "max_q_mvar": "float64", + "scaling": "float64", + "slack": "bool", + "in_service": "bool", + "slack_weight": "float64", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "switch": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"bus\",\"element\",\"et\",\"type\",\"closed\",\"name\",\"z_ohm\",\"in_ka\"],\"index\":[101,3021,321],\"data\":[[103,101,\"l\",null,true,null,0.0,null],[101,106,\"b\",null,true,null,0.0,null],[101,0,\"t\",null,true,null,0.0,null]]}", + "orient": "split", + "dtype": { + "bus": "int64", + "element": "int64", + "et": "object", + "type": "object", + "closed": "bool", + "name": "object", + "z_ohm": "float64", + "in_ka": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "shunt": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"bus\",\"name\",\"q_mvar\",\"p_mw\",\"vn_kv\",\"step\",\"max_step\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "bus": "uint32", + "name": "object", + "q_mvar": "float64", + "p_mw": "float64", + "vn_kv": "float64", + "step": "uint32", + "max_step": "uint32", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "svc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"x_l_ohm\",\"x_cvar_ohm\",\"set_vm_pu\",\"thyristor_firing_angle_degree\",\"controllable\",\"in_service\",\"min_angle_degree\",\"max_angle_degree\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "x_l_ohm": "float64", + "x_cvar_ohm": "float64", + "set_vm_pu": "float64", + "thyristor_firing_angle_degree": "float64", + "controllable": "bool", + "in_service": "bool", + "min_angle_degree": "float64", + "max_angle_degree": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "ssc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"r_ohm\",\"x_ohm\",\"vm_internal_pu\",\"va_internal_degree\",\"set_vm_pu\",\"controllable\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "r_ohm": "float64", + "x_ohm": "float64", + "vm_internal_pu": "float64", + "va_internal_degree": "float64", + "set_vm_pu": "float64", + "controllable": "bool", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "ext_grid": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"vm_pu\",\"va_degree\",\"slack_weight\",\"in_service\",\"x0x_max\",\"r0x0_max\",\"s_sc_max_mva\",\"rx_max\"],\"index\":[0],\"data\":[[null,101,1.0,0.0,1.0,true,1.0,0.0,10000000000.0,0.0]]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "vm_pu": "float64", + "va_degree": "float64", + "slack_weight": "float64", + "in_service": "bool", + "x0x_max": "float64", + "r0x0_max": "float64", + "s_sc_max_mva": "float64", + "rx_max": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "line": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"std_type\",\"from_bus\",\"to_bus\",\"length_km\",\"r_ohm_per_km\",\"x_ohm_per_km\",\"c_nf_per_km\",\"g_us_per_km\",\"max_i_ka\",\"df\",\"parallel\",\"type\",\"in_service\",\"r0_ohm_per_km\",\"x0_ohm_per_km\",\"c0_nf_per_km\",\"g0_us_per_km\"],\"index\":[101],\"data\":[[null,null,103,102,1.23,0.208,0.08,261.0,0.0,0.27,0.2,2,null,true,0.208,0.08,261.0,0.0]]}", + "orient": "split", + "dtype": { + "name": "object", + "std_type": "object", + "from_bus": "uint32", + "to_bus": "uint32", + "length_km": "float64", + "r_ohm_per_km": "float64", + "x_ohm_per_km": "float64", + "c_nf_per_km": "float64", + "g_us_per_km": "float64", + "max_i_ka": "float64", + "df": "float64", + "parallel": "uint32", + "type": "object", + "in_service": "bool", + "r0_ohm_per_km": "float64", + "x0_ohm_per_km": "float64", + "c0_nf_per_km": "float64", + "g0_us_per_km": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "trafo": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"std_type\",\"hv_bus\",\"lv_bus\",\"sn_mva\",\"vn_hv_kv\",\"vn_lv_kv\",\"vk_percent\",\"vkr_percent\",\"pfe_kw\",\"i0_percent\",\"shift_degree\",\"tap_side\",\"tap_neutral\",\"tap_min\",\"tap_max\",\"tap_step_percent\",\"tap_step_degree\",\"tap_pos\",\"tap_phase_shifter\",\"parallel\",\"df\",\"in_service\",\"vk0_percent\",\"vkr0_percent\",\"mag0_percent\",\"mag0_rx\",\"si0_hv_partial\",\"vector_group\",\"xn_ohm\",\"k_st\"],\"index\":[0],\"data\":[[null,null,101,102,40.0,110.0,20.0,8.9,4.0,51.600000000000001,0.3,0.0,\"hv\",1,-1,3,2.0,null,1,false,2,1.0,true,8.9,4.0,374531.835205992450938,0.47628073,0.9,\"YNyn\",0.0,1.0]]}", + "orient": "split", + "dtype": { + "name": "object", + "std_type": "object", + "hv_bus": "uint32", + "lv_bus": "uint32", + "sn_mva": "float64", + "vn_hv_kv": "float64", + "vn_lv_kv": "float64", + "vk_percent": "float64", + "vkr_percent": "float64", + "pfe_kw": "float64", + "i0_percent": "float64", + "shift_degree": "float64", + "tap_side": "object", + "tap_neutral": "int32", + "tap_min": "int32", + "tap_max": "int32", + "tap_step_percent": "float64", + "tap_step_degree": "float64", + "tap_pos": "int32", + "tap_phase_shifter": "bool", + "parallel": "uint32", + "df": "float64", + "in_service": "bool", + "vk0_percent": "float64", + "vkr0_percent": "float64", + "mag0_percent": "float64", + "mag0_rx": "float64", + "si0_hv_partial": "float64", + "vector_group": "object", + "xn_ohm": "float64", + "k_st": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "trafo3w": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"std_type\",\"hv_bus\",\"mv_bus\",\"lv_bus\",\"sn_hv_mva\",\"sn_mv_mva\",\"sn_lv_mva\",\"vn_hv_kv\",\"vn_mv_kv\",\"vn_lv_kv\",\"vk_hv_percent\",\"vk_mv_percent\",\"vk_lv_percent\",\"vkr_hv_percent\",\"vkr_mv_percent\",\"vkr_lv_percent\",\"pfe_kw\",\"i0_percent\",\"shift_mv_degree\",\"shift_lv_degree\",\"tap_side\",\"tap_neutral\",\"tap_min\",\"tap_max\",\"tap_step_percent\",\"tap_step_degree\",\"tap_pos\",\"tap_at_star_point\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "std_type": "object", + "hv_bus": "uint32", + "mv_bus": "uint32", + "lv_bus": "uint32", + "sn_hv_mva": "float64", + "sn_mv_mva": "float64", + "sn_lv_mva": "float64", + "vn_hv_kv": "float64", + "vn_mv_kv": "float64", + "vn_lv_kv": "float64", + "vk_hv_percent": "float64", + "vk_mv_percent": "float64", + "vk_lv_percent": "float64", + "vkr_hv_percent": "float64", + "vkr_mv_percent": "float64", + "vkr_lv_percent": "float64", + "pfe_kw": "float64", + "i0_percent": "float64", + "shift_mv_degree": "float64", + "shift_lv_degree": "float64", + "tap_side": "object", + "tap_neutral": "int32", + "tap_min": "int32", + "tap_max": "int32", + "tap_step_percent": "float64", + "tap_step_degree": "float64", + "tap_pos": "int32", + "tap_at_star_point": "bool", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "impedance": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"from_bus\",\"to_bus\",\"rft_pu\",\"xft_pu\",\"rtf_pu\",\"xtf_pu\",\"sn_mva\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "from_bus": "uint32", + "to_bus": "uint32", + "rft_pu": "float64", + "xft_pu": "float64", + "rtf_pu": "float64", + "xtf_pu": "float64", + "sn_mva": "float64", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "tcsc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"from_bus\",\"to_bus\",\"x_l_ohm\",\"x_cvar_ohm\",\"set_p_to_mw\",\"thyristor_firing_angle_degree\",\"controllable\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "from_bus": "uint32", + "to_bus": "uint32", + "x_l_ohm": "float64", + "x_cvar_ohm": "float64", + "set_p_to_mw": "float64", + "thyristor_firing_angle_degree": "float64", + "controllable": "bool", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "dcline": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"from_bus\",\"to_bus\",\"p_mw\",\"loss_percent\",\"loss_mw\",\"vm_from_pu\",\"vm_to_pu\",\"max_p_mw\",\"min_q_from_mvar\",\"min_q_to_mvar\",\"max_q_from_mvar\",\"max_q_to_mvar\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "from_bus": "uint32", + "to_bus": "uint32", + "p_mw": "float64", + "loss_percent": "float64", + "loss_mw": "float64", + "vm_from_pu": "float64", + "vm_to_pu": "float64", + "max_p_mw": "float64", + "min_q_from_mvar": "float64", + "min_q_to_mvar": "float64", + "max_q_from_mvar": "float64", + "max_q_to_mvar": "float64", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "ward": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"ps_mw\",\"qs_mvar\",\"qz_mvar\",\"pz_mw\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "ps_mw": "float64", + "qs_mvar": "float64", + "qz_mvar": "float64", + "pz_mw": "float64", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "xward": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"bus\",\"ps_mw\",\"qs_mvar\",\"qz_mvar\",\"pz_mw\",\"r_ohm\",\"x_ohm\",\"vm_pu\",\"slack_weight\",\"in_service\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "bus": "uint32", + "ps_mw": "float64", + "qs_mvar": "float64", + "qz_mvar": "float64", + "pz_mw": "float64", + "r_ohm": "float64", + "x_ohm": "float64", + "vm_pu": "float64", + "slack_weight": "float64", + "in_service": "bool" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "measurement": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"measurement_type\",\"element_type\",\"element\",\"value\",\"std_dev\",\"side\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "measurement_type": "object", + "element_type": "object", + "element": "uint32", + "value": "float64", + "std_dev": "float64", + "side": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "pwl_cost": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"power_type\",\"element\",\"et\",\"points\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "power_type": "object", + "element": "uint32", + "et": "object", + "points": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "poly_cost": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"element\",\"et\",\"cp0_eur\",\"cp1_eur_per_mw\",\"cp2_eur_per_mw2\",\"cq0_eur\",\"cq1_eur_per_mvar\",\"cq2_eur_per_mvar2\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "element": "uint32", + "et": "object", + "cp0_eur": "float64", + "cp1_eur_per_mw": "float64", + "cp2_eur_per_mw2": "float64", + "cq0_eur": "float64", + "cq1_eur_per_mvar": "float64", + "cq2_eur_per_mvar2": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "characteristic": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"object\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "object": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "controller": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"object\",\"in_service\",\"order\",\"level\",\"initial_run\",\"recycle\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "object": "object", + "in_service": "bool", + "order": "float64", + "level": "object", + "initial_run": "bool", + "recycle": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "group": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"element_type\",\"element\",\"reference_column\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "name": "object", + "element_type": "object", + "element": "object", + "reference_column": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "line_geodata": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"coords\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "coords": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "bus_geodata": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"x\",\"y\",\"coords\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "x": "float64", + "y": "float64", + "coords": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "version": "2.14.10", + "format_version": "2.14.0", + "converged": true, + "OPF_converged": false, + "name": "", + "f_hz": 50, + "sn_mva": 1, + "std_types": { + "line": { + "NAYY 4x50 SE": { + "c_nf_per_km": 210, + "r_ohm_per_km": 0.642, + "x_ohm_per_km": 0.083, + "max_i_ka": 0.142, + "type": "cs", + "q_mm2": 50, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "NAYY 4x120 SE": { + "c_nf_per_km": 264, + "r_ohm_per_km": 0.225, + "x_ohm_per_km": 0.08, + "max_i_ka": 0.242, + "type": "cs", + "q_mm2": 120, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "NAYY 4x150 SE": { + "c_nf_per_km": 261, + "r_ohm_per_km": 0.208, + "x_ohm_per_km": 0.08, + "max_i_ka": 0.27, + "type": "cs", + "q_mm2": 150, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "NA2XS2Y 1x95 RM/25 12/20 kV": { + "c_nf_per_km": 216, + "r_ohm_per_km": 0.313, + "x_ohm_per_km": 0.132, + "max_i_ka": 0.252, + "type": "cs", + "q_mm2": 95, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x185 RM/25 12/20 kV": { + "c_nf_per_km": 273, + "r_ohm_per_km": 0.161, + "x_ohm_per_km": 0.117, + "max_i_ka": 0.362, + "type": "cs", + "q_mm2": 185, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x240 RM/25 12/20 kV": { + "c_nf_per_km": 304, + "r_ohm_per_km": 0.122, + "x_ohm_per_km": 0.112, + "max_i_ka": 0.421, + "type": "cs", + "q_mm2": 240, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x95 RM/25 6/10 kV": { + "c_nf_per_km": 315, + "r_ohm_per_km": 0.313, + "x_ohm_per_km": 0.123, + "max_i_ka": 0.249, + "type": "cs", + "q_mm2": 95, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x185 RM/25 6/10 kV": { + "c_nf_per_km": 406, + "r_ohm_per_km": 0.161, + "x_ohm_per_km": 0.11, + "max_i_ka": 0.358, + "type": "cs", + "q_mm2": 185, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x240 RM/25 6/10 kV": { + "c_nf_per_km": 456, + "r_ohm_per_km": 0.122, + "x_ohm_per_km": 0.105, + "max_i_ka": 0.416, + "type": "cs", + "q_mm2": 240, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x150 RM/25 12/20 kV": { + "c_nf_per_km": 250, + "r_ohm_per_km": 0.206, + "x_ohm_per_km": 0.116, + "max_i_ka": 0.319, + "type": "cs", + "q_mm2": 150, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x120 RM/25 12/20 kV": { + "c_nf_per_km": 230, + "r_ohm_per_km": 0.253, + "x_ohm_per_km": 0.119, + "max_i_ka": 0.283, + "type": "cs", + "q_mm2": 120, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x70 RM/25 12/20 kV": { + "c_nf_per_km": 190, + "r_ohm_per_km": 0.443, + "x_ohm_per_km": 0.132, + "max_i_ka": 0.22, + "type": "cs", + "q_mm2": 70, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x150 RM/25 6/10 kV": { + "c_nf_per_km": 360, + "r_ohm_per_km": 0.206, + "x_ohm_per_km": 0.11, + "max_i_ka": 0.315, + "type": "cs", + "q_mm2": 150, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x120 RM/25 6/10 kV": { + "c_nf_per_km": 340, + "r_ohm_per_km": 0.253, + "x_ohm_per_km": 0.113, + "max_i_ka": 0.28, + "type": "cs", + "q_mm2": 120, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "NA2XS2Y 1x70 RM/25 6/10 kV": { + "c_nf_per_km": 280, + "r_ohm_per_km": 0.443, + "x_ohm_per_km": 0.123, + "max_i_ka": 0.217, + "type": "cs", + "q_mm2": 70, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "N2XS(FL)2Y 1x120 RM/35 64/110 kV": { + "c_nf_per_km": 112, + "r_ohm_per_km": 0.153, + "x_ohm_per_km": 0.166, + "max_i_ka": 0.366, + "type": "cs", + "q_mm2": 120, + "alpha": 0.00393, + "voltage_rating": "HV" + }, + "N2XS(FL)2Y 1x185 RM/35 64/110 kV": { + "c_nf_per_km": 125, + "r_ohm_per_km": 0.099, + "x_ohm_per_km": 0.156, + "max_i_ka": 0.457, + "type": "cs", + "q_mm2": 185, + "alpha": 0.00393, + "voltage_rating": "HV" + }, + "N2XS(FL)2Y 1x240 RM/35 64/110 kV": { + "c_nf_per_km": 135, + "r_ohm_per_km": 0.075, + "x_ohm_per_km": 0.149, + "max_i_ka": 0.526, + "type": "cs", + "q_mm2": 240, + "alpha": 0.00393, + "voltage_rating": "HV" + }, + "N2XS(FL)2Y 1x300 RM/35 64/110 kV": { + "c_nf_per_km": 144, + "r_ohm_per_km": 0.06, + "x_ohm_per_km": 0.144, + "max_i_ka": 0.588, + "type": "cs", + "q_mm2": 300, + "alpha": 0.00393, + "voltage_rating": "HV" + }, + "15-AL1/3-ST1A 0.4": { + "c_nf_per_km": 11, + "r_ohm_per_km": 1.8769, + "x_ohm_per_km": 0.35, + "max_i_ka": 0.105, + "type": "ol", + "q_mm2": 16, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "24-AL1/4-ST1A 0.4": { + "c_nf_per_km": 11.25, + "r_ohm_per_km": 1.2012, + "x_ohm_per_km": 0.335, + "max_i_ka": 0.14, + "type": "ol", + "q_mm2": 24, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "48-AL1/8-ST1A 0.4": { + "c_nf_per_km": 12.2, + "r_ohm_per_km": 0.5939, + "x_ohm_per_km": 0.3, + "max_i_ka": 0.21, + "type": "ol", + "q_mm2": 48, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "94-AL1/15-ST1A 0.4": { + "c_nf_per_km": 13.2, + "r_ohm_per_km": 0.306, + "x_ohm_per_km": 0.29, + "max_i_ka": 0.35, + "type": "ol", + "q_mm2": 94, + "alpha": 0.00403, + "voltage_rating": "LV" + }, + "34-AL1/6-ST1A 10.0": { + "c_nf_per_km": 9.7, + "r_ohm_per_km": 0.8342, + "x_ohm_per_km": 0.36, + "max_i_ka": 0.17, + "type": "ol", + "q_mm2": 34, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "48-AL1/8-ST1A 10.0": { + "c_nf_per_km": 10.1, + "r_ohm_per_km": 0.5939, + "x_ohm_per_km": 0.35, + "max_i_ka": 0.21, + "type": "ol", + "q_mm2": 48, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "70-AL1/11-ST1A 10.0": { + "c_nf_per_km": 10.4, + "r_ohm_per_km": 0.4132, + "x_ohm_per_km": 0.339, + "max_i_ka": 0.29, + "type": "ol", + "q_mm2": 70, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "94-AL1/15-ST1A 10.0": { + "c_nf_per_km": 10.75, + "r_ohm_per_km": 0.306, + "x_ohm_per_km": 0.33, + "max_i_ka": 0.35, + "type": "ol", + "q_mm2": 94, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "122-AL1/20-ST1A 10.0": { + "c_nf_per_km": 11.1, + "r_ohm_per_km": 0.2376, + "x_ohm_per_km": 0.323, + "max_i_ka": 0.41, + "type": "ol", + "q_mm2": 122, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "149-AL1/24-ST1A 10.0": { + "c_nf_per_km": 11.25, + "r_ohm_per_km": 0.194, + "x_ohm_per_km": 0.315, + "max_i_ka": 0.47, + "type": "ol", + "q_mm2": 149, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "34-AL1/6-ST1A 20.0": { + "c_nf_per_km": 9.15, + "r_ohm_per_km": 0.8342, + "x_ohm_per_km": 0.382, + "max_i_ka": 0.17, + "type": "ol", + "q_mm2": 34, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "48-AL1/8-ST1A 20.0": { + "c_nf_per_km": 9.5, + "r_ohm_per_km": 0.5939, + "x_ohm_per_km": 0.372, + "max_i_ka": 0.21, + "type": "ol", + "q_mm2": 48, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "70-AL1/11-ST1A 20.0": { + "c_nf_per_km": 9.7, + "r_ohm_per_km": 0.4132, + "x_ohm_per_km": 0.36, + "max_i_ka": 0.29, + "type": "ol", + "q_mm2": 70, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "94-AL1/15-ST1A 20.0": { + "c_nf_per_km": 10, + "r_ohm_per_km": 0.306, + "x_ohm_per_km": 0.35, + "max_i_ka": 0.35, + "type": "ol", + "q_mm2": 94, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "122-AL1/20-ST1A 20.0": { + "c_nf_per_km": 10.3, + "r_ohm_per_km": 0.2376, + "x_ohm_per_km": 0.344, + "max_i_ka": 0.41, + "type": "ol", + "q_mm2": 122, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "149-AL1/24-ST1A 20.0": { + "c_nf_per_km": 10.5, + "r_ohm_per_km": 0.194, + "x_ohm_per_km": 0.337, + "max_i_ka": 0.47, + "type": "ol", + "q_mm2": 149, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "184-AL1/30-ST1A 20.0": { + "c_nf_per_km": 10.75, + "r_ohm_per_km": 0.1571, + "x_ohm_per_km": 0.33, + "max_i_ka": 0.535, + "type": "ol", + "q_mm2": 184, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "243-AL1/39-ST1A 20.0": { + "c_nf_per_km": 11, + "r_ohm_per_km": 0.1188, + "x_ohm_per_km": 0.32, + "max_i_ka": 0.645, + "type": "ol", + "q_mm2": 243, + "alpha": 0.00403, + "voltage_rating": "MV" + }, + "48-AL1/8-ST1A 110.0": { + "c_nf_per_km": 8, + "r_ohm_per_km": 0.5939, + "x_ohm_per_km": 0.46, + "max_i_ka": 0.21, + "type": "ol", + "q_mm2": 48, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "70-AL1/11-ST1A 110.0": { + "c_nf_per_km": 8.4, + "r_ohm_per_km": 0.4132, + "x_ohm_per_km": 0.45, + "max_i_ka": 0.29, + "type": "ol", + "q_mm2": 70, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "94-AL1/15-ST1A 110.0": { + "c_nf_per_km": 8.65, + "r_ohm_per_km": 0.306, + "x_ohm_per_km": 0.44, + "max_i_ka": 0.35, + "type": "ol", + "q_mm2": 94, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "122-AL1/20-ST1A 110.0": { + "c_nf_per_km": 8.5, + "r_ohm_per_km": 0.2376, + "x_ohm_per_km": 0.43, + "max_i_ka": 0.41, + "type": "ol", + "q_mm2": 122, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "149-AL1/24-ST1A 110.0": { + "c_nf_per_km": 8.75, + "r_ohm_per_km": 0.194, + "x_ohm_per_km": 0.41, + "max_i_ka": 0.47, + "type": "ol", + "q_mm2": 149, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "184-AL1/30-ST1A 110.0": { + "c_nf_per_km": 8.8, + "r_ohm_per_km": 0.1571, + "x_ohm_per_km": 0.4, + "max_i_ka": 0.535, + "type": "ol", + "q_mm2": 184, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "243-AL1/39-ST1A 110.0": { + "c_nf_per_km": 9, + "r_ohm_per_km": 0.1188, + "x_ohm_per_km": 0.39, + "max_i_ka": 0.645, + "type": "ol", + "q_mm2": 243, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "305-AL1/39-ST1A 110.0": { + "c_nf_per_km": 9.2, + "r_ohm_per_km": 0.0949, + "x_ohm_per_km": 0.38, + "max_i_ka": 0.74, + "type": "ol", + "q_mm2": 305, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "490-AL1/64-ST1A 110.0": { + "c_nf_per_km": 9.75, + "r_ohm_per_km": 0.059, + "x_ohm_per_km": 0.37, + "max_i_ka": 0.96, + "type": "ol", + "q_mm2": 490, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "679-AL1/86-ST1A 110.0": { + "c_nf_per_km": 9.95, + "r_ohm_per_km": 0.042, + "x_ohm_per_km": 0.36, + "max_i_ka": 1.15, + "type": "ol", + "q_mm2": 679, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "490-AL1/64-ST1A 220.0": { + "c_nf_per_km": 10, + "r_ohm_per_km": 0.059, + "x_ohm_per_km": 0.285, + "max_i_ka": 0.96, + "type": "ol", + "q_mm2": 490, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "679-AL1/86-ST1A 220.0": { + "c_nf_per_km": 11.7, + "r_ohm_per_km": 0.042, + "x_ohm_per_km": 0.275, + "max_i_ka": 1.15, + "type": "ol", + "q_mm2": 679, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "490-AL1/64-ST1A 380.0": { + "c_nf_per_km": 11, + "r_ohm_per_km": 0.059, + "x_ohm_per_km": 0.253, + "max_i_ka": 0.96, + "type": "ol", + "q_mm2": 490, + "alpha": 0.00403, + "voltage_rating": "HV" + }, + "679-AL1/86-ST1A 380.0": { + "c_nf_per_km": 14.6, + "r_ohm_per_km": 0.042, + "x_ohm_per_km": 0.25, + "max_i_ka": 1.15, + "type": "ol", + "q_mm2": 679, + "alpha": 0.00403, + "voltage_rating": "HV" + } + }, + "trafo": { + "160 MVA 380/110 kV": { + "i0_percent": 0.06, + "pfe_kw": 60, + "vkr_percent": 0.25, + "sn_mva": 160, + "vn_lv_kv": 110.0, + "vn_hv_kv": 380.0, + "vk_percent": 12.2, + "shift_degree": 0, + "vector_group": "Yy0", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "100 MVA 220/110 kV": { + "i0_percent": 0.06, + "pfe_kw": 55, + "vkr_percent": 0.26, + "sn_mva": 100, + "vn_lv_kv": 110.0, + "vn_hv_kv": 220.0, + "vk_percent": 12.0, + "shift_degree": 0, + "vector_group": "Yy0", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "63 MVA 110/20 kV": { + "i0_percent": 0.04, + "pfe_kw": 22, + "vkr_percent": 0.32, + "sn_mva": 63, + "vn_lv_kv": 20.0, + "vn_hv_kv": 110.0, + "vk_percent": 18, + "shift_degree": 150, + "vector_group": "YNd5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "40 MVA 110/20 kV": { + "i0_percent": 0.05, + "pfe_kw": 18, + "vkr_percent": 0.34, + "sn_mva": 40, + "vn_lv_kv": 20.0, + "vn_hv_kv": 110.0, + "vk_percent": 16.2, + "shift_degree": 150, + "vector_group": "YNd5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "25 MVA 110/20 kV": { + "i0_percent": 0.07, + "pfe_kw": 14, + "vkr_percent": 0.41, + "sn_mva": 25, + "vn_lv_kv": 20.0, + "vn_hv_kv": 110.0, + "vk_percent": 12, + "shift_degree": 150, + "vector_group": "YNd5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "63 MVA 110/10 kV": { + "sn_mva": 63, + "vn_hv_kv": 110, + "vn_lv_kv": 10, + "vk_percent": 18, + "vkr_percent": 0.32, + "pfe_kw": 22, + "i0_percent": 0.04, + "shift_degree": 150, + "vector_group": "YNd5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "40 MVA 110/10 kV": { + "sn_mva": 40, + "vn_hv_kv": 110, + "vn_lv_kv": 10, + "vk_percent": 16.2, + "vkr_percent": 0.34, + "pfe_kw": 18, + "i0_percent": 0.05, + "shift_degree": 150, + "vector_group": "YNd5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "25 MVA 110/10 kV": { + "sn_mva": 25, + "vn_hv_kv": 110, + "vn_lv_kv": 10, + "vk_percent": 12, + "vkr_percent": 0.41, + "pfe_kw": 14, + "i0_percent": 0.07, + "shift_degree": 150, + "vector_group": "YNd5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -9, + "tap_max": 9, + "tap_step_degree": 0, + "tap_step_percent": 1.5, + "tap_phase_shifter": false + }, + "0.25 MVA 20/0.4 kV": { + "sn_mva": 0.25, + "vn_hv_kv": 20, + "vn_lv_kv": 0.4, + "vk_percent": 6, + "vkr_percent": 1.44, + "pfe_kw": 0.8, + "i0_percent": 0.32, + "shift_degree": 150, + "vector_group": "Yzn5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -2, + "tap_max": 2, + "tap_step_degree": 0, + "tap_step_percent": 2.5, + "tap_phase_shifter": false + }, + "0.4 MVA 20/0.4 kV": { + "sn_mva": 0.4, + "vn_hv_kv": 20, + "vn_lv_kv": 0.4, + "vk_percent": 6, + "vkr_percent": 1.425, + "pfe_kw": 1.35, + "i0_percent": 0.3375, + "shift_degree": 150, + "vector_group": "Dyn5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -2, + "tap_max": 2, + "tap_step_degree": 0, + "tap_step_percent": 2.5, + "tap_phase_shifter": false + }, + "0.63 MVA 20/0.4 kV": { + "sn_mva": 0.63, + "vn_hv_kv": 20, + "vn_lv_kv": 0.4, + "vk_percent": 6, + "vkr_percent": 1.206, + "pfe_kw": 1.65, + "i0_percent": 0.2619, + "shift_degree": 150, + "vector_group": "Dyn5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -2, + "tap_max": 2, + "tap_step_degree": 0, + "tap_step_percent": 2.5, + "tap_phase_shifter": false + }, + "0.25 MVA 10/0.4 kV": { + "sn_mva": 0.25, + "vn_hv_kv": 10, + "vn_lv_kv": 0.4, + "vk_percent": 4, + "vkr_percent": 1.2, + "pfe_kw": 0.6, + "i0_percent": 0.24, + "shift_degree": 150, + "vector_group": "Dyn5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -2, + "tap_max": 2, + "tap_step_degree": 0, + "tap_step_percent": 2.5, + "tap_phase_shifter": false + }, + "0.4 MVA 10/0.4 kV": { + "sn_mva": 0.4, + "vn_hv_kv": 10, + "vn_lv_kv": 0.4, + "vk_percent": 4, + "vkr_percent": 1.325, + "pfe_kw": 0.95, + "i0_percent": 0.2375, + "shift_degree": 150, + "vector_group": "Dyn5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -2, + "tap_max": 2, + "tap_step_degree": 0, + "tap_step_percent": 2.5, + "tap_phase_shifter": false + }, + "0.63 MVA 10/0.4 kV": { + "sn_mva": 0.63, + "vn_hv_kv": 10, + "vn_lv_kv": 0.4, + "vk_percent": 4, + "vkr_percent": 1.0794, + "pfe_kw": 1.18, + "i0_percent": 0.1873, + "shift_degree": 150, + "vector_group": "Dyn5", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -2, + "tap_max": 2, + "tap_step_degree": 0, + "tap_step_percent": 2.5, + "tap_phase_shifter": false + } + }, + "trafo3w": { + "63/25/38 MVA 110/20/10 kV": { + "sn_hv_mva": 63, + "sn_mv_mva": 25, + "sn_lv_mva": 38, + "vn_hv_kv": 110, + "vn_mv_kv": 20, + "vn_lv_kv": 10, + "vk_hv_percent": 10.4, + "vk_mv_percent": 10.4, + "vk_lv_percent": 10.4, + "vkr_hv_percent": 0.28, + "vkr_mv_percent": 0.32, + "vkr_lv_percent": 0.35, + "pfe_kw": 35, + "i0_percent": 0.89, + "shift_mv_degree": 0, + "shift_lv_degree": 0, + "vector_group": "YN0yn0yn0", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -10, + "tap_max": 10, + "tap_step_percent": 1.2 + }, + "63/25/38 MVA 110/10/10 kV": { + "sn_hv_mva": 63, + "sn_mv_mva": 25, + "sn_lv_mva": 38, + "vn_hv_kv": 110, + "vn_mv_kv": 10, + "vn_lv_kv": 10, + "vk_hv_percent": 10.4, + "vk_mv_percent": 10.4, + "vk_lv_percent": 10.4, + "vkr_hv_percent": 0.28, + "vkr_mv_percent": 0.32, + "vkr_lv_percent": 0.35, + "pfe_kw": 35, + "i0_percent": 0.89, + "shift_mv_degree": 0, + "shift_lv_degree": 0, + "vector_group": "YN0yn0yn0", + "tap_side": "hv", + "tap_neutral": 0, + "tap_min": -10, + "tap_max": 10, + "tap_step_percent": 1.2 + } + }, + "fuse": { + "HV 100A": { + "fuse_type": "HV 100A", + "i_rated_a": 100.0, + "t_avg": 0, + "t_min": [ + 10.0, + 3.64, + 0.854, + 0.281, + 0.1, + 0.0531, + 0.022, + 0.01 + ], + "t_total": [ + 10.0, + 4.267, + 1.21, + 0.403, + 0.1, + 0.058, + 0.022, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 300.0, + 350.0, + 450.0, + 550.0, + 700.0, + 850.0, + 1200.0, + 1752.0 + ], + "x_total": [ + 600.0, + 700.0, + 900.0, + 1150.0, + 1665.0, + 2000.0, + 3000.0, + 4313.0 + ] + }, + "HV 10A": { + "fuse_type": "HV 10A", + "i_rated_a": 10.0, + "t_avg": 0, + "t_min": [ + 10.0, + 1675.0, + 0.344, + 0.156, + 0.1, + 0.0417, + 0.0171, + 0.01 + ], + "t_total": [ + 10.0, + 1.3, + 0.3, + 0.155, + 0.1, + 0.0555, + 0.023, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 30.0, + 32.0, + 35.0, + 37.0, + 39.0, + 50.0, + 70.0, + 88.0 + ], + "x_total": [ + 60.0, + 70.0, + 80.0, + 87.0, + 94.0, + 110.0, + 150.0, + 216.0 + ] + }, + "HV 125A": { + "fuse_type": "HV 125A", + "i_rated_a": 125.0, + "t_avg": 0, + "t_min": [ + 10.0, + 1.82, + 0.344, + 0.1, + 0.0467, + 0.0269, + 0.01 + ], + "t_total": [ + 10.0, + 2.478, + 0.426, + 0.1, + 0.0427, + 0.0211, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 375.0, + 500.0, + 700.0, + 925.0, + 1200.0, + 1500.0, + 2341.0 + ], + "x_total": [ + 750.0, + 1000.0, + 1500.0, + 2200.0, + 3000.0, + 4000.0, + 5765.0 + ] + }, + "HV 160A": { + "fuse_type": "HV 160A", + "i_rated_a": 160.0, + "t_avg": 0, + "t_min": [ + 10.0, + 4.15, + 1.03, + 0.198, + 0.1, + 0.051, + 0.0172, + 0.01 + ], + "t_total": [ + 10.0, + 2.3, + 0.734, + 0.274, + 0.1, + 0.046, + 0.0177, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 480.0, + 550.0, + 700.0, + 1000.0, + 1260.0, + 1600.0, + 2500.0, + 3227.0 + ], + "x_total": [ + 960.0, + 1300.0, + 1700.0, + 2200.0, + 2996.0, + 4000.0, + 6000.0, + 7946.0 + ] + }, + "HV 16A": { + "fuse_type": "HV 16A", + "i_rated_a": 16.0, + "t_avg": 0, + "t_min": [ + 10.0, + 0.352, + 0.164, + 0.1, + 0.0649, + 0.0342, + 0.01 + ], + "t_total": [ + 10.0, + 2.34, + 0.722, + 0.181, + 0.1, + 0.055, + 0.0296, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 48.0, + 60.0, + 65.0, + 71.0, + 80.0, + 100.0, + 162.0 + ], + "x_total": [ + 96.0, + 110.0, + 125.0, + 150.0, + 168.0, + 200.0, + 250.0, + 398.0 + ] + }, + "HV 200A": { + "fuse_type": "HV 200A", + "i_rated_a": 200.0, + "t_avg": 0, + "t_min": [ + 10.0, + 4.267, + 1.21, + 0.403, + 0.1, + 0.058, + 0.022, + 0.01 + ], + "t_total": [ + 10.0, + 3.73, + 1.654, + 0.328, + 0.1, + 0.0531, + 0.019, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 600.0, + 700.0, + 900.0, + 1150.0, + 1665.0, + 2000.0, + 3000.0, + 4313.0 + ], + "x_total": [ + 1200.0, + 1500.0, + 1800.0, + 2700.0, + 3960.0, + 5000.0, + 7500.0, + 10620.0 + ] + }, + "HV 20A": { + "fuse_type": "HV 20A", + "i_rated_a": 20.0, + "t_avg": 0, + "t_min": [ + 10.0, + 1.3, + 0.3, + 0.155, + 0.1, + 0.0555, + 0.023, + 0.01 + ], + "t_total": [ + 10.0, + 1.3, + 0.161, + 0.1, + 0.0611, + 0.0399, + 0.0141, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 60.0, + 70.0, + 80.0, + 87.0, + 94.0, + 110.0, + 150.0, + 216.0 + ], + "x_total": [ + 120.0, + 150.0, + 200.0, + 223.0, + 260.0, + 300.0, + 450.0, + 532.0 + ] + }, + "HV 25A": { + "fuse_type": "HV 25A", + "i_rated_a": 25.0, + "t_avg": 0, + "t_min": [ + 10.0, + 2.512, + 0.833, + 0.299, + 0.1, + 0.0372, + 0.0223, + 0.01 + ], + "t_total": [ + 10.0, + 3.125, + 0.597, + 0.198, + 0.1, + 0.0378, + 0.022, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 75.0, + 82.0, + 90.0, + 100.0, + 124.0, + 170.0, + 200.0, + 289.0 + ], + "x_total": [ + 150.0, + 170.0, + 210.0, + 250.0, + 294.0, + 400.0, + 500.0, + 711.0 + ] + }, + "HV 31.5A": { + "fuse_type": "HV 31.5A", + "i_rated_a": 31.5, + "t_avg": 0, + "t_min": [ + 10.0, + 2.34, + 0.722, + 0.181, + 0.1, + 0.055, + 0.0296, + 0.01 + ], + "t_total": [ + 10.0, + 2.84, + 0.368, + 0.164, + 0.1, + 0.0621, + 0.0378, + 0.0195, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 95.0, + 110.0, + 125.0, + 150.0, + 165.0, + 200.0, + 250.0, + 390.0 + ], + "x_total": [ + 189.0, + 220.0, + 300.0, + 350.0, + 393.0, + 450.0, + 530.0, + 700.0, + 960.0 + ] + }, + "HV 40A": { + "fuse_type": "HV 40A", + "i_rated_a": 40.0, + "t_avg": 0, + "t_min": [ + 10.0, + 1.3, + 0.161, + 0.1, + 0.0611, + 0.0399, + 0.0141, + 0.01 + ], + "t_total": [ + 10.0, + 2.05, + 0.369, + 0.198, + 0.1, + 0.051, + 0.0298, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 120.0, + 150.0, + 200.0, + 223.0, + 260.0, + 300.0, + 450.0, + 532.0 + ], + "x_total": [ + 240.0, + 300.0, + 400.0, + 450.0, + 530.0, + 650.0, + 800.0, + 1311.0 + ] + }, + "HV 50A": { + "fuse_type": "HV 50A", + "i_rated_a": 50.0, + "t_avg": 0, + "t_min": [ + 10.0, + 3.215, + 0.597, + 0.198, + 0.1, + 0.0378, + 0.022, + 0.01 + ], + "t_total": [ + 10.0, + 3.64, + 0.854, + 0.281, + 0.1, + 0.0531, + 0.022, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 150.0, + 170.0, + 210.0, + 250.0, + 294.0, + 400.0, + 500.0, + 711.0 + ], + "x_total": [ + 300.0, + 350.0, + 450.0, + 550.0, + 700.0, + 850.0, + 1200.0, + 1752.0 + ] + }, + "HV 6.3A": { + "fuse_type": "HV 6.3A", + "i_rated_a": 6.3, + "t_avg": 0, + "t_min": [ + 10.0, + 1.39, + 0.344, + 0.168, + 0.1, + 0.056, + 0.0263, + 0.01 + ], + "t_total": [ + 10.0, + 1.711, + 0.516, + 0.198, + 0.1, + 0.0634, + 0.0303, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 19.0, + 19.5, + 20.4, + 20.8, + 22.0, + 25.0, + 32.0, + 48.0 + ], + "x_total": [ + 38.0, + 40.0, + 43.0, + 48.0, + 53.0, + 60.0, + 75.0, + 118.0 + ] + }, + "HV 63A": { + "fuse_type": "HV 63A", + "i_rated_a": 63.0, + "t_avg": 0, + "t_min": [ + 10.0, + 2.84, + 0.368, + 0.164, + 0.1, + 0.0621, + 0.0378, + 0.0195, + 0.01 + ], + "t_total": [ + 10.0, + 1.82, + 0.344, + 0.1, + 0.0467, + 0.0269, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 189.0, + 220.0, + 300.0, + 350.0, + 393.0, + 450.0, + 530.0, + 700.0, + 961.0 + ], + "x_total": [ + 378.0, + 500.0, + 700.0, + 934.0, + 1200.0, + 1500.0, + 2366.0 + ] + }, + "HV 80A": { + "fuse_type": "HV 80A", + "i_rated_a": 80.0, + "t_avg": 0, + "t_min": [ + 10.0, + 2.05, + 0.369, + 0.198, + 0.1, + 0.051, + 0.0298, + 0.01 + ], + "t_total": [ + 10.0, + 4.15, + 1.03, + 0.198, + 0.1, + 0.051, + 0.0172, + 0.01 + ], + "x_avg": 0, + "x_min": [ + 240.0, + 300.0, + 400.0, + 450.0, + 530.0, + 650.0, + 800.0, + 1311.0 + ], + "x_total": [ + 480.0, + 550.0, + 700.0, + 1000.0, + 1260.0, + 1600.0, + 2500.0, + 3227.0 + ] + }, + "Siemens NH-1-100": { + "fuse_type": "Siemens NH-1-100", + "i_rated_a": 100.0, + "t_avg": [ + 5400.0, + 2000.0, + 400.0, + 20.0, + 1.0, + 0.2, + 0.012, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 150.0, + 190.0, + 250.0, + 430.0, + 900.0, + 1250.0, + 2700.0, + 3600.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-125": { + "fuse_type": "Siemens NH-1-125", + "i_rated_a": 125.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 180.0, + 400.0, + 740.0, + 2000.0, + 4250.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-16": { + "fuse_type": "Siemens NH-1-16", + "i_rated_a": 16.0, + "t_avg": [ + 4000.0, + 400.0, + 2.0, + 0.1, + 0.04, + 0.01 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 26.0, + 35.0, + 75.0, + 150.0, + 200.0, + 300.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-160": { + "fuse_type": "Siemens NH-1-160", + "i_rated_a": 160.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 210.0, + 500.0, + 900.0, + 2300.0, + 5000.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-25": { + "fuse_type": "Siemens NH-1-25", + "i_rated_a": 25.0, + "t_avg": [ + 4000.0, + 1000.0, + 10.0, + 0.2, + 0.02, + 0.01 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 40.0, + 50.0, + 100.0, + 210.0, + 400.0, + 500.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-50": { + "fuse_type": "Siemens NH-1-50", + "i_rated_a": 50.0, + "t_avg": [ + 4000.0, + 40.0, + 4.0, + 1.0, + 0.02, + 0.01 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 86.0, + 200.0, + 300.0, + 400.0, + 1000.0, + 1280.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-63": { + "fuse_type": "Siemens NH-1-63", + "i_rated_a": 63.0, + "t_avg": [ + 4000.0, + 100.0, + 10.0, + 2.0, + 0.04, + 0.01 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 100.0, + 200.0, + 300.0, + 400.0, + 1000.0, + 1500.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-1-80": { + "fuse_type": "Siemens NH-1-80", + "i_rated_a": 80.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.01 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 150.58, + 250.0, + 450.0, + 1150.0, + 2470.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-1000": { + "fuse_type": "Siemens NH-2-1000", + "i_rated_a": 1000.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 1900.0, + 3500.0, + 8400.0, + 24000.0, + 52000.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-200": { + "fuse_type": "Siemens NH-2-200", + "i_rated_a": 200.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 280.0, + 650.0, + 1200.0, + 3000.0, + 7000.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-224": { + "fuse_type": "Siemens NH-2-224", + "i_rated_a": 224.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.2, + 0.04, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 400.0, + 750.0, + 1453.0, + 3025.0, + 4315.0, + 7600.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-250": { + "fuse_type": "Siemens NH-2-250", + "i_rated_a": 250.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 450.0, + 800.0, + 1650.0, + 4000.0, + 8500.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-315": { + "fuse_type": "Siemens NH-2-315", + "i_rated_a": 315.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 550.0, + 920.0, + 1900.0, + 5000.0, + 11000.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-355": { + "fuse_type": "Siemens NH-2-355", + "i_rated_a": 355.0, + "t_avg": [ + 4800.0, + 120.0, + 6.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 650.0, + 1116.27, + 2350.0, + 5840.0, + 12790.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-400": { + "fuse_type": "Siemens NH-2-400", + "i_rated_a": 400.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 720.0, + 1350.0, + 2800.0, + 6500.0, + 15000.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-425": { + "fuse_type": "Siemens NH-2-425", + "i_rated_a": 425.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 850.0, + 1500.0, + 3050.0, + 7500.0, + 16500.0 + ], + "x_min": 0, + "x_total": 0 + }, + "Siemens NH-2-630": { + "fuse_type": "Siemens NH-2-630", + "i_rated_a": 630.0, + "t_avg": [ + 4800.0, + 120.0, + 7.0, + 0.1, + 0.004 + ], + "t_min": 0, + "t_total": 0, + "x_avg": [ + 1200.0, + 2000.0, + 4800.0, + 12000.0, + 26000.0 + ], + "x_min": 0, + "x_total": 0 + } + } + }, + "res_bus": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"vm_pu\",\"va_degree\",\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "vm_pu": "float64", + "va_degree": "float64", + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_line": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_from_mw\",\"q_from_mvar\",\"p_to_mw\",\"q_to_mvar\",\"pl_mw\",\"ql_mvar\",\"i_from_ka\",\"i_to_ka\",\"i_ka\",\"vm_from_pu\",\"va_from_degree\",\"vm_to_pu\",\"va_to_degree\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_from_mw": "float64", + "q_from_mvar": "float64", + "p_to_mw": "float64", + "q_to_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_from_ka": "float64", + "i_to_ka": "float64", + "i_ka": "float64", + "vm_from_pu": "float64", + "va_from_degree": "float64", + "vm_to_pu": "float64", + "va_to_degree": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_hv_mw\",\"q_hv_mvar\",\"p_lv_mw\",\"q_lv_mvar\",\"pl_mw\",\"ql_mvar\",\"i_hv_ka\",\"i_lv_ka\",\"vm_hv_pu\",\"va_hv_degree\",\"vm_lv_pu\",\"va_lv_degree\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_hv_mw": "float64", + "q_hv_mvar": "float64", + "p_lv_mw": "float64", + "q_lv_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_hv_ka": "float64", + "i_lv_ka": "float64", + "vm_hv_pu": "float64", + "va_hv_degree": "float64", + "vm_lv_pu": "float64", + "va_lv_degree": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo3w": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_hv_mw\",\"q_hv_mvar\",\"p_mv_mw\",\"q_mv_mvar\",\"p_lv_mw\",\"q_lv_mvar\",\"pl_mw\",\"ql_mvar\",\"i_hv_ka\",\"i_mv_ka\",\"i_lv_ka\",\"vm_hv_pu\",\"va_hv_degree\",\"vm_mv_pu\",\"va_mv_degree\",\"vm_lv_pu\",\"va_lv_degree\",\"va_internal_degree\",\"vm_internal_pu\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_hv_mw": "float64", + "q_hv_mvar": "float64", + "p_mv_mw": "float64", + "q_mv_mvar": "float64", + "p_lv_mw": "float64", + "q_lv_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_hv_ka": "float64", + "i_mv_ka": "float64", + "i_lv_ka": "float64", + "vm_hv_pu": "float64", + "va_hv_degree": "float64", + "vm_mv_pu": "float64", + "va_mv_degree": "float64", + "vm_lv_pu": "float64", + "va_lv_degree": "float64", + "va_internal_degree": "float64", + "vm_internal_pu": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_impedance": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_from_mw\",\"q_from_mvar\",\"p_to_mw\",\"q_to_mvar\",\"pl_mw\",\"ql_mvar\",\"i_from_ka\",\"i_to_ka\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_from_mw": "float64", + "q_from_mvar": "float64", + "p_to_mw": "float64", + "q_to_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_from_ka": "float64", + "i_to_ka": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_ext_grid": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_load": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_motor": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_sgen": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_storage": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_shunt": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\",\"vm_pu\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64", + "vm_pu": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_gen": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\",\"va_degree\",\"vm_pu\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64", + "va_degree": "float64", + "vm_pu": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_ward": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\",\"vm_pu\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64", + "vm_pu": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_xward": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\",\"vm_pu\",\"va_internal_degree\",\"vm_internal_pu\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64", + "vm_pu": "float64", + "va_internal_degree": "float64", + "vm_internal_pu": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_dcline": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_from_mw\",\"q_from_mvar\",\"p_to_mw\",\"q_to_mvar\",\"pl_mw\",\"vm_from_pu\",\"va_from_degree\",\"vm_to_pu\",\"va_to_degree\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_from_mw": "float64", + "q_from_mvar": "float64", + "p_to_mw": "float64", + "q_to_mvar": "float64", + "pl_mw": "float64", + "vm_from_pu": "float64", + "va_from_degree": "float64", + "vm_to_pu": "float64", + "va_to_degree": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_asymmetric_load": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_asymmetric_sgen": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_switch": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"i_ka\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "i_ka": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_tcsc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"thyristor_firing_angle_degree\",\"x_ohm\",\"p_from_mw\",\"q_from_mvar\",\"p_to_mw\",\"q_to_mvar\",\"pl_mw\",\"ql_mvar\",\"i_ka\",\"vm_from_pu\",\"va_from_degree\",\"vm_to_pu\",\"va_to_degree\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "thyristor_firing_angle_degree": "float64", + "x_ohm": "float64", + "p_from_mw": "float64", + "q_from_mvar": "float64", + "p_to_mw": "float64", + "q_to_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_ka": "float64", + "vm_from_pu": "float64", + "va_from_degree": "float64", + "vm_to_pu": "float64", + "va_to_degree": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_svc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"thyristor_firing_angle_degree\",\"x_ohm\",\"q_mvar\",\"vm_pu\",\"va_degree\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "thyristor_firing_angle_degree": "float64", + "x_ohm": "float64", + "q_mvar": "float64", + "vm_pu": "float64", + "va_degree": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_ssc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"q_mvar\",\"vm_internal_pu\",\"va_internal_degree\",\"vm_pu\",\"va_degree\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "q_mvar": "float64", + "vm_internal_pu": "float64", + "va_internal_degree": "float64", + "vm_pu": "float64", + "va_degree": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_bus_est": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"vm_pu\",\"va_degree\",\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "vm_pu": "float64", + "va_degree": "float64", + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_line_est": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_from_mw\",\"q_from_mvar\",\"p_to_mw\",\"q_to_mvar\",\"pl_mw\",\"ql_mvar\",\"i_from_ka\",\"i_to_ka\",\"i_ka\",\"vm_from_pu\",\"va_from_degree\",\"vm_to_pu\",\"va_to_degree\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_from_mw": "float64", + "q_from_mvar": "float64", + "p_to_mw": "float64", + "q_to_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_from_ka": "float64", + "i_to_ka": "float64", + "i_ka": "float64", + "vm_from_pu": "float64", + "va_from_degree": "float64", + "vm_to_pu": "float64", + "va_to_degree": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo_est": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_hv_mw\",\"q_hv_mvar\",\"p_lv_mw\",\"q_lv_mvar\",\"pl_mw\",\"ql_mvar\",\"i_hv_ka\",\"i_lv_ka\",\"vm_hv_pu\",\"va_hv_degree\",\"vm_lv_pu\",\"va_lv_degree\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_hv_mw": "float64", + "q_hv_mvar": "float64", + "p_lv_mw": "float64", + "q_lv_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_hv_ka": "float64", + "i_lv_ka": "float64", + "vm_hv_pu": "float64", + "va_hv_degree": "float64", + "vm_lv_pu": "float64", + "va_lv_degree": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo3w_est": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_hv_mw\",\"q_hv_mvar\",\"p_mv_mw\",\"q_mv_mvar\",\"p_lv_mw\",\"q_lv_mvar\",\"pl_mw\",\"ql_mvar\",\"i_hv_ka\",\"i_mv_ka\",\"i_lv_ka\",\"vm_hv_pu\",\"va_hv_degree\",\"vm_mv_pu\",\"va_mv_degree\",\"vm_lv_pu\",\"va_lv_degree\",\"va_internal_degree\",\"vm_internal_pu\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_hv_mw": "float64", + "q_hv_mvar": "float64", + "p_mv_mw": "float64", + "q_mv_mvar": "float64", + "p_lv_mw": "float64", + "q_lv_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_hv_ka": "float64", + "i_mv_ka": "float64", + "i_lv_ka": "float64", + "vm_hv_pu": "float64", + "va_hv_degree": "float64", + "vm_mv_pu": "float64", + "va_mv_degree": "float64", + "vm_lv_pu": "float64", + "va_lv_degree": "float64", + "va_internal_degree": "float64", + "vm_internal_pu": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_impedance_est": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_from_mw\",\"q_from_mvar\",\"p_to_mw\",\"q_to_mvar\",\"pl_mw\",\"ql_mvar\",\"i_from_ka\",\"i_to_ka\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_from_mw": "float64", + "q_from_mvar": "float64", + "p_to_mw": "float64", + "q_to_mvar": "float64", + "pl_mw": "float64", + "ql_mvar": "float64", + "i_from_ka": "float64", + "i_to_ka": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_switch_est": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"i_ka\",\"loading_percent\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "i_ka": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_bus_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_line_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo3w_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_ext_grid_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_gen_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_sgen_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_switch_sc": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_bus_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"vm_a_pu\",\"va_a_degree\",\"vm_b_pu\",\"va_b_degree\",\"vm_c_pu\",\"va_c_degree\",\"p_a_mw\",\"q_a_mvar\",\"p_b_mw\",\"q_b_mvar\",\"p_c_mw\",\"q_c_mvar\",\"unbalance_percent\"],\"index\":[101,102,103,106],\"data\":[[1.000000000000649,-0.000000014467166,1.000000000000706,-120.000000014467219,0.999999999998645,120.00000002893438,-0.76586721276166,0.142600574268217,-0.765870349186078,0.142774135244491,1.529587620821064,0.13652642290409,0.000000025248458],[0.999413066587415,-0.143342436111115,0.99941331944751,-120.143349997549379,1.002844447733494,120.248691141259584,0.0,0.0,0.0,0.0,0.0,0.0,0.255229968019964],[0.998786896904501,-0.170005794192065,0.998787149925785,-120.170013342503964,1.004418791821623,120.270535414590881,0.73,-0.19,0.73,-0.19,-1.57,-0.19,0.317807726599274],[1.000000000000649,-0.000000014467166,1.000000000000706,-120.000000014467219,0.999999999998645,120.00000002893438,0.0,0.0,0.0,0.0,0.0,0.0,0.000000025248458]]}", + "orient": "split", + "dtype": { + "vm_a_pu": "float64", + "va_a_degree": "float64", + "vm_b_pu": "float64", + "va_b_degree": "float64", + "vm_c_pu": "float64", + "va_c_degree": "float64", + "p_a_mw": "float64", + "q_a_mvar": "float64", + "p_b_mw": "float64", + "q_b_mvar": "float64", + "p_c_mw": "float64", + "q_c_mvar": "float64", + "unbalance_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_line_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_a_from_mw\",\"q_a_from_mvar\",\"p_b_from_mw\",\"q_b_from_mvar\",\"q_c_from_mvar\",\"p_a_to_mw\",\"q_a_to_mvar\",\"p_b_to_mw\",\"q_b_to_mvar\",\"p_c_to_mw\",\"q_c_to_mvar\",\"p_a_l_mw\",\"q_a_l_mvar\",\"p_b_l_mw\",\"q_b_l_mvar\",\"p_c_l_mw\",\"q_c_l_mvar\",\"i_a_from_ka\",\"i_a_to_ka\",\"i_b_from_ka\",\"i_b_to_ka\",\"i_c_from_ka\",\"i_c_to_ka\",\"i_a_ka\",\"i_b_ka\",\"i_c_ka\",\"i_n_from_ka\",\"i_n_to_ka\",\"i_n_ka\",\"loading_a_percent\",\"loading_b_percent\",\"loading_c_percent\",\"p_c_from_mw\",\"loading_percent\"],\"index\":[101],\"data\":[[-0.729999999996567,0.19000000000026,-0.729999999996566,0.190000000000261,0.19000000001556,0.730552301039331,-0.216633736167421,0.730552300762162,-0.216633749867232,-1.567616528781956,-0.216173539601529,0.000552301042765,-0.026633736167161,0.000552300765596,-0.02663374986697,0.002383471230365,-0.026173539585968,0.065405448594188,0.066029483815909,0.065405432025122,0.06602946742436,0.136355496215811,0.136655605565042,0.066029483815909,0.06602946742436,0.136655605565042,0.198789638449406,0.19880656576458,0.19880656576458,61.138410940656399,61.138395763296025,126.532968115779696,1.570000000012321,126.532968115779696]]}", + "orient": "split", + "dtype": { + "p_a_from_mw": "float64", + "q_a_from_mvar": "float64", + "p_b_from_mw": "float64", + "q_b_from_mvar": "float64", + "q_c_from_mvar": "float64", + "p_a_to_mw": "float64", + "q_a_to_mvar": "float64", + "p_b_to_mw": "float64", + "q_b_to_mvar": "float64", + "p_c_to_mw": "float64", + "q_c_to_mvar": "float64", + "p_a_l_mw": "float64", + "q_a_l_mvar": "float64", + "p_b_l_mw": "float64", + "q_b_l_mvar": "float64", + "p_c_l_mw": "float64", + "q_c_l_mvar": "float64", + "i_a_from_ka": "float64", + "i_a_to_ka": "float64", + "i_b_from_ka": "float64", + "i_b_to_ka": "float64", + "i_c_from_ka": "float64", + "i_c_to_ka": "float64", + "i_a_ka": "float64", + "i_b_ka": "float64", + "i_c_ka": "float64", + "i_n_from_ka": "float64", + "i_n_to_ka": "float64", + "i_n_ka": "float64", + "loading_a_percent": "float64", + "loading_b_percent": "float64", + "loading_c_percent": "float64", + "p_c_from_mw": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_trafo_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_a_hv_mw\",\"q_a_hv_mvar\",\"p_b_hv_mw\",\"q_b_hv_mvar\",\"p_c_hv_mw\",\"q_c_hv_mvar\",\"p_a_lv_mw\",\"q_a_lv_mvar\",\"p_b_lv_mw\",\"q_b_lv_mvar\",\"p_c_lv_mw\",\"q_c_lv_mvar\",\"p_a_l_mw\",\"q_a_l_mvar\",\"p_b_l_mw\",\"q_b_l_mvar\",\"p_c_l_mw\",\"q_c_l_mvar\",\"i_a_hv_ka\",\"i_a_lv_ka\",\"i_b_hv_ka\",\"i_b_lv_ka\",\"i_c_hv_ka\",\"i_c_lv_ka\",\"loading_a_percent\",\"loading_b_percent\",\"loading_c_percent\",\"loading_percent\"],\"index\":[0],\"data\":[[0.765867212761676,-0.142600574268206,0.76587034918608,-0.142774135244511,-1.529587620821082,-0.136526422904082,-0.730551408499011,0.216635342580699,-0.730551355834715,0.216632173706613,1.567614685268512,0.216173496640995,0.035315804262665,0.074034768312494,0.035318993351365,0.073858038462102,0.038027064447431,0.079647073736913,0.012266538958654,0.066029449240481,0.012267088052456,0.066029350092719,0.024180507930633,0.136655447350574,2.921361947544116,2.921492718069054,5.917354448556197,5.917354448556197]]}", + "orient": "split", + "dtype": { + "p_a_hv_mw": "float64", + "q_a_hv_mvar": "float64", + "p_b_hv_mw": "float64", + "q_b_hv_mvar": "float64", + "p_c_hv_mw": "float64", + "q_c_hv_mvar": "float64", + "p_a_lv_mw": "float64", + "q_a_lv_mvar": "float64", + "p_b_lv_mw": "float64", + "q_b_lv_mvar": "float64", + "p_c_lv_mw": "float64", + "q_c_lv_mvar": "float64", + "p_a_l_mw": "float64", + "q_a_l_mvar": "float64", + "p_b_l_mw": "float64", + "q_b_l_mvar": "float64", + "p_c_l_mw": "float64", + "q_c_l_mvar": "float64", + "i_a_hv_ka": "float64", + "i_a_lv_ka": "float64", + "i_b_hv_ka": "float64", + "i_b_lv_ka": "float64", + "i_c_hv_ka": "float64", + "i_c_lv_ka": "float64", + "loading_a_percent": "float64", + "loading_b_percent": "float64", + "loading_c_percent": "float64", + "loading_percent": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_ext_grid_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_a_mw\",\"q_a_mvar\",\"p_b_mw\",\"q_b_mvar\",\"p_c_mw\",\"q_c_mvar\"],\"index\":[0],\"data\":[[0.76586721276166,-0.142600574268217,0.765870349186078,-0.142774135244491,-1.529587620821064,-0.13652642290409]]}", + "orient": "split", + "dtype": { + "p_a_mw": "float64", + "q_a_mvar": "float64", + "p_b_mw": "float64", + "q_b_mvar": "float64", + "p_c_mw": "float64", + "q_c_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_shunt_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[],\"index\":[],\"data\":[]}", + "orient": "split", + "is_multiindex": false, + "is_multicolumn": false + }, + "res_load_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[101],\"data\":[[2.5,0.24]]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_sgen_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[31],\"data\":[[1.21,0.81]]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_storage_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_mw\",\"q_mvar\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "p_mw": "float64", + "q_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_asymmetric_load_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_a_mw\",\"q_a_mvar\",\"p_b_mw\",\"q_b_mvar\",\"p_c_mw\",\"q_c_mvar\"],\"index\":[33],\"data\":[[0.4,0.01,0.5,0.01,1.0,0.01]]}", + "orient": "split", + "dtype": { + "p_a_mw": "float64", + "q_a_mvar": "float64", + "p_b_mw": "float64", + "q_b_mvar": "float64", + "p_c_mw": "float64", + "q_c_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "res_asymmetric_sgen_3ph": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"p_a_mw\",\"q_a_mvar\",\"p_b_mw\",\"q_b_mvar\",\"p_c_mw\",\"q_c_mvar\"],\"index\":[32],\"data\":[[0.1,0.01,0.2,0.01,3.0,0.01]]}", + "orient": "split", + "dtype": { + "p_a_mw": "float64", + "q_a_mvar": "float64", + "p_b_mw": "float64", + "q_b_mvar": "float64", + "p_c_mw": "float64", + "q_c_mvar": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "user_pf_options": {} + } +} \ No newline at end of file From 7e5aa8b4ce096b48134314ff53091deec08df525 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Fri, 5 Sep 2025 23:46:09 +0500 Subject: [PATCH 27/28] TODOs Signed-off-by: furqan463 --- src/power_grid_model_io/converters/pandapower_converter.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 677e8bc4..2125cb90 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -99,7 +99,7 @@ def _parse_data( self.idx_lookup = {} self.next_idx = 0 - # Set pandas data + # Set pandapower data self.pp_input_data = data # Convert @@ -360,6 +360,9 @@ def _create_output_data_3ph(self): Furthermore, creates a global node lookup table, which stores nodes' voltage magnitude per unit and the voltage angle in degrees """ + #TODO create output_data_3ph for remaining components + #Although Pandapower itself did not implmenet res_shunt_3ph + #Since results are avaiable in PGM output, these should be converted. self._pp_buses_output_3ph() self._pp_lines_output_3ph() self._pp_ext_grids_output_3ph() @@ -376,6 +379,7 @@ def _create_pgm_input_nodes(self): Returns: a power-grid-model structured array for the Node component """ + #TODO handle out-of-service buses, either here or in get_switch_states pp_busses = self.pp_input_data["bus"] if pp_busses.empty: From 6788b51c84f324839f1b53f235e0c44fc87830b4 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Sat, 6 Sep 2025 13:31:17 +0500 Subject: [PATCH 28/28] Add license file, run pre-commit Signed-off-by: furqan463 --- .../converters/pandapower_converter.py | 8 ++++---- .../pp_v2_net_3ph_output_current_loading.json.license | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json.license diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 2125cb90..1f666567 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -360,9 +360,9 @@ def _create_output_data_3ph(self): Furthermore, creates a global node lookup table, which stores nodes' voltage magnitude per unit and the voltage angle in degrees """ - #TODO create output_data_3ph for remaining components - #Although Pandapower itself did not implmenet res_shunt_3ph - #Since results are avaiable in PGM output, these should be converted. + # TODO create output_data_3ph for remaining components + # Although Pandapower itself did not implmenet res_shunt_3ph + # Since results are avaiable in PGM output, these should be converted. self._pp_buses_output_3ph() self._pp_lines_output_3ph() self._pp_ext_grids_output_3ph() @@ -379,7 +379,7 @@ def _create_pgm_input_nodes(self): Returns: a power-grid-model structured array for the Node component """ - #TODO handle out-of-service buses, either here or in get_switch_states + # TODO handle out-of-service buses, either here or in get_switch_states pp_busses = self.pp_input_data["bus"] if pp_busses.empty: diff --git a/tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json.license b/tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json.license new file mode 100644 index 00000000..76010591 --- /dev/null +++ b/tests/data/pandapower/pp_v2_net_3ph_output_current_loading.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0