Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/power_grid_model_ds/_core/model/arrays/base/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,13 @@ def as_df(self: Self):
if pandas is None:
raise ImportError("pandas is not installed")
return pandas.DataFrame(self._data)

@classmethod
def from_extended(cls: Type[Self], extended: Self) -> Self:
"""Create an instance from an extended array."""
if not isinstance(extended, cls):
raise TypeError(f"Extended array must be of type {cls.__name__}, got {type(extended).__name__}")
new_array = cls.zeros(len(extended), empty_id=False)
for column in cls.get_dtype().names:
new_array[column] = extended[column]
return new_array
17 changes: 17 additions & 0 deletions src/power_grid_model_ds/_core/model/grids/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,23 @@ def set_feeder_ids(self):
set_is_feeder(grid=self)
set_feeder_ids(grid=self)

@classmethod
def from_extended(cls, extended: "Grid", load_graphs: bool = True) -> "Grid":
"""Create a grid from an extended Grid object."""
new_grid = cls.empty()

for field in dataclasses.fields(cls):
if issubclass(field.type, FancyArray):
extended_array = getattr(extended, field.name)
new_array = field.type.from_extended(extended_array)
setattr(new_grid, field.name, new_array)

new_grid._id_counter = new_grid.max_id

if load_graphs:
new_grid.graphs = GraphContainer.from_arrays(new_grid)
return new_grid


def _add_branch_array(branch: BranchArray | Branch3Array, grid: Grid):
"""Add a branch array to the grid"""
Expand Down
17 changes: 17 additions & 0 deletions tests/fixtures/arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import numpy as np
from numpy._typing import NDArray

from power_grid_model_ds._core.model.arrays import LineArray, NodeArray
from power_grid_model_ds._core.model.arrays.base.array import FancyArray
from power_grid_model_ds._core.model.dtypes.sensors import NDArray3

Expand Down Expand Up @@ -57,3 +58,19 @@ class FancyTestArray3(FancyArray):

test_float1: NDArray3[np.float64]
test_float2: NDArray3[np.float64]


class ExtendedNodeArray(NodeArray):
"""Extends the node array with an output value"""

_defaults = {"u": 0}

u: NDArray[np.float64]


class ExtendedLineArray(LineArray):
"""Extends the line array with an output value"""

_defaults = {"i_from": 0}

i_from: NDArray[np.float64]
5 changes: 4 additions & 1 deletion tests/fixtures/grid_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
from dataclasses import dataclass

from power_grid_model_ds._core.model.grids.base import Grid
from tests.fixtures.arrays import ExtendedLineArray, ExtendedNodeArray


@dataclass
class ExtendedGrid(Grid):
"""Grid with an extra container"""
"""ExtendedGrid class for testing purposes."""

node: ExtendedNodeArray
line: ExtendedLineArray
extra_value: int = 123
16 changes: 7 additions & 9 deletions tests/fixtures/grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@

from power_grid_model_ds._core.model.arrays import (
LineArray,
LinkArray,
NodeArray,
SourceArray,
SymLoadArray,
ThreeWindingTransformerArray,
TransformerArray,
)
from power_grid_model_ds._core.model.enums.nodes import NodeType
from power_grid_model_ds._core.model.grids.base import Grid
Expand Down Expand Up @@ -44,18 +42,18 @@ def build_basic_grid(grid: T) -> T:
# ***

# Add Substations
substation = NodeArray(id=[101], u_rated=[10_500.0], node_type=[NodeType.SUBSTATION_NODE.value])
substation = grid.node.__class__(id=[101], u_rated=[10_500.0], node_type=[NodeType.SUBSTATION_NODE.value])
grid.append(substation, check_max_id=False)

