Skip to content

Commit

Permalink
clean and test
Browse files Browse the repository at this point in the history
Signed-off-by: Damien Jeandemange <damien.jeandemange@artelys.com>
  • Loading branch information
jeandemanged committed Sep 24, 2024
1 parent 62ac326 commit 6a3b108
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class AreaBoundariesDataframeAdder implements NetworkElementAdder {

private static final List<SeriesMetadata> METADATA = List.of(
SeriesMetadata.stringIndex("id"),
SeriesMetadata.strings("boundary_element"),
SeriesMetadata.strings("boundary_side"),
SeriesMetadata.strings("element"),
SeriesMetadata.strings("side"),
SeriesMetadata.booleans("ac")
);

Expand All @@ -40,27 +40,27 @@ public List<List<SeriesMetadata>> 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");
}

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() {
Expand All @@ -77,17 +77,17 @@ public void addElements(Network network, List<UpdatingDataframe> dataframes) {
Map<Area, List<Pair<Terminal, Boolean>>> 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));
Expand All @@ -97,9 +97,9 @@ public void addElements(Network network, List<UpdatingDataframe> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Series> 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");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -561,17 +560,16 @@ 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
assertEquals(2, area2.getAreaBoundaryStream().count()); // unchanged because area2 is not in updating df

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());
Expand Down
32 changes: 23 additions & 9 deletions pypowsybl/network/impl/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
43 changes: 31 additions & 12 deletions tests/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand All @@ -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()
Expand Down

0 comments on commit 6a3b108

Please sign in to comment.