diff --git a/src/power_grid_model_ds/_core/model/arrays/__init__.py b/src/power_grid_model_ds/_core/model/arrays/__init__.py index 780deb25..a69bba0e 100644 --- a/src/power_grid_model_ds/_core/model/arrays/__init__.py +++ b/src/power_grid_model_ds/_core/model/arrays/__init__.py @@ -7,14 +7,19 @@ """ from power_grid_model_ds._core.model.arrays.pgm_arrays import ( + AsymCurrentSensorArray, + AsymLineArray, + AsymPowerSensorArray, AsymVoltageSensorArray, Branch3Array, BranchArray, + GenericBranchArray, IdArray, LineArray, LinkArray, NodeArray, SourceArray, + SymCurrentSensorArray, SymGenArray, SymLoadArray, SymPowerSensorArray, @@ -25,9 +30,12 @@ ) __all__ = [ + "AsymPowerSensorArray", "AsymVoltageSensorArray", + "AsymCurrentSensorArray", "Branch3Array", "BranchArray", + "GenericBranchArray", "IdArray", "LineArray", "LinkArray", @@ -35,8 +43,10 @@ "SourceArray", "SymLoadArray", "SymGenArray", + "SymCurrentSensorArray", "SymPowerSensorArray", "SymVoltageSensorArray", + "AsymLineArray", "ThreeWindingTransformerArray", "TransformerArray", "TransformerTapRegulatorArray", diff --git a/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py b/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py index 9280d727..0e4b9bcf 100644 --- a/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py +++ b/src/power_grid_model_ds/_core/model/arrays/pgm_arrays.py @@ -13,8 +13,10 @@ from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.dtypes.appliances import Source, SymGen, SymLoad from power_grid_model_ds._core.model.dtypes.branches import ( + AsymLine, Branch, Branch3, + GenericBranch, Line, Link, ThreeWindingTransformer, @@ -23,7 +25,14 @@ from power_grid_model_ds._core.model.dtypes.id import Id from power_grid_model_ds._core.model.dtypes.nodes import Node from power_grid_model_ds._core.model.dtypes.regulators import TransformerTapRegulator -from power_grid_model_ds._core.model.dtypes.sensors import AsymVoltageSensor, SymPowerSensor, SymVoltageSensor +from power_grid_model_ds._core.model.dtypes.sensors import ( + AsymCurrentSensor, + AsymPowerSensor, + AsymVoltageSensor, + SymCurrentSensor, + SymPowerSensor, + SymVoltageSensor, +) # pylint: disable=missing-class-docstring @@ -99,6 +108,14 @@ class TransformerArray(Transformer, BranchArray): pass +class GenericBranchArray(GenericBranch, BranchArray): + pass + + +class AsymLineArray(AsymLine, BranchArray): + pass + + class Branch3Array(IdArray, Branch3): def as_branches(self) -> BranchArray: """Convert Branch3Array to BranchArray.""" @@ -138,5 +155,17 @@ class SymVoltageSensorArray(IdArray, SymVoltageSensor): pass +class SymCurrentSensorArray(IdArray, SymCurrentSensor): + pass + + +class AsymPowerSensorArray(IdArray, AsymPowerSensor): + pass + + class AsymVoltageSensorArray(IdArray, AsymVoltageSensor): pass + + +class AsymCurrentSensorArray(IdArray, AsymCurrentSensor): + pass diff --git a/src/power_grid_model_ds/_core/model/dtypes/branches.py b/src/power_grid_model_ds/_core/model/dtypes/branches.py index e4a2aea1..87e868ea 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/branches.py +++ b/src/power_grid_model_ds/_core/model/dtypes/branches.py @@ -43,6 +43,19 @@ class Line(Branch): i_n: NDArray[np.float64] # rated current +class GenericBranch(Branch): + """GenericBranch data type (generic_branch in power-grid-model) + + Off-nominal ratio k and phase shift theta are modelled explicitly. Rated power sn optional. + The impedance (r1, x1) and admittance (g1, b1) are given wrt the to-side. + """ + + r1: NDArray[np.float64] # positive-sequence resistance + x1: NDArray[np.float64] # positive-sequence reactance + g1: NDArray[np.float64] # positive-sequence conductance + b1: NDArray[np.float64] # positive-sequence susceptance + + class Transformer(Branch): """Transformer data type""" @@ -115,3 +128,34 @@ class ThreeWindingTransformer(Branch3): pk_12_max: NDArray[np.float64] pk_13_max: NDArray[np.float64] pk_23_max: NDArray[np.float64] + + +class AsymLine(Branch): + """Asymmetric Line data type (asym_line in power-grid-model) + + Supports 3 or 4 phase (with neutral) resistance / reactance matrices and optional capacitance matrix + or sequence capacitances c0/c1. If c_* matrix is omitted, c0 & c1 may be specified instead. + Only include fields; validation logic handled elsewhere (not implemented here yet). + """ + + # Resistance matrix entries (series) + r_aa: NDArray[np.float64] + r_ba: NDArray[np.float64] + r_bb: NDArray[np.float64] + r_ca: NDArray[np.float64] + r_cb: NDArray[np.float64] + r_cc: NDArray[np.float64] + + # Reactance matrix entries (series) + x_aa: NDArray[np.float64] + x_ba: NDArray[np.float64] + x_bb: NDArray[np.float64] + x_ca: NDArray[np.float64] + x_cb: NDArray[np.float64] + x_cc: NDArray[np.float64] + + # Alternative sequence capacitances + c0: NDArray[np.float64] + c1: NDArray[np.float64] + + i_n: NDArray[np.float64] # rated current diff --git a/src/power_grid_model_ds/_core/model/dtypes/sensors.py b/src/power_grid_model_ds/_core/model/dtypes/sensors.py index 513e0169..20a728ba 100644 --- a/src/power_grid_model_ds/_core/model/dtypes/sensors.py +++ b/src/power_grid_model_ds/_core/model/dtypes/sensors.py @@ -43,6 +43,15 @@ class SymPowerSensor(GenericPowerSensor): q_sigma: NDArray[np.float64] # std of reactive power +class AsymPowerSensor(GenericPowerSensor): + """AsymPowerSensor data type""" + + p_measured: NDArray3[np.float64] # measured active power + q_measured: NDArray3[np.float64] # measured reactive power + p_sigma: NDArray3[np.float64] # std of active power + q_sigma: NDArray3[np.float64] # std of reactive power + + class GenericVoltageSensor(Sensor): """Base class for voltage sensor data type""" @@ -61,3 +70,26 @@ class AsymVoltageSensor(GenericVoltageSensor): u_sigma: NDArray3[np.float64] # std of 3 voltages u_measured: NDArray3[np.float64] # measured 3 voltages u_angle_measured: NDArray3[np.float64] # measured 3 phases + + +class GenericCurrentSensor(Sensor): + """Base class for current sensor data type""" + + measured_terminal_type: NDArray[np.int32] + angle_measurement_type: NDArray[np.int32] + i_sigma: NDArray[np.float64] + i_angle_sigma: NDArray[np.float64] + + +class SymCurrentSensor(GenericCurrentSensor): + """SymCurrentSensor data type""" + + i_measured: NDArray[np.float64] + i_angle_measured: NDArray[np.float64] + + +class AsymCurrentSensor(GenericCurrentSensor): + """AsymCurrentSensor data type""" + + i_measured: NDArray3[np.float64] + i_angle_measured: NDArray3[np.float64] diff --git a/src/power_grid_model_ds/_core/model/grids/_text_sources.py b/src/power_grid_model_ds/_core/model/grids/_text_sources.py index ab9c1a9c..548242e3 100644 --- a/src/power_grid_model_ds/_core/model/grids/_text_sources.py +++ b/src/power_grid_model_ds/_core/model/grids/_text_sources.py @@ -7,6 +7,8 @@ import logging from typing import TYPE_CHECKING +from power_grid_model import ComponentType + from power_grid_model_ds._core.model.enums.nodes import NodeType if TYPE_CHECKING: @@ -94,10 +96,14 @@ def add_branch(self, branch: tuple[str, str], comments: list[str]): from_node = int(from_node_str.replace("S", "")) to_node = int(to_node_str.replace("S", "")) - if "transformer" in comments: + if ComponentType.transformer.value in comments: new_branch = self.grid.transformer.empty(1) - elif "link" in comments: + elif ComponentType.link.value in comments: new_branch = self.grid.link.empty(1) + elif ComponentType.generic_branch.value in comments: + new_branch = self.grid.generic_branch.empty(1) + elif ComponentType.asym_line.value in comments: + new_branch = self.grid.asym_line.empty(1) else: # assume it is a line new_branch = self.grid.line.empty(1) diff --git a/src/power_grid_model_ds/_core/model/grids/base.py b/src/power_grid_model_ds/_core/model/grids/base.py index aacd636a..f35e9342 100644 --- a/src/power_grid_model_ds/_core/model/grids/base.py +++ b/src/power_grid_model_ds/_core/model/grids/base.py @@ -14,16 +14,22 @@ import numpy as np import numpy.typing as npt +from power_grid_model import ComponentType from power_grid_model_ds._core import fancypy as fp from power_grid_model_ds._core.model.arrays import ( + AsymCurrentSensorArray, + AsymLineArray, + AsymPowerSensorArray, AsymVoltageSensorArray, Branch3Array, BranchArray, + GenericBranchArray, LineArray, LinkArray, NodeArray, SourceArray, + SymCurrentSensorArray, SymGenArray, SymLoadArray, SymPowerSensorArray, @@ -72,6 +78,8 @@ class Grid(FancyArrayContainer): three_winding_transformer: ThreeWindingTransformerArray line: LineArray link: LinkArray + generic_branch: GenericBranchArray + asym_line: AsymLineArray source: SourceArray sym_load: SymLoadArray @@ -83,7 +91,10 @@ class Grid(FancyArrayContainer): # sensors sym_power_sensor: SymPowerSensorArray sym_voltage_sensor: SymVoltageSensorArray + sym_current_sensor: SymCurrentSensorArray + asym_power_sensor: AsymPowerSensorArray asym_voltage_sensor: AsymVoltageSensorArray + asym_current_sensor: AsymCurrentSensorArray def __str__(self) -> str: """String representation of the grid. @@ -109,13 +120,17 @@ def __str__(self) -> str: suffix_str = f"{suffix_str},open" if branch.id in self.transformer.id: - suffix_str = f"{suffix_str},transformer" + suffix_str = f"{suffix_str},{ComponentType.transformer.value}" elif branch.id in self.link.id: - suffix_str = f"{suffix_str},link" + suffix_str = f"{suffix_str},{ComponentType.link.value}" elif branch.id in self.line.id: pass # no suffix needed + elif branch.id in self.generic_branch.id: + suffix_str = f"{suffix_str},{ComponentType.generic_branch.value}" + elif branch.id in self.asym_line.id: + suffix_str = f"{suffix_str},{ComponentType.asym_line.value}" else: - raise ValueError(f"Branch {branch.id} is not a transformer, link or line") + raise ValueError(f"Branch {branch.id} is not a transformer, link, line, generic_branch or asym_line") grid_str += f"{from_node_str} {to_node_str} {suffix_str}\n" return grid_str @@ -141,7 +156,7 @@ def branch_arrays(self) -> list[BranchArray]: return branch_arrays def get_typed_branches(self, branch_ids: list[int] | npt.NDArray[np.int32]) -> BranchArray: - """Find a matching LineArray, LinkArray or TransformerArray for the given branch_ids + """Find a matching Branch-subtype array for the given branch_ids Raises: ValueError: @@ -162,7 +177,7 @@ def reverse_branches(self, branches: BranchArray): """Reverse the direction of the branches.""" if not branches.size: return - if not isinstance(branches, (LineArray, LinkArray, TransformerArray)): + if not isinstance(branches, (LineArray, LinkArray, TransformerArray, GenericBranchArray, AsymLineArray)): try: branches = self.get_typed_branches(branches.id) except ValueError: diff --git a/src/power_grid_model_ds/_core/visualizer/app.py b/src/power_grid_model_ds/_core/visualizer/app.py index 169aacbc..c6775113 100644 --- a/src/power_grid_model_ds/_core/visualizer/app.py +++ b/src/power_grid_model_ds/_core/visualizer/app.py @@ -5,6 +5,7 @@ import dash_bootstrap_components as dbc from dash import Dash, dcc, html from dash_bootstrap_components.icons import FONT_AWESOME +from power_grid_model import ComponentType from power_grid_model_ds._core.model.grids.base import Grid from power_grid_model_ds._core.visualizer.callbacks import ( # noqa: F401 # pylint: disable=unused-import @@ -57,11 +58,13 @@ def _get_columns_store(grid: Grid) -> dcc.Store: return dcc.Store( id="columns-store", data={ - "node": grid.node.columns, - "line": grid.line.columns, - "link": grid.link.columns, - "transformer": grid.transformer.columns, - "three_winding_transformer": grid.three_winding_transformer.columns, + ComponentType.node: grid.node.columns, + ComponentType.line: grid.line.columns, + ComponentType.link: grid.link.columns, + ComponentType.transformer: grid.transformer.columns, + ComponentType.three_winding_transformer: grid.three_winding_transformer.columns, + ComponentType.asym_line: grid.asym_line.columns, + ComponentType.generic_branch: grid.generic_branch.columns, "branch": grid.branches.columns, }, ) diff --git a/src/power_grid_model_ds/_core/visualizer/layout/colors.py b/src/power_grid_model_ds/_core/visualizer/layout/colors.py index 47be645a..32df9853 100644 --- a/src/power_grid_model_ds/_core/visualizer/layout/colors.py +++ b/src/power_grid_model_ds/_core/visualizer/layout/colors.py @@ -2,15 +2,20 @@ # # SPDX-License-Identifier: MPL-2.0 + YELLOW = "#facc37" CYTO_COLORS = { "line": YELLOW, "link": "#008000", "transformer": "#4290f5", "node": YELLOW, + "generic_branch": "#dddddd", + "asym_line": "#2de2ca", "selected": "#e28743", "selected_transformer": "#0349a3", "selected_link": "#004000", + "selected_generic_branch": "#9e9e9e", + "selected_asym_line": "#1D9181", "substation_node": "purple", "open_branch": "#c9c9c9", "highlighted": "#a10000", diff --git a/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py b/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py index ef0db275..658c667d 100644 --- a/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py +++ b/src/power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py @@ -4,6 +4,8 @@ """Contains selectors for the Cytoscape stylesheet.""" +from power_grid_model import ComponentType + from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS NODE_SIZE = 100 @@ -12,8 +14,8 @@ _BRANCH_STYLE = { "selector": "edge", "style": { - "line-color": CYTO_COLORS["line"], - "target-arrow-color": CYTO_COLORS["line"], + "line-color": CYTO_COLORS[ComponentType.line], + "target-arrow-color": CYTO_COLORS[ComponentType.line], "curve-style": "bezier", "target-arrow-shape": "triangle", "width": BRANCH_WIDTH, @@ -85,6 +87,30 @@ "style": {"line-color": CYTO_COLORS["selected_link"], "target-arrow-color": CYTO_COLORS["selected_link"]}, } +_GENERIC_BRANCH_STYLE = { + "selector": "edge[group = 'generic_branch']", + "style": {"line-color": CYTO_COLORS["generic_branch"], "target-arrow-color": CYTO_COLORS["generic_branch"]}, +} +_SELECTED_GENERIC_BRANCH_STYLE = { + "selector": "edge[group = 'generic_branch']:selected, edge[group = 'generic_branch']:active", + "style": { + "line-color": CYTO_COLORS["selected_generic_branch"], + "target-arrow-color": CYTO_COLORS["selected_generic_branch"], + }, +} + +_ASYM_LINE_STYLE = { + "selector": "edge[group = 'asym_line']", + "style": {"line-color": CYTO_COLORS["asym_line"], "target-arrow-color": CYTO_COLORS["asym_line"]}, +} + +_SELECTED_ASYM_LINE_STYLE = { + "selector": "edge[group = 'asym_line']:selected, edge[group = 'asym_line']:active", + "style": { + "line-color": CYTO_COLORS["selected_asym_line"], + "target-arrow-color": CYTO_COLORS["selected_asym_line"], + }, +} _OPEN_BRANCH_STYLE = { "selector": "edge[from_status = 0], edge[to_status = 0]", "style": { @@ -124,4 +150,8 @@ _OPEN_BRANCH_STYLE, _OPEN_FROM_SIDE_BRANCH_STYLE, _OPEN_TO_SIDE_BRANCH_STYLE, + _GENERIC_BRANCH_STYLE, + _SELECTED_GENERIC_BRANCH_STYLE, + _ASYM_LINE_STYLE, + _SELECTED_ASYM_LINE_STYLE, ] diff --git a/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py b/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py index e66d36f8..68865d75 100644 --- a/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py +++ b/src/power_grid_model_ds/_core/visualizer/layout/header_legenda.py @@ -19,6 +19,8 @@ _LINE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["line"]} _LINK_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["link"]} _TRANSFORMER_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["transformer"]} +_GENERIC_BRANCH_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["generic_branch"]} +_ASYM_LINE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["asym_line"]} _OPEN_BRANCH_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["open_branch"]} LEGENDA_ELEMENTS = [ html.I(className="fas fa-circle", id="node-icon", style=NODE_ICON_STYLE), @@ -31,6 +33,10 @@ dbc.Tooltip("Transformer", target="transformer-icon", placement="bottom"), html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="link-icon", style=_LINK_ICON_STYLE), dbc.Tooltip("Link", target="link-icon", placement="bottom"), + html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="generic-branch-icon", style=_GENERIC_BRANCH_ICON_STYLE), + dbc.Tooltip("Generic Branch", target="generic-branch-icon", placement="bottom"), + html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="asym-line-icon", style=_ASYM_LINE_ICON_STYLE), + dbc.Tooltip("Asymmetrical Line", target="asym-line-icon", placement="bottom"), html.I(className="fas fa-ellipsis", id="open-branch-icon", style=_OPEN_BRANCH_ICON_STYLE), dbc.Tooltip("Open Branch", target="open-branch-icon", placement="bottom"), ] diff --git a/src/power_grid_model_ds/_core/visualizer/parsers.py b/src/power_grid_model_ds/_core/visualizer/parsers.py index 50b048fd..9ed131a8 100644 --- a/src/power_grid_model_ds/_core/visualizer/parsers.py +++ b/src/power_grid_model_ds/_core/visualizer/parsers.py @@ -32,7 +32,10 @@ def parse_branches(grid: Grid) -> list[dict[str, Any]]: parsed_branches.extend(parse_branch_array(grid.line, "line")) parsed_branches.extend(parse_branch_array(grid.link, "link")) parsed_branches.extend(parse_branch_array(grid.transformer, "transformer")) + parsed_branches.extend(parse_branch_array(grid.generic_branch, "generic_branch")) + parsed_branches.extend(parse_branch_array(grid.asym_line, "asym_line")) parsed_branches.extend(parse_branch3_array(grid.three_winding_transformer, "transformer")) + return parsed_branches @@ -56,7 +59,10 @@ def parse_branch3_array(branches: Branch3Array, group: Literal["transformer"]) - return parsed_branches -def parse_branch_array(branches: BranchArray, group: Literal["line", "link", "transformer"]) -> list[dict[str, Any]]: +def parse_branch_array( + branches: BranchArray, + group: Literal["line", "link", "transformer", "generic_branch", "asym_line"], +) -> list[dict[str, Any]]: """Parse the branch array.""" parsed_branches = [] columns = branches.columns diff --git a/src/power_grid_model_ds/arrays.py b/src/power_grid_model_ds/arrays.py index 5fdfc450..80f08c60 100644 --- a/src/power_grid_model_ds/arrays.py +++ b/src/power_grid_model_ds/arrays.py @@ -3,14 +3,18 @@ # SPDX-License-Identifier: MPL-2.0 from power_grid_model_ds._core.model.arrays import ( + AsymCurrentSensorArray, + AsymLineArray, AsymVoltageSensorArray, Branch3Array, BranchArray, + GenericBranchArray, IdArray, LineArray, LinkArray, NodeArray, SourceArray, + SymCurrentSensorArray, SymGenArray, SymLoadArray, SymPowerSensorArray, @@ -26,6 +30,8 @@ "BranchArray", "LinkArray", "LineArray", + "GenericBranchArray", + "AsymLineArray", "TransformerArray", "Branch3Array", "ThreeWindingTransformerArray", @@ -34,6 +40,8 @@ "SymLoadArray", "TransformerTapRegulatorArray", "AsymVoltageSensorArray", + "AsymCurrentSensorArray", "SymPowerSensorArray", "SymVoltageSensorArray", + "SymCurrentSensorArray", ] diff --git a/tests/integration/visualizer_tests.py b/tests/integration/visualizer_tests.py index 2cb437a5..77e6ca75 100644 --- a/tests/integration/visualizer_tests.py +++ b/tests/integration/visualizer_tests.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: MPL-2.0 + from dataclasses import dataclass from power_grid_model_ds import Grid @@ -49,7 +50,19 @@ def visualize_grid_with_links(): visualize(grid=get_grid_with_links(), debug=True) +def visualize_grid_with_all_types(): + grid = Grid.from_txt( + "1 2 12", + "2 3 link,23", + "3 4 transformer,34", + "4 5 generic_branch,45", + "5 6 asym_line,56", + ) + visualize(grid=grid, debug=True) + + if __name__ == "__main__": - visualize_grid() + # visualize_grid() # visualize_coordinated_grid() # visualize_grid_with_links() + visualize_grid_with_all_types() diff --git a/tests/unit/model/arrays/test_build.py b/tests/unit/model/arrays/test_build.py index 07f90458..2bbfe82d 100644 --- a/tests/unit/model/arrays/test_build.py +++ b/tests/unit/model/arrays/test_build.py @@ -8,7 +8,7 @@ from numpy.typing import NDArray from power_grid_model_ds._core import fancypy as fp -from power_grid_model_ds._core.model.arrays import AsymVoltageSensorArray, SymPowerSensorArray +from power_grid_model_ds._core.model.arrays import AsymVoltageSensorArray from power_grid_model_ds._core.model.arrays.base.array import FancyArray from power_grid_model_ds._core.model.arrays.base.errors import ArrayDefinitionError from power_grid_model_ds._core.model.constants import EMPTY_ID @@ -232,27 +232,13 @@ def test_initialization_from_args_with_extra_columns(): assert "undefined" not in array.dtype.names -def test_sensor_array(): - test_len = 2 - # test proper intiliazation of a SensorArray - pow_sens = SymPowerSensorArray.empty(test_len) - sym_pow_fields = [ - "measured_object", - "measured_terminal_type", - "power_sigma", - "p_measured", - "p_sigma", - "q_measured", - "q_sigma", - ] - for field in sym_pow_fields: - assert field in pow_sens.dtype.fields - +def test_asymmetric_sensor_array(): + array_length = 2 # test if asymmetric array has NDArray3 fields, i.e. with 3 floats per element (one per phase) - asym_volt_sens = AsymVoltageSensorArray.empty(test_len) + asym_volt_sens = AsymVoltageSensorArray.empty(array_length) nd3_fields = ["u_sigma", "u_measured", "u_angle_measured"] for field in nd3_fields: - assert asym_volt_sens[field].shape == (test_len, 3) + assert asym_volt_sens[field].shape == (array_length, 3) def test_inherit_defaults_from_multiple_parents(): diff --git a/tests/unit/model/grids/test_grid_base.py b/tests/unit/model/grids/test_grid_base.py index 1527a80e..5faf3ac5 100644 --- a/tests/unit/model/grids/test_grid_base.py +++ b/tests/unit/model/grids/test_grid_base.py @@ -31,20 +31,25 @@ def test_initialize_empty_grid(grid: Grid): assert isinstance(grid, Grid) fields = dataclasses.asdict(grid).keys() assert { - "link", - "sym_load", - "sym_power_sensor", - "source", "_id_counter", - "transformer_tap_regulator", + "asym_current_sensor", + "asym_line", + "asym_power_sensor", "asym_voltage_sensor", - "three_winding_transformer", - "transformer", - "node", + "generic_branch", + "graphs", "line", + "link", + "node", + "source", + "sym_current_sensor", "sym_gen", - "graphs", + "sym_load", + "sym_power_sensor", "sym_voltage_sensor", + "three_winding_transformer", + "transformer", + "transformer_tap_regulator", } == set(fields) @@ -401,3 +406,18 @@ def test_from_txt_file(self, tmp_path: Path): assert 1 == grid.branches.filter(to_status=0).size assert 1 == grid.transformer.size np.testing.assert_array_equal([14, 10, 11, 12, 13, 15, 16, 17], grid.branches.id) + + def test_from_txt_all_branch_types(self): + grid = Grid.from_txt( + "1 2 12", + "2 3 link,23", + "3 4 transformer,34", + "4 5 generic_branch,45", + "5 6 asym_line,56", + ) + + assert grid.line.id.tolist() == [12] + assert grid.link.id.tolist() == [23] + assert grid.transformer.id.tolist() == [34] + assert grid.generic_branch.id.tolist() == [45] + assert grid.asym_line.id.tolist() == [56]