# Add Nodes
nodes = NodeArray(
nodes = grid.node.__class__(
id=[102, 103, 104, 105, 106],
u_rated=[10_500.0] * 4 + [400.0],
)
grid.append(nodes, check_max_id=False)

# Add Lines
lines = LineArray(
lines = grid.line.__class__(
id=[201, 202, 203, 204],
from_status=[1, 1, 0, 1],
to_status=[1, 1, 0, 1],
Expand All @@ -70,7 +68,7 @@ def build_basic_grid(grid: T) -> T:
grid.append(lines, check_max_id=False)

# Add a transformer
transformer = TransformerArray.empty(1)
transformer = grid.transformer.__class__.empty(1)
transformer.id = 301
transformer.from_status = 1
transformer.to_status = 1
Expand All @@ -80,7 +78,7 @@ def build_basic_grid(grid: T) -> T:
grid.append(transformer, check_max_id=False)

# Add a link
link = LinkArray.empty(1)
link = grid.link.__class__.empty(1)
link.id = 601
link.from_status = 1
link.to_status = 1
Expand All @@ -90,7 +88,7 @@ def build_basic_grid(grid: T) -> T:
grid.append(link, check_max_id=False)

# Loads
loads = SymLoadArray(
loads = grid.sym_load.__class__(
id=[401, 402, 403, 404],
node=[102, 103, 104, 105],
type=[1] * 4,
Expand All @@ -101,7 +99,7 @@ def build_basic_grid(grid: T) -> T:
grid.append(loads, check_max_id=False)

# Add Source
source = SourceArray(id=[501], node=[101], status=[1], u_ref=[0.0])
source = grid.source.__class__(id=[501], node=[101], status=[1], u_ref=[0.0])
grid.append(source, check_max_id=False)
grid.check_ids()

Expand Down
17 changes: 1 addition & 16 deletions tests/integration/loadflow/test_power_grid_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,12 @@
)
from power_grid_model_ds._core.model.arrays.pgm_arrays import TransformerTapRegulatorArray
from power_grid_model_ds._core.model.grids.base import Grid
from tests.fixtures.arrays import ExtendedLineArray, ExtendedNodeArray
from tests.unit.model.grids.test_custom_grid import CustomGrid

# pylint: disable=missing-function-docstring,missing-class-docstring


class ExtendedNodeArray(NodeArray):
"""Extends the node array with an output value"""

_defaults = {"u": 0}

u: NDArray[np.float64]


class ExtendedLineArray(LineArray):
"""Extends the line array with an output value"""

_defaults = {"i_from": 0}

i_from: NDArray[np.float64]


def test_load_flow_on_random():
"""Tests the power flow on a randomly configured grid"""
grid_generator = RadialGridGenerator(grid_class=Grid, nr_nodes=5, nr_sources=1, nr_nops=0)
Expand Down
11 changes: 9 additions & 2 deletions tests/unit/model/arrays/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

from power_grid_model_ds._core import fancypy as fp
from power_grid_model_ds._core.model.arrays.base.array import FancyArray
from power_grid_model_ds._core.model.arrays.pgm_arrays import TransformerArray
from power_grid_model_ds._core.model.arrays.pgm_arrays import LineArray, TransformerArray
from power_grid_model_ds._core.model.constants import EMPTY_ID, empty
from tests.conftest import FancyTestArray
from tests.fixtures.arrays import FancyTestArray3
from tests.fixtures.arrays import ExtendedLineArray, FancyTestArray3

# pylint: disable=missing-function-docstring

Expand Down Expand Up @@ -289,3 +289,10 @@ def test_overflow_value():
with pytest.raises(OverflowError):
transformer.tap_min = -167
assert transformer.tap_min == -128


def test_from_extended_array():
extended_array = ExtendedLineArray.zeros(2)
array = LineArray.from_extended(extended_array)
assert not isinstance(array, ExtendedLineArray)
assert_array_equal(array.data, extended_array[array.columns])
13 changes: 13 additions & 0 deletions tests/unit/model/grids/test_grid_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import numpy as np
import pytest
from numpy.ma.testutils import assert_array_equal

from power_grid_model_ds._core.model.arrays import (
LineArray,
Expand All @@ -20,6 +21,7 @@
from power_grid_model_ds._core.model.constants import EMPTY_ID
from power_grid_model_ds._core.model.grids.base import Grid
from tests.fixtures.grid_classes import ExtendedGrid
from tests.fixtures.grids import build_basic_grid

# pylint: disable=missing-function-docstring,missing-class-docstring

Expand Down Expand Up @@ -50,6 +52,17 @@ def test_initialize_empty_extended_grid():
assert isinstance(grid, ExtendedGrid)


def test_from_extended_grid():
extended_grid = build_basic_grid(ExtendedGrid.empty())
grid = Grid.from_extended(extended_grid)
assert not isinstance(grid, ExtendedGrid)
assert_array_equal(grid.line.data, extended_grid.line.data[grid.line.columns])
assert grid.node.size
assert grid.branches.size
assert grid.graphs.active_graph.nr_nodes == len(grid.node)
assert grid.graphs.complete_graph.nr_nodes == len(grid.branches)


def test_grid_build(basic_grid: Grid):
grid = basic_grid

Expand Down
Loading