diff --git a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/TieLineUtil.java b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/TieLineUtil.java index 89f30f93cfb..92ca0dc529b 100644 --- a/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/TieLineUtil.java +++ b/iidm/iidm-api/src/main/java/com/powsybl/iidm/network/util/TieLineUtil.java @@ -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; @@ -159,61 +158,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> getDanglingLinesByXnodeCode, BiConsumer 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 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 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 connectedDls = dls.stream().filter(dl -> dl.getTerminal().isConnected()).collect(Collectors.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 connectedDls = dls.stream().filter(dl -> dl.getTerminal().isConnected()).collect(Collectors.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 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); } } diff --git a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java index 4b1f6bbfbc4..e6f172ae25a 100644 --- a/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java +++ b/iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NetworkImpl.java @@ -944,9 +944,6 @@ private void merge(Network other, boolean allowSubnetworkCreationForMyself) { Multimap, String> intersection = index.intersection(otherNetwork.index); for (Map.Entry, Collection> entry : intersection.asMap().entrySet()) { Class clazz = entry.getKey(); - if (clazz == DanglingLineImpl.class) { // fine for dangling lines - continue; - } Collection objs = entry.getValue(); if (!objs.isEmpty()) { throw new PowsyblException("The following object(s) of type " @@ -978,7 +975,7 @@ private void merge(Network other, boolean allowSubnetworkCreationForMyself) { } } 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!!! diff --git a/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/AbstractMergeNetworkTest.java b/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/AbstractMergeNetworkTest.java index 08b19f3c980..ff297fa76f9 100644 --- a/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/AbstractMergeNetworkTest.java +++ b/iidm/iidm-tck/src/test/java/com/powsybl/iidm/network/tck/AbstractMergeNetworkTest.java @@ -56,15 +56,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() { - addCommonSubstationsAndVoltageLevels(); - addCommonDanglingLines("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() { addCommonSubstationsAndVoltageLevels(); @@ -269,14 +260,11 @@ private void checkDanglingLineStatusCount(Network network, long unpairedNb, long } @Test - public void testMergeSameId() { + public void failMergeDanglingLinesWithSameId() { addCommonSubstationsAndVoltageLevels(); addCommonDanglingLines("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]")); } @Test