Skip to content

Commit 8443774

Browse files
committed
feat: support all component types in interface
1 parent 54a4061 commit 8443774

File tree

6 files changed

+51
-38
lines changed

6 files changed

+51
-38
lines changed

docs/demos/connecting_new_consumer.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
"metadata": {},
132132
"outputs": [],
133133
"source": [
134-
"from power_grid_model_ds._core.load_flow import PowerGridModelInterface\n",
134+
"from power_grid_model_ds import PowerGridModelInterface\n",
135135
"\n",
136136
"R_PER_KM = 0.1\n",
137137
"X_PER_KM = 0.1\n",

src/power_grid_model_ds/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
#
33
# SPDX-License-Identifier: MPL-2.0
44

5-
from power_grid_model_ds._core.load_flow import PowerGridModelInterface
65
from power_grid_model_ds._core.model.graphs.container import GraphContainer
76
from power_grid_model_ds._core.model.grids.base import Grid
7+
from power_grid_model_ds._core.power_grid_model_interface import PowerGridModelInterface
88

99
__all__ = ["Grid", "GraphContainer", "PowerGridModelInterface"]

src/power_grid_model_ds/_core/load_flow.py renamed to src/power_grid_model_ds/_core/power_grid_model_interface.py

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,10 @@
99

1010
import numpy as np
1111
from numpy.typing import NDArray
12-
from power_grid_model import CalculationMethod, PowerGridModel, initialize_array
12+
from power_grid_model import CalculationMethod, ComponentType, PowerGridModel, initialize_array
1313

1414
from power_grid_model_ds._core.model.grids.base import Grid
1515

16-
PGM_ARRAYS = [
17-
"node",
18-
"line",
19-
"link",
20-
"transformer",
21-
"three_winding_transformer",
22-
"sym_load",
23-
"sym_gen",
24-
"source",
25-
"transformer_tap_regulator",
26-
"sym_power_sensor",
27-
"sym_voltage_sensor",
28-
"asym_voltage_sensor",
29-
]
30-
3116

3217
class PGMCoreException(Exception):
3318
"""Raised when there is an error in running the power grid model"""
@@ -70,7 +55,9 @@ def create_input_from_grid(self):
7055
"""
7156
Create input for the PowerGridModel
7257
"""
73-
for array_name in PGM_ARRAYS:
58+
for array_name in ComponentType:
59+
if not hasattr(self.grid, array_name):
60+
continue
7461
pgm_array = self._create_power_grid_array(array_name=array_name)
7562
self._input_data[array_name] = pgm_array
7663
return self._input_data
@@ -86,8 +73,8 @@ def create_grid_from_input_data(self, check_ids: bool = True) -> Grid:
8673
8774
Returns a Grid object with the arrays filled with the PowerGridModel input.
8875
"""
89-
for pgm_name in PGM_ARRAYS:
90-
if pgm_name in self._input_data:
76+
for pgm_name in ComponentType:
77+
if pgm_name in self._input_data and hasattr(self.grid, pgm_name):
9178
pgm_ds_array_class = getattr(self.grid, pgm_name).__class__
9279
pgm_ds_array = pgm_ds_array_class(self._input_data[pgm_name])
9380
self.grid.append(pgm_ds_array, check_max_id=False)
@@ -155,12 +142,13 @@ def update_grid(self) -> None:
155142
"""
156143
if not self.output_data:
157144
raise PGMCoreException("Can not update grid without output_data")
158-
for array_name in PGM_ARRAYS:
159-
if array_name in self.output_data.keys():
160-
internal_array = getattr(self.grid, array_name)
161-
pgm_output_array = self.output_data[array_name]
162-
fields = self._match_dtypes(pgm_output_array.dtype, internal_array.dtype)
163-
internal_array[fields] = pgm_output_array[fields]
145+
for array_name in self.output_data.keys():
146+
if not hasattr(self.grid, array_name):
147+
continue
148+
internal_array = getattr(self.grid, array_name)
149+
pgm_output_array = self.output_data[array_name]
150+
fields = self._match_dtypes(pgm_output_array.dtype, internal_array.dtype)
151+
internal_array[fields] = pgm_output_array[fields]
164152

165153
@staticmethod
166154
def _match_dtypes(first_dtype: np.dtype, second_dtype: np.dtype):

src/power_grid_model_ds/errors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#
33
# SPDX-License-Identifier: MPL-2.0
44

5-
from power_grid_model_ds._core.load_flow import PGMCoreException
65
from power_grid_model_ds._core.model.arrays.base.errors import (
76
ArrayDefinitionError,
87
MultipleRecordsReturned,
@@ -14,6 +13,7 @@
1413
MissingNodeError,
1514
NoPathBetweenNodes,
1615
)
16+
from power_grid_model_ds._core.power_grid_model_interface import PGMCoreException
1717

1818
__all__ = [
1919
"PGMCoreException",

tests/integration/loadflow/test_power_grid_model.py

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
# SPDX-License-Identifier: MPL-2.0
44

55

6+
from enum import StrEnum
7+
from unittest.mock import patch
8+
69
import numpy as np
710
import pytest
8-
from power_grid_model import TapChangingStrategy, initialize_array
11+
from power_grid_model import ComponentType, TapChangingStrategy, initialize_array
912

1013
from power_grid_model_ds._core.data_source.generator.grid_generators import RadialGridGenerator
11-
from power_grid_model_ds._core.load_flow import PowerGridModelInterface
1214
from power_grid_model_ds._core.model.arrays import (
1315
LineArray,
1416
NodeArray,
1517
SourceArray,
1618
SymLoadArray,
1719
)
1820
from power_grid_model_ds._core.model.grids.base import Grid
21+
from power_grid_model_ds._core.power_grid_model_interface import PowerGridModelInterface
1922
from tests.fixtures.arrays import ExtendedLineArray, ExtendedNodeArray
2023
from tests.fixtures.grid_classes import ExtendedGrid
2124
from tests.unit.model.grids.test_custom_grid import CustomGrid
@@ -112,26 +115,48 @@ def test_grid_with_automatic_tap_regulator(self, grid_with_tap_regulator: Grid):
112115
assert output["transformer_tap_regulator"]["tap_pos"][0] > 0
113116

114117

115-
class PowerGridModelInterfaceMethods:
118+
ExtendedComponentType = StrEnum("ExtendedComponentType", {x.name: x.value for x in ComponentType} | {"onzin": "onzin"})
119+
120+
121+
class TestPowerGridModelInterfaceMethods:
116122
def test_update_grid(self):
117123
"""Tests the power flow on a randomly configured grid and update grid with results"""
118124
grid_generator = RadialGridGenerator(grid_class=Grid, nr_nodes=5, nr_sources=1, nr_nops=0)
119125
grid = grid_generator.run(seed=0)
120-
121126
grid.node = ExtendedNodeArray(grid.node.data)
122127
grid.line = ExtendedLineArray(grid.line.data)
123128

124-
core_interface = PowerGridModelInterface(grid=grid)
125-
core_interface.create_input_from_grid()
126-
core_interface.calculate_power_flow()
127-
core_interface.update_grid()
129+
with patch("power_grid_model_ds._core.power_grid_model_interface.ComponentType", ExtendedComponentType):
130+
core_interface = PowerGridModelInterface(grid=grid)
131+
core_interface.create_input_from_grid()
132+
core_interface.calculate_power_flow()
133+
core_interface.update_grid()
128134

135+
grid = core_interface.grid
129136
# voltage should be in neighbourhood of 10500
130137
assert grid.node.u[0] == pytest.approx(10_500, 0.1)
131138
assert grid.node.u[1] == pytest.approx(10_500, 0.1)
132139
# all lines have a current
133140
assert all(grid.line.i_from > 0)
134141

142+
# def test_update_grid_missing_component(self, core_interface_after_loadflow: PowerGridModelInterface):
143+
# """Test that update grid works when a component is missing in the grid."""
144+
# del core_interface_after_loadflow.grid.source
145+
146+
# core_interface_after_loadflow.update_grid()
147+
148+
# # voltage should be in neighbourhood of 10500
149+
# grid = core_interface_after_loadflow.grid
150+
# assert not all(grid.node.is_empty("u"))
151+
# assert not hasattr(grid, "source")
152+
153+
def test_input_from_grid_missing_component(self, grid: Grid):
154+
# Mimic no source in grid
155+
del grid.source
156+
157+
core_interface = PowerGridModelInterface(grid=grid)
158+
assert "source" not in core_interface.create_input_from_grid()
159+
135160
def test_update_model(self):
136161
"""Test whether a pgm model can be updated and returns different results"""
137162
grid_generator = RadialGridGenerator(grid_class=Grid, nr_nodes=5, nr_sources=1, nr_nops=0)
@@ -183,7 +208,7 @@ def test_setup_model(self):
183208

184209
core_interface = PowerGridModelInterface(grid=grid)
185210
assert core_interface.model is None
186-
assert core_interface._input_data is None
211+
assert core_interface._input_data == {}
187212
core_interface.setup_model()
188213
assert core_interface.model
189214
assert core_interface._input_data

tests/unit/data_source/generator/test_grid_generators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
from power_grid_model_ds._core.data_source.generator.arrays.node import NodeGenerator
1313
from power_grid_model_ds._core.data_source.generator.arrays.source import SourceGenerator
1414
from power_grid_model_ds._core.data_source.generator.grid_generators import RadialGridGenerator
15-
from power_grid_model_ds._core.load_flow import PowerGridModelInterface
1615
from power_grid_model_ds._core.model.arrays import LineArray, NodeArray, SourceArray, SymLoadArray
1716
from power_grid_model_ds._core.model.graphs.models.base import BaseGraphModel
1817
from power_grid_model_ds._core.model.grids.base import Grid
18+
from power_grid_model_ds._core.power_grid_model_interface import PowerGridModelInterface
1919

2020

2121
def test_generate_random_grid():

0 commit comments

Comments
 (0)