From 6a3b1081fb0eeec57fc0d17484ccc7f9b39dee7b Mon Sep 17 00:00:00 2001 From: Damien Jeandemange Date: Tue, 24 Sep 2024 18:31:14 +0200 Subject: [PATCH] clean and test Signed-off-by: Damien Jeandemange --- .../dataframe/network/NetworkDataframes.java | 4 +- .../adders/AreaBoundariesDataframeAdder.java | 36 ++++++++-------- .../network/NetworkDataframesTest.java | 4 +- .../adders/NetworkElementAddersTest.java | 10 ++--- pypowsybl/network/impl/network.py | 32 ++++++++++---- tests/test_network.py | 43 +++++++++++++------ 6 files changed, 80 insertions(+), 49 deletions(-) diff --git a/java/src/main/java/com/powsybl/dataframe/network/NetworkDataframes.java b/java/src/main/java/com/powsybl/dataframe/network/NetworkDataframes.java index c11652db1..b7517f96d 100644 --- a/java/src/main/java/com/powsybl/dataframe/network/NetworkDataframes.java +++ b/java/src/main/java/com/powsybl/dataframe/network/NetworkDataframes.java @@ -1286,8 +1286,8 @@ private static NetworkDataframeMapper areaBoundaries() { return NetworkDataframeMapperBuilder.ofStream(NetworkDataframes::areaBoundariesData) .stringsIndex("id", pair -> pair.getLeft().getId()) .strings("boundary_type", pair -> getAreaBoundaryType(pair.getRight()), false) - .strings("boundary_element", pair -> getAreaBoundaryElement(pair.getRight())) - .strings("boundary_side", pair -> getAreaBoundarySide(pair.getRight()), false) + .strings("element", pair -> getAreaBoundaryElement(pair.getRight())) + .strings("side", pair -> getAreaBoundarySide(pair.getRight()), false) .booleans("ac", pair -> pair.getRight().isAc()) .doubles("p", (pair, context) -> perUnitPQ(context, pair.getRight().getP())) .doubles("q", (pair, context) -> perUnitPQ(context, pair.getRight().getQ())) diff --git a/java/src/main/java/com/powsybl/dataframe/network/adders/AreaBoundariesDataframeAdder.java b/java/src/main/java/com/powsybl/dataframe/network/adders/AreaBoundariesDataframeAdder.java index 21f155f7c..75c08c4ea 100644 --- a/java/src/main/java/com/powsybl/dataframe/network/adders/AreaBoundariesDataframeAdder.java +++ b/java/src/main/java/com/powsybl/dataframe/network/adders/AreaBoundariesDataframeAdder.java @@ -27,8 +27,8 @@ public class AreaBoundariesDataframeAdder implements NetworkElementAdder { private static final List METADATA = List.of( SeriesMetadata.stringIndex("id"), - SeriesMetadata.strings("boundary_element"), - SeriesMetadata.strings("boundary_side"), + SeriesMetadata.strings("element"), + SeriesMetadata.strings("side"), SeriesMetadata.booleans("ac") ); @@ -40,14 +40,14 @@ public List> getMetadata() { private static final class AreaBoundaries { private final StringSeries ids; - private final StringSeries boundaryElements; - private final StringSeries boundarySides; + private final StringSeries elements; + private final StringSeries sides; private final IntSeries acs; AreaBoundaries(UpdatingDataframe dataframe) { this.ids = getRequiredStrings(dataframe, "id"); - this.boundaryElements = getRequiredStrings(dataframe, "boundary_element"); - this.boundarySides = getRequiredStrings(dataframe, "boundary_side"); + this.elements = getRequiredStrings(dataframe, "element"); + this.sides = dataframe.getStrings("side"); this.acs = getRequiredInts(dataframe, "ac"); } @@ -55,12 +55,12 @@ public StringSeries getIds() { return ids; } - public StringSeries getBoundaryElements() { - return boundaryElements; + public StringSeries getElements() { + return elements; } - public StringSeries getBoundarySides() { - return boundarySides; + public StringSeries getSides() { + return sides; } public IntSeries getAcs() { @@ -77,17 +77,17 @@ public void addElements(Network network, List dataframes) { Map>> terminalBoundaries = new HashMap<>(); for (int i = 0; i < primaryTable.getRowCount(); i++) { String areaId = series.getIds().get(i); - String boundaryElement = series.getBoundaryElements().get(i); - String boundarySide = series.getBoundarySides().get(i); + String element = series.getElements().get(i); + String side = series.getSides() == null ? "" : series.getSides().get(i); boolean ac = series.getAcs().get(i) == 1; Area area = network.getArea(areaId); if (area == null) { throw new PowsyblException("Area " + areaId + " not found"); } - // an empty boundaryElement alone for an area indicates remove all boundaries in area - Connectable connectable = boundaryElement.isEmpty() ? null : network.getConnectable(boundaryElement); - if (!boundaryElement.isEmpty() && connectable == null) { - throw new PowsyblException("Connectable " + boundaryElement + " not found"); + // an empty element alone for an area indicates remove all boundaries in area + Connectable connectable = element.isEmpty() ? null : network.getConnectable(element); + if (!element.isEmpty() && connectable == null) { + throw new PowsyblException("Connectable " + element + " not found"); } if (connectable == null) { danglingLineBoundaries.computeIfAbsent(area, k -> new ArrayList<>()).add(Pair.of(null, null)); @@ -97,9 +97,9 @@ public void addElements(Network network, List dataframes) { } else if (connectable instanceof Injection injection) { terminalBoundaries.computeIfAbsent(area, k -> new ArrayList<>()).add(Pair.of(injection.getTerminal(), ac)); } else if (connectable instanceof Branch branch) { - terminalBoundaries.computeIfAbsent(area, k -> new ArrayList<>()).add(Pair.of(branch.getTerminal(TwoSides.valueOf(boundarySide)), ac)); + terminalBoundaries.computeIfAbsent(area, k -> new ArrayList<>()).add(Pair.of(branch.getTerminal(TwoSides.valueOf(side)), ac)); } else if (connectable instanceof ThreeWindingsTransformer t3wt) { - terminalBoundaries.computeIfAbsent(area, k -> new ArrayList<>()).add(Pair.of(t3wt.getTerminal(ThreeSides.valueOf(boundarySide)), ac)); + terminalBoundaries.computeIfAbsent(area, k -> new ArrayList<>()).add(Pair.of(t3wt.getTerminal(ThreeSides.valueOf(side)), ac)); } } // delete boundaries of involved areas diff --git a/java/src/test/java/com/powsybl/dataframe/network/NetworkDataframesTest.java b/java/src/test/java/com/powsybl/dataframe/network/NetworkDataframesTest.java index 9853dd0fa..eec026b3d 100644 --- a/java/src/test/java/com/powsybl/dataframe/network/NetworkDataframesTest.java +++ b/java/src/test/java/com/powsybl/dataframe/network/NetworkDataframesTest.java @@ -716,11 +716,11 @@ void areasBoundaries() { assertThat(series) .extracting(Series::getName) - .containsExactly("id", "boundary_element", "ac", "p", "q"); + .containsExactly("id", "element", "ac", "p", "q"); List allAttributeSeries = createDataFrame(AREA_BOUNDARIES, network, new DataframeFilter(ALL_ATTRIBUTES, Collections.emptyList())); assertThat(allAttributeSeries) .extracting(Series::getName) - .containsExactly("id", "boundary_type", "boundary_element", "boundary_side", "ac", "p", "q"); + .containsExactly("id", "boundary_type", "element", "side", "ac", "p", "q"); } } diff --git a/java/src/test/java/com/powsybl/dataframe/network/adders/NetworkElementAddersTest.java b/java/src/test/java/com/powsybl/dataframe/network/adders/NetworkElementAddersTest.java index 9212a218b..18b5391f1 100644 --- a/java/src/test/java/com/powsybl/dataframe/network/adders/NetworkElementAddersTest.java +++ b/java/src/test/java/com/powsybl/dataframe/network/adders/NetworkElementAddersTest.java @@ -550,8 +550,7 @@ void areaBoundaries() { .add(); var dataframe = new DefaultUpdatingDataframe(4); addStringColumn(dataframe, "id", "area1", "area1", "area2", "area2"); - addStringColumn(dataframe, "boundary_element", "NHV1_XNODE1", "NVH1_XNODE2", "XNODE1_NHV2", "XNODE2_NHV2"); - addStringColumn(dataframe, "boundary_side", "", "", "", ""); + addStringColumn(dataframe, "element", "NHV1_XNODE1", "NVH1_XNODE2", "XNODE1_NHV2", "XNODE2_NHV2"); addIntColumn(dataframe, "ac", 1, 1, 1, 1); assertEquals(0, area1.getAreaBoundaryStream().count()); assertEquals(0, area2.getAreaBoundaryStream().count()); @@ -561,8 +560,7 @@ void areaBoundaries() { dataframe = new DefaultUpdatingDataframe(1); addStringColumn(dataframe, "id", "area1"); - addStringColumn(dataframe, "boundary_element", ""); - addStringColumn(dataframe, "boundary_side", ""); + addStringColumn(dataframe, "element", ""); addIntColumn(dataframe, "ac", 1); NetworkElementAdders.addElements(DataframeElementType.AREA_BOUNDARIES, network, singletonList(dataframe)); assertEquals(0, area1.getAreaBoundaryStream().count()); // cleared @@ -570,8 +568,8 @@ void areaBoundaries() { dataframe = new DefaultUpdatingDataframe(1); addStringColumn(dataframe, "id", "area1"); - addStringColumn(dataframe, "boundary_element", "NGEN_NHV1"); - addStringColumn(dataframe, "boundary_side", "TWO"); + addStringColumn(dataframe, "element", "NGEN_NHV1"); + addStringColumn(dataframe, "side", "TWO"); addIntColumn(dataframe, "ac", 1); NetworkElementAdders.addElements(DataframeElementType.AREA_BOUNDARIES, network, singletonList(dataframe)); assertEquals(1, area1.getAreaBoundaryStream().count()); diff --git a/pypowsybl/network/impl/network.py b/pypowsybl/network/impl/network.py index 821d3ed6c..1404e1186 100644 --- a/pypowsybl/network/impl/network.py +++ b/pypowsybl/network/impl/network.py @@ -2509,8 +2509,8 @@ def get_areas_boundaries(self, all_attributes: bool = False, attributes: List[st - **id**: area identifier - **boundary_type** (optional): either `DANGLING_LINE` or `TERMINAL` - - **boundary_element**: either identifier of the Dangling Line or the equipment terminal - - **boundary_side** (optional): equipment side + - **element**: either identifier of the Dangling Line or the equipment terminal + - **side** (optional): equipment side - **ac**: True if the boundary is considered as AC and not DC - **p**: Active power at boundary (MW) - **q**: Reactive power at boundary (MW) @@ -2528,7 +2528,7 @@ def get_areas_boundaries(self, all_attributes: bool = False, attributes: List[st will output something like: ============= ================ ===== =========== =========== - \ boundary_element ac p q + \ element ac p q ============= ================ ===== =========== =========== id ControlArea_A NHV1_XNODE1 True -301.474347 -116.518644 @@ -4803,9 +4803,7 @@ def create_areas_voltage_levels(self, df: DataFrame = None, **kwargs: ArrayLike) - **voltage_level_id**: the identifier of the voltage level to be associated with the area Examples: - To associate voltage levels VL1 and VL2 to Area1. Note that any other voltage level than VL1 and VL2 - previously associated to Area1 will be dissociated from Area1. Any existing other area than Area1 is - kept unchanged. + To associate voltage levels VL1 and VL2 to Area1. .. code-block:: python @@ -4838,12 +4836,28 @@ def create_areas_boundaries(self, df: DataFrame = None, **kwargs: ArrayLike) -> Valid attributes are: - **id**: the identifier of the area - - **boundary_element**: dangling line identifier, or any connectable - - **boundary_side**: if boundary_element is not a dangling line (e.g. a branch or transformer), the terminal side + - **element**: dangling line identifier, or any connectable + - **side**: if element is not a dangling line (e.g. a branch or transformer), the terminal side - **ac**: True is boundary is to be considered as AC Examples: - TODO + To associate voltage levels VL1 and VL2 to Area1. + + .. code-block:: python + + # define dangling lines NHV1_XNODE1 and NVH1_XNODE2 as boundaries of AreaA, and + # define dangling lines XNODE1_NHV2 and XNODE2_NHV2 as boundaries of AreaB + network.create_areas_boundaries(id=['AreaA', 'AreaA', 'AreaB', 'AreaB'], + element=['NHV1_XNODE1', 'NVH1_XNODE2', 'XNODE1_NHV2', 'XNODE2_NHV2'], + side=['', '', '', ''], + ac=[True, True, True, True]) + + To clear all boundaries of Area2. + + .. code-block:: python + + # Any existing other area than AreaA is kept unchanged. + n.create_areas_boundaries(id='AreaA', element='', side='', ac=False) """ return self._create_elements(ElementType.AREA_BOUNDARIES, [df], **kwargs) diff --git a/tests/test_network.py b/tests/test_network.py index d6682e8a3..0c5a91f72 100644 --- a/tests/test_network.py +++ b/tests/test_network.py @@ -685,12 +685,12 @@ def test_areas_voltage_levels_data_frame(): def test_areas_boundaries_data_frame(): n = pp.network.create_eurostag_tutorial_example1_with_tie_lines_and_areas() - areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'boundary_element']) + areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'element']) expected = pd.DataFrame( index=pd.Series(name='id', data=[ 'ControlArea_A', 'ControlArea_A', 'ControlArea_B', 'ControlArea_B']), - columns=['boundary_type', 'boundary_element', 'boundary_side', 'ac', 'p', 'q'], + columns=['boundary_type', 'element', 'side', 'ac', 'p', 'q'], data=[['DANGLING_LINE', 'NHV1_XNODE1', '', True, -301.47, -116.51], ['DANGLING_LINE', 'NVH1_XNODE2', '', True, -301.47, -116.51], ['DANGLING_LINE', 'XNODE1_NHV2', '', True, +301.47, +116.43], @@ -699,38 +699,57 @@ def test_areas_boundaries_data_frame(): # test creation n = pp.network.create_eurostag_tutorial_example1_with_tie_lines_and_areas() - n.create_areas_boundaries(id='ControlArea_A', boundary_element='', boundary_side='', ac=False) - n.create_areas_boundaries(id='ControlArea_B', boundary_element='', boundary_side='', ac=False) + n.create_areas_boundaries(id='ControlArea_A', element='', side='', ac=False) + n.create_areas_boundaries(id='ControlArea_B', element='', side='', ac=False) n.create_areas(id=['testAreaA', 'testAreaB'], area_type=['testAreaType', 'testAreaType'], interchange_target=[10., nan]) n.create_areas_boundaries(id=['testAreaA', 'testAreaA', 'testAreaB', 'testAreaB'], - boundary_element=['NHV1_XNODE1', 'NVH1_XNODE2', 'XNODE1_NHV2', 'XNODE2_NHV2'], - boundary_side=['', '', '', ''], + element=['NHV1_XNODE1', 'NVH1_XNODE2', 'XNODE1_NHV2', 'XNODE2_NHV2'], ac=[True, True, True, True]) - areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'boundary_element']) + areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'element']) expected = pd.DataFrame( index=pd.Series(name='id', data=[ 'testAreaA', 'testAreaA', 'testAreaB', 'testAreaB']), - columns=['boundary_type', 'boundary_element', 'boundary_side', 'ac', 'p', 'q'], + columns=['boundary_type', 'element', 'side', 'ac', 'p', 'q'], data=[['DANGLING_LINE', 'NHV1_XNODE1', '', True, -301.47, -116.51], ['DANGLING_LINE', 'NVH1_XNODE2', '', True, -301.47, -116.51], ['DANGLING_LINE', 'XNODE1_NHV2', '', True, +301.47, +116.43], ['DANGLING_LINE', 'XNODE2_NHV2', '', True, +301.47, +116.43]]) pd.testing.assert_frame_equal(expected, areas_boundaries, check_dtype=False, atol=1e-2) - # removal is a bit special, have to supply an empty string - n.create_areas_boundaries(id='testAreaA', boundary_element='', boundary_side='', ac=False) - areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'boundary_element']) + # removal is a bit special, have to supply an empty element string + n.create_areas_boundaries(id='testAreaA', element='', ac=False) + areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'element']) expected = pd.DataFrame( index=pd.Series(name='id', data=[ 'testAreaB', 'testAreaB']), - columns=['boundary_type', 'boundary_element', 'boundary_side', 'ac', 'p', 'q'], + columns=['boundary_type', 'element', 'side', 'ac', 'p', 'q'], data=[['DANGLING_LINE', 'XNODE1_NHV2', '', True, +301.47, +116.43], ['DANGLING_LINE', 'XNODE2_NHV2', '', True, +301.47, +116.43]]) pd.testing.assert_frame_equal(expected, areas_boundaries, check_dtype=False, atol=1e-2) + # test using terminals instead of dangling lines, e.g. boundary located at NGEN_NHV1 HV side + n = pp.network.create_eurostag_tutorial_example1_network() + n.create_areas(id=['testAreaA', 'testAreaB'], + area_type=['testAreaType', 'testAreaType'], + interchange_target=[10., nan]) + n.update_2_windings_transformers(id='NGEN_NHV1', p2=-600, q2=-50) + n.update_lines(id=['NHV1_NHV2_1', 'NHV1_NHV2_2'], p1=[300, 300], q1=[25, 25]) + n.create_areas_boundaries(id=['testAreaA', 'testAreaB', 'testAreaB'], + element=['NGEN_NHV1', 'NHV1_NHV2_1', 'NHV1_NHV2_2'], + side=['TWO', 'ONE', 'ONE'], + ac=[True, True, True]) + areas_boundaries = n.get_areas_boundaries(all_attributes=True).sort_values(by=['id', 'element']) + expected = pd.DataFrame( + index=pd.Series(name='id', data=['testAreaA', 'testAreaB', 'testAreaB']), + columns=['boundary_type', 'element', 'side', 'ac', 'p', 'q'], + data=[['TERMINAL', 'NGEN_NHV1', 'TWO', True, -600, -50], + ['TERMINAL', 'NHV1_NHV2_1', 'ONE', True, 300, 25], + ['TERMINAL', 'NHV1_NHV2_2', 'ONE', True, 300, 25]]) + pd.testing.assert_frame_equal(expected, areas_boundaries, check_dtype=False, atol=1e-2) + def test_update_unknown_data(): n = pp.network.create_eurostag_tutorial_example1_network()