Skip to content

Commit

Permalink
Remove dangling lines merge by ID
Browse files Browse the repository at this point in the history
Signed-off-by: Olivier Perrin <olivier.perrin@rte-france.com>
  • Loading branch information
olperr1 committed Aug 22, 2023
1 parent 94fe8c0 commit 8d1ae63
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package com.powsybl.iidm.network.util;

import com.google.common.collect.Sets;
import com.powsybl.commons.PowsyblException;
import com.powsybl.commons.reporter.Reporter;
import com.powsybl.iidm.network.DanglingLine;
import com.powsybl.iidm.network.DanglingLineFilter;
Expand Down Expand Up @@ -158,61 +157,40 @@ public static void mergeDifferentAliases(DanglingLine dl1, DanglingLine dl2, Map
/**
* If it exists, find the dangling line in the merging network that should be associated to a candidate dangling line in the network to be merged.
* Two dangling lines in different IGM should be associated if:
* - they have the same ID and at least one has a non-null X-node code
* OR
* - they have the same non-null X-node code and are the only dangling lines to have this X-node code in their respective networks
* OR
* - they have the same non-null X-node code and are the only connected dangling lines to have this X-node code in their respective networks
*
* @param candidateDanglingLine candidate dangling line in the network to be merged
* @param danglingLine dangling line in the merging network with same ID as the candidate dangling line. Can be null.
* @param getDanglingLinesByXnodeCode function to retrieve dangling lines with a given X-node code in the merging network.
* @param associateDanglingLines function associating two dangling lines
*/
public static void findAndAssociateDanglingLines(DanglingLine candidateDanglingLine, DanglingLine danglingLine,
public static void findAndAssociateDanglingLines(DanglingLine candidateDanglingLine,
Function<String, List<DanglingLine>> getDanglingLinesByXnodeCode,
BiConsumer<DanglingLine, DanglingLine> associateDanglingLines) {
Objects.requireNonNull(candidateDanglingLine);
Objects.requireNonNull(getDanglingLinesByXnodeCode);
Objects.requireNonNull(associateDanglingLines);
if (danglingLine == null) { // if dangling line with same ID not present, find dangling line(s) with same X-node code in merging network if present
// mapping by ucte xnode code
if (candidateDanglingLine.getUcteXnodeCode() != null) { // if X-node code null: no associated dangling line
if (candidateDanglingLine.getNetwork().getDanglingLineStream(DanglingLineFilter.UNPAIRED)
.filter(d -> d != candidateDanglingLine)
.filter(d -> candidateDanglingLine.getUcteXnodeCode().equals(d.getUcteXnodeCode()))
.anyMatch(d -> d.getTerminal().isConnected())) { // check that there is no connected dangling line with same X-node code in the network to be merged
return; // in that case, do nothing
// mapping by ucte xnode code
if (candidateDanglingLine.getUcteXnodeCode() != null) { // if X-node code null: no associated dangling line
if (candidateDanglingLine.getNetwork().getDanglingLineStream(DanglingLineFilter.UNPAIRED)
.filter(d -> d != candidateDanglingLine)
.filter(d -> candidateDanglingLine.getUcteXnodeCode().equals(d.getUcteXnodeCode()))
.anyMatch(d -> d.getTerminal().isConnected())) { // check that there is no connected dangling line with same X-node code in the network to be merged
return; // in that case, do nothing
}
List<DanglingLine> dls = getDanglingLinesByXnodeCode.apply(candidateDanglingLine.getUcteXnodeCode());
if (dls != null) {
if (dls.size() == 1) { // if there is exactly one dangling line in the merging network, merge it
associateDanglingLines.accept(dls.get(0), candidateDanglingLine);
}
List<DanglingLine> dls = getDanglingLinesByXnodeCode.apply(candidateDanglingLine.getUcteXnodeCode());
if (dls != null) {
if (dls.size() == 1) { // if there is exactly one dangling line in the merging network, merge it
associateDanglingLines.accept(dls.get(0), candidateDanglingLine);
}
if (dls.size() > 1) { // if more than one dangling line in the merging network, check how many are connected
List<DanglingLine> connectedDls = dls.stream().filter(dl -> dl.getTerminal().isConnected()).toList();
if (connectedDls.size() == 1) { // if there is exactly one connected dangling line in the merging network, merge it. Otherwise, do nothing
associateDanglingLines.accept(connectedDls.get(0), candidateDanglingLine);
}
if (dls.size() > 1) { // if more than one dangling line in the merging network, check how many are connected
List<DanglingLine> connectedDls = dls.stream().filter(dl -> dl.getTerminal().isConnected()).toList();
if (connectedDls.size() == 1) { // if there is exactly one connected dangling line in the merging network, merge it. Otherwise, do nothing
associateDanglingLines.accept(connectedDls.get(0), candidateDanglingLine);
}
}
}
} else {
// if dangling line with same ID present, there is only one: they are associated if the X-node code is identical (if not: throw exception)
boolean nonNullAndDifferent = danglingLine.getUcteXnodeCode() != null && candidateDanglingLine.getUcteXnodeCode() != null
&& !danglingLine.getUcteXnodeCode().equals(candidateDanglingLine.getUcteXnodeCode());
boolean bothNull = danglingLine.getUcteXnodeCode() == null && candidateDanglingLine.getUcteXnodeCode() == null;
if (nonNullAndDifferent || bothNull) {
throw new PowsyblException("Dangling line couple " + danglingLine.getId()
+ " have inconsistent Xnodes (" + danglingLine.getUcteXnodeCode()
+ "!=" + candidateDanglingLine.getUcteXnodeCode() + ")");
}
String code = Optional.ofNullable(danglingLine.getUcteXnodeCode()).orElseGet(candidateDanglingLine::getUcteXnodeCode);
List<DanglingLine> dls = getDanglingLinesByXnodeCode.apply(code);
if (dls != null && dls.size() > 1) {
throw new PowsyblException("Should not have any dangling lines other than " + danglingLine.getId() + " linked to " + code);
}
associateDanglingLines.accept(danglingLine, candidateDanglingLine);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -891,9 +891,6 @@ public void merge(Network other) {
Multimap<Class<? extends Identifiable>, String> intersection = index.intersection(otherNetwork.index);
for (Map.Entry<Class<? extends Identifiable>, Collection<String>> entry : intersection.asMap().entrySet()) {
Class<? extends Identifiable> clazz = entry.getKey();
if (clazz == DanglingLineImpl.class) { // fine for dangling lines
continue;
}
Collection<String> objs = entry.getValue();
if (!objs.isEmpty()) {
throw new PowsyblException("The following object(s) of type "
Expand All @@ -912,7 +909,7 @@ public void merge(Network other) {
}
}
for (DanglingLine dl2 : Lists.newArrayList(other.getDanglingLines(DanglingLineFilter.ALL))) {
findAndAssociateDanglingLines(dl2, getDanglingLine(dl2.getId()), dl1byXnodeCode::get, (dll1, dll2) -> pairDanglingLines(lines, dll1, dll2, dl1byXnodeCode));
findAndAssociateDanglingLines(dl2, dl1byXnodeCode::get, (dll1, dll2) -> pairDanglingLines(lines, dll1, dll2, dl1byXnodeCode));
}

// do not forget to remove the other network from its index!!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,6 @@ public void failMergeWithSameObj() {
assertTrue(e.getMessage().contains("The following object(s) of type SubstationImpl exist(s) in both networks: [P1]"));
}

@Test
public void xnodeNonCompatible() {
addSubstationAndVoltageLevel();
addDanglingLines("dl", "code", "dl", "deco");
merge.merge(n1);
PowsyblException e = assertThrows(PowsyblException.class, () -> merge.merge(n2));
assertTrue(e.getMessage().contains("Dangling line couple dl have inconsistent Xnodes (code!=deco)"));
}

@Test
public void testMerge() {
addSubstationAndVoltageLevel();
Expand All @@ -64,14 +55,12 @@ public void testMerge() {
}

@Test
public void testMergeSameId() {

public void failMergeDanglingLinesWithSameId() {
addSubstationAndVoltageLevel();
addDanglingLines("dl", null, "dl", "code");
merge.merge(n1, n2);
assertNotNull(merge.getTieLine("dl"));
assertEquals("dl", merge.getTieLine("dl").getId());
assertEquals("dl_name", merge.getTieLine("dl").getOptionalName().orElse(null));
assertEquals("dl_name", merge.getTieLine("dl").getNameOrId());
PowsyblException e = assertThrows(PowsyblException.class, () -> merge.merge(n1, n2));
assertTrue(e.getMessage().contains("The following object(s) of type DanglingLineImpl exist(s) in both networks: [dl]"));
}

private void addSubstation(Network network, String substationId) {
Expand Down

0 comments on commit 8d1ae63

Please sign in to comment.