Skip to content

Commit 84b06f4

Browse files
committed
Add state estimation interface
1 parent db231b8 commit 84b06f4

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

src/power_grid_model_ds/_core/power_grid_model_interface.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,25 @@ def calculate_power_flow(
100100
)
101101
return self.output_data
102102

103+
def calculate_state_estimation(
104+
self,
105+
calculation_method: CalculationMethod = CalculationMethod.iterative_linear,
106+
update_data: dict | None = None,
107+
**kwargs,
108+
):
109+
"""Initialize the PowerGridModel and calculate state estimation over input data.
110+
111+
If input data is not available, self.create_input_from_grid() will be called to create it.
112+
113+
Returns output of the state estimation calculation (also stored in self.output_data)
114+
"""
115+
self.model = self.model or self.setup_model()
116+
117+
self.output_data = self.model.calculate_state_estimation(
118+
calculation_method=calculation_method, update_data=update_data, **kwargs
119+
)
120+
return self.output_data
121+
103122
def _create_power_grid_array(self, array_name: str) -> np.ndarray:
104123
"""Create power grid model array"""
105124
internal_array = getattr(self.grid, array_name)

tests/integration/loadflow/test_power_grid_model.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import numpy as np
1010
import pytest
11-
from power_grid_model import ComponentType, TapChangingStrategy, initialize_array
11+
from power_grid_model import ComponentType, MeasuredTerminalType, TapChangingStrategy, initialize_array
1212

1313
from power_grid_model_ds._core.data_source.generator.grid_generators import RadialGridGenerator
1414
from power_grid_model_ds._core.model.grids.base import Grid
@@ -114,6 +114,39 @@ def test_grid_with_automatic_tap_regulator(self, grid_with_tap_regulator: Grid):
114114
assert output["transformer_tap_regulator"]["tap_pos"][0] > 0
115115

116116

117+
class TestCalculateStateEstimation:
118+
def test_simple_grid_with_sensors(self, simple_loadflow_grid: Grid):
119+
core_interface = PowerGridModelInterface(grid=simple_loadflow_grid)
120+
input_data = core_interface.create_input_from_grid()
121+
122+
voltage_sensors = initialize_array("input", "sym_voltage_sensor", 2)
123+
voltage_sensors["id"] = [10, 11]
124+
voltage_sensors["measured_object"] = [0, 1]
125+
voltage_sensors["u_sigma"] = [1.0, 1.0]
126+
voltage_sensors["u_measured"] = [10_500.0, 10_497.5]
127+
voltage_sensors["u_angle_measured"] = [0.0, -0.0002]
128+
129+
power_sensors = initialize_array("input", "sym_power_sensor", 2)
130+
power_sensors["id"] = [12, 13]
131+
power_sensors["measured_object"] = [3, 4]
132+
power_sensors["measured_terminal_type"] = [MeasuredTerminalType.source, MeasuredTerminalType.load]
133+
power_sensors["power_sigma"] = [100.0, 100.0]
134+
power_sensors["p_measured"] = [-250_000.0, 250_000.0]
135+
power_sensors["q_measured"] = [-50_000.0, 50_000.0]
136+
power_sensors["p_sigma"] = [100.0, 100.0]
137+
power_sensors["q_sigma"] = [100.0, 100.0]
138+
139+
input_data["sym_voltage_sensor"] = voltage_sensors
140+
input_data["sym_power_sensor"] = power_sensors
141+
142+
output = core_interface.calculate_state_estimation()
143+
144+
assert output is core_interface.output_data
145+
assert output["node"]["u"][0] == pytest.approx(10_498.75, 0.1)
146+
assert output["node"]["u"][1] == pytest.approx(10_498.75, 0.1)
147+
assert all(output["line"]["i_from"] > 0)
148+
149+
117150
@pytest.fixture
118151
def base_grid() -> Grid:
119152
grid_generator = RadialGridGenerator(grid_class=Grid, nr_nodes=5, nr_sources=1, nr_nops=0)

0 commit comments

Comments
 (0)