From 80111040a49b1423ca08b14761b629b8524da9df Mon Sep 17 00:00:00 2001 From: furqan463 Date: Wed, 10 Sep 2025 11:37:28 +0500 Subject: [PATCH 1/2] Resolve bug with broadcasting Signed-off-by: furqan463 --- .../converters/pandapower_converter.py | 23 ++++++++++++------- .../test_pandapower_converter_input.py | 10 ++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 1f666567..8efd162a 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -410,8 +410,15 @@ def _create_pgm_input_lines(self): in_service = self._get_pp_attr("line", "in_service", expected_type="bool", default=True) length_km = self._get_pp_attr("line", "length_km", expected_type="f8") parallel = self._get_pp_attr("line", "parallel", expected_type="u4", default=1) - c_nf_per_km = self._get_pp_attr("line", "c_nf_per_km", expected_type="f8") - c0_nf_per_km = self._get_pp_attr("line", "c0_nf_per_km", expected_type="f8", default=np.nan) + c_nf_per_km = self._get_pp_attr("line", "c_nf_per_km", expected_type="f8", default=0) + c0_nf_per_km = self._get_pp_attr("line", "c0_nf_per_km", expected_type="f8", default=0) + g_us_per_km = self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0) + g0_us_per_km = self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0) + # broadcast to array length + c_nf_per_km = c_nf_per_km * np.ones(shape=len(pp_lines), dtype="f8") + c0_nf_per_km = c0_nf_per_km * np.ones(shape=len(pp_lines), dtype="f8") + g_us_per_km = g_us_per_km * np.ones(shape=len(pp_lines), dtype="f8") + g0_us_per_km = g0_us_per_km * np.ones(shape=len(pp_lines), dtype="f8") multiplier = length_km / parallel pgm_lines = initialize_array( @@ -427,11 +434,11 @@ def _create_pgm_input_lines(self): 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"] = np.divide( - self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0), + g_us_per_km, c_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where=c_nf_per_km != 0.0, + where=np.logical_not(np.isclose(c_nf_per_km, 0.0)), ) - pgm_lines["tan1"][np.equal(c_nf_per_km, 0.0)] = 0.0 + pgm_lines["tan1"][np.isclose(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) @@ -441,11 +448,11 @@ def _create_pgm_input_lines(self): 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"] = np.divide( - self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0), + g0_us_per_km, c0_nf_per_km * (2 * np.pi * self.system_frequency * 1e-3), - where=c0_nf_per_km != 0.0, + where=np.logical_not(np.isclose(c0_nf_per_km, 0.0)), ) - pgm_lines["tan0"][np.equal(c0_nf_per_km, 0.0)] = 0.0 + pgm_lines["tan0"][np.isclose(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 diff --git a/tests/validation/converters/test_pandapower_converter_input.py b/tests/validation/converters/test_pandapower_converter_input.py index 55ad295e..1badfa3c 100644 --- a/tests/validation/converters/test_pandapower_converter_input.py +++ b/tests/validation/converters/test_pandapower_converter_input.py @@ -150,3 +150,13 @@ def test_pgm_input_lines__cnf_zero(): 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) + + +@pytest.mark.filterwarnings("error") +def test_simple_example(): + from pandapower.networks import example_simple + + pp_net = example_simple() + pp_net["gen"] = pp_net["gen"].iloc[:0] + pp_converter = PandaPowerConverter() + data, _ = pp_converter.load_input_data(pp_net) From a8675a4ddfb9274facaed6342dd1c36e56f683f1 Mon Sep 17 00:00:00 2001 From: furqan463 Date: Wed, 10 Sep 2025 14:05:46 +0500 Subject: [PATCH 2/2] improvement Signed-off-by: furqan463 --- .../converters/pandapower_converter.py | 15 ++++--------- .../test_pandapower_converter_input.py | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/power_grid_model_io/converters/pandapower_converter.py b/src/power_grid_model_io/converters/pandapower_converter.py index 8efd162a..a4c1e7d0 100644 --- a/src/power_grid_model_io/converters/pandapower_converter.py +++ b/src/power_grid_model_io/converters/pandapower_converter.py @@ -412,13 +412,6 @@ def _create_pgm_input_lines(self): parallel = self._get_pp_attr("line", "parallel", expected_type="u4", default=1) c_nf_per_km = self._get_pp_attr("line", "c_nf_per_km", expected_type="f8", default=0) c0_nf_per_km = self._get_pp_attr("line", "c0_nf_per_km", expected_type="f8", default=0) - g_us_per_km = self._get_pp_attr("line", "g_us_per_km", expected_type="f8", default=0) - g0_us_per_km = self._get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0) - # broadcast to array length - c_nf_per_km = c_nf_per_km * np.ones(shape=len(pp_lines), dtype="f8") - c0_nf_per_km = c0_nf_per_km * np.ones(shape=len(pp_lines), dtype="f8") - g_us_per_km = g_us_per_km * np.ones(shape=len(pp_lines), dtype="f8") - g0_us_per_km = g0_us_per_km * np.ones(shape=len(pp_lines), dtype="f8") multiplier = length_km / parallel pgm_lines = initialize_array( @@ -433,12 +426,12 @@ 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"] = 0.0 pgm_lines["tan1"] = np.divide( - g_us_per_km, + 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.logical_not(np.isclose(c_nf_per_km, 0.0)), ) - pgm_lines["tan1"][np.isclose(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) @@ -447,12 +440,12 @@ 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"] = 0.0 pgm_lines["tan0"] = np.divide( - g0_us_per_km, + 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.logical_not(np.isclose(c0_nf_per_km, 0.0)), ) - pgm_lines["tan0"][np.isclose(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 diff --git a/tests/unit/converters/test_pandapower_converter_input.py b/tests/unit/converters/test_pandapower_converter_input.py index 4b6b8842..4b3c4cdb 100644 --- a/tests/unit/converters/test_pandapower_converter_input.py +++ b/tests/unit/converters/test_pandapower_converter_input.py @@ -525,13 +525,13 @@ def test_create_pgm_input_lines(mock_init_array: MagicMock, two_pp_objs, convert converter._get_pp_attr.assert_any_call("line", "parallel", expected_type="u4", default=1) converter._get_pp_attr.assert_any_call("line", "r_ohm_per_km", expected_type="f8") converter._get_pp_attr.assert_any_call("line", "x_ohm_per_km", expected_type="f8") - converter._get_pp_attr.assert_any_call("line", "c_nf_per_km", expected_type="f8") + converter._get_pp_attr.assert_any_call("line", "c_nf_per_km", expected_type="f8", default=0) converter._get_pp_attr.assert_any_call("line", "g_us_per_km", expected_type="f8", default=0) converter._get_pp_attr.assert_any_call("line", "max_i_ka", expected_type="f8", default=np.nan) converter._get_pp_attr.assert_any_call("line", "df", expected_type="f8", default=1) converter._get_pp_attr.assert_any_call("line", "r0_ohm_per_km", expected_type="f8", default=np.nan) converter._get_pp_attr.assert_any_call("line", "x0_ohm_per_km", expected_type="f8", default=np.nan) - converter._get_pp_attr.assert_any_call("line", "c0_nf_per_km", expected_type="f8", default=np.nan) + converter._get_pp_attr.assert_any_call("line", "c0_nf_per_km", expected_type="f8", default=0) converter._get_pp_attr.assert_any_call("line", "g0_us_per_km", expected_type="f8", default=0) assert len(converter._get_pp_attr.call_args_list) == 15 @@ -566,7 +566,7 @@ def test_create_pgm_input_lines(mock_init_array: MagicMock, two_pp_objs, convert ) pgm.assert_any_call( "c1", - _get_pp_attr("line", "c_nf_per_km", expected_type="f8") + _get_pp_attr("line", "c_nf_per_km", expected_type="f8", default=0) * _get_pp_attr("line", "length_km", expected_type="f8") * _get_pp_attr("line", "parallel", expected_type="u4", default=1) * 1e-9, @@ -575,8 +575,8 @@ def test_create_pgm_input_lines(mock_init_array: MagicMock, two_pp_objs, convert "tan1", 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, + _get_pp_attr("line", "c_nf_per_km", expected_type="f8", default=0) * (np.pi / 10), + where=np.logical_not(np.isclose(_get_pp_attr("line", "c_nf_per_km", expected_type="f8", default=0), 0.0)), ), ) pgm.assert_any_call( @@ -585,11 +585,18 @@ def test_create_pgm_input_lines(mock_init_array: MagicMock, two_pp_objs, convert * _get_pp_attr("line", "df", expected_type="f8", default=1) * _get_pp_attr("line", "parallel", expected_type="u4", default=1), ) + pgm.assert_any_call( + "tan0", + np.divide( + _get_pp_attr("line", "g0_us_per_km", expected_type="f8", default=0), + _get_pp_attr("line", "c0_nf_per_km", expected_type="f8", default=0) * (np.pi / 10), + where=np.logical_not(np.isclose(_get_pp_attr("line", "c0_nf_per_km", expected_type="f8", default=0), 0.0)), + ), + ) pgm.assert_any_call("r0", ANY) pgm.assert_any_call("x0", ANY) pgm.assert_any_call("c0", ANY) - pgm.assert_any_call("tan0", ANY) - assert len(pgm.call_args_list) == 14 + assert len(pgm.call_args_list) == 16 # result assert converter.pgm_input_data[ComponentType.line] == mock_init_array.return_value