Skip to content

Commit

Permalink
Find a NodeTerminal for empty CalculatedBus (#824)
Browse files Browse the repository at this point in the history
Signed-off-by: Mathieu BAGUE <[email protected]>
  • Loading branch information
Mathieu BAGUE committed Jun 18, 2019
1 parent 62e3158 commit 014884b
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import gnu.trove.list.array.TIntArrayList;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;

Expand All @@ -26,9 +24,44 @@ class CalculatedBusImpl extends AbstractBus implements CalculatedBus {

private final List<NodeTerminal> terminals;

CalculatedBusImpl(String id, VoltageLevelExt voltageLevel, List<NodeTerminal> terminals) {
private NodeTerminal terminalRef;

CalculatedBusImpl(String id, NodeBreakerVoltageLevel voltageLevel, TIntArrayList nodes, List<NodeTerminal> terminals) {
super(id, voltageLevel);
this.terminals = Objects.requireNonNull(terminals);
this.terminalRef = findTerminal(voltageLevel, nodes, terminals);
}

/**
* Find a terminal to retrieve voltage, angle or connected and synchronous component numbers.
* If the terminals list contains at least one element, we use the first terminal as reference.
* Otherwise this method tries to find a terminal which does not belong to this bus, but to the same "electrical" bus
* and therefore can be used as reference.
*
* @param voltageLevel The {@literal VoltageLevel} instance to traverse
* @param nodes The nodes which belong to this bus
* @param terminals The terminals belong to this bus
* @return The first terminal of the {@code terminals} list, or a terminal which belongs to an equivalent "electrical" bus.
*/
private static NodeTerminal findTerminal(NodeBreakerVoltageLevel voltageLevel, TIntArrayList nodes, List<NodeTerminal> terminals) {
if (!terminals.isEmpty()) {
return terminals.get(0);
}

NodeTerminal[] terminal = new NodeTerminal[1];

// Traverse the graph until a valid NodeTerminal is found
VoltageLevel.NodeBreakerView.Traverser traverser = (node1, sw, node2) -> {
if (sw.isOpen()) {
return false;
}
terminal[0] = (NodeTerminal) voltageLevel.getNodeBreakerView().getTerminal(node2);
return terminal[0] == null;
};

voltageLevel.getNodeBreakerView().traverse(nodes.getQuick(0), traverser);

return terminal[0];
}

private void checkValidity() {
Expand All @@ -46,6 +79,7 @@ public void invalidate() {
valid = false;
voltageLevel = null;
terminals.clear();
terminalRef = null;
}

@Override
Expand Down Expand Up @@ -89,10 +123,7 @@ public BusExt setV(double v) {
@Override
public double getV() {
checkValidity();
if (terminals.isEmpty()) {
return Double.NaN;
}
return terminals.get(0).getV();
return terminalRef == null ? Double.NaN : terminalRef.getV();
}

@Override
Expand All @@ -107,10 +138,7 @@ public BusExt setAngle(double angle) {
@Override
public double getAngle() {
checkValidity();
if (terminals.isEmpty()) {
return Double.NaN;
}
return terminals.get(0).getAngle();
return terminalRef == null ? Double.NaN : terminalRef.getAngle();
}

@Override
Expand Down Expand Up @@ -138,7 +166,7 @@ public Component getConnectedComponent() {
checkValidity();
NetworkImpl.ConnectedComponentsManager ccm = voltageLevel.getNetwork().getConnectedComponentsManager();
ccm.update();
return terminals.isEmpty() ? null : ccm.getComponent(terminals.get(0).getConnectedComponentNumber());
return terminalRef == null ? null : ccm.getComponent(terminalRef.getConnectedComponentNumber());
}

@Override
Expand All @@ -154,7 +182,7 @@ public Component getSynchronousComponent() {
checkValidity();
NetworkImpl.SynchronousComponentsManager scm = voltageLevel.getNetwork().getSynchronousComponentsManager();
scm.update();
return terminals.isEmpty() ? null : scm.getComponent(terminals.get(0).getSynchronousComponentNumber());
return terminalRef == null ? null : scm.getComponent(terminalRef.getSynchronousComponentNumber());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ private void traverse(int n, boolean[] encountered, Predicate<SwitchImpl> termin
}
}
if (getBusChecker().isValid(graph, nodes, terminals)) {
CalculatedBusImpl bus = new CalculatedBusImpl(busId, NodeBreakerVoltageLevel.this, terminals);
CalculatedBusImpl bus = new CalculatedBusImpl(busId, NodeBreakerVoltageLevel.this, nodes, terminals);
id2bus.put(busId, bus);
for (int i = 0; i < nodes.size(); i++) {
node2bus[nodes.getQuick(i)] = bus;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.powsybl.iidm.network.impl;

import com.powsybl.iidm.network.*;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* @author Nicolas Lhuillier <[email protected]>
* @author Mathieu Bague <[email protected]>
*/
public class MainConnectedComponentWithSwitchTest {

@Test
public void test() {

Network network = NetworkFactory.create("test_mcc", "test");

Substation s1 = network.newSubstation()
.setId("A")
.setCountry(Country.FR)
.add();
VoltageLevel vl1 = s1.newVoltageLevel()
.setId("B")
.setNominalV(225.0)
.setLowVoltageLimit(0.0)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
vl1.getNodeBreakerView().setNodeCount(3);
vl1.getNodeBreakerView().newBusbarSection()
.setId("C")
.setNode(0)
.add();
vl1.getNodeBreakerView().newSwitch()
.setId("D")
.setKind(SwitchKind.DISCONNECTOR)
.setRetained(false)
.setOpen(false)
.setNode1(0)
.setNode2(1)
.add();
vl1.getNodeBreakerView().newSwitch()
.setId("E")
.setKind(SwitchKind.BREAKER)
.setRetained(false)
.setOpen(false)
.setNode1(1)
.setNode2(2)
.add();

Substation s2 = network.newSubstation()
.setId("F")
.setCountry(Country.FR)
.add();
VoltageLevel vl2 = s2.newVoltageLevel()
.setId("G")
.setNominalV(225.0)
.setLowVoltageLimit(0.0)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
vl2.getNodeBreakerView().setNodeCount(5);
vl2.getNodeBreakerView().newBusbarSection()
.setId("H")
.setNode(0)
.add();
vl2.getNodeBreakerView().newBusbarSection()
.setId("I")
.setNode(1)
.add();
vl2.getNodeBreakerView().newSwitch()
.setId("J")
.setKind(SwitchKind.DISCONNECTOR)
.setRetained(true)
.setOpen(false)
.setNode1(0)
.setNode2(2)
.add();
vl2.getNodeBreakerView().newSwitch()
.setId("K")
.setKind(SwitchKind.DISCONNECTOR)
.setRetained(true)
.setOpen(false)
.setNode1(1)
.setNode2(3)
.add();
vl2.getNodeBreakerView().newSwitch()
.setId("L")
.setKind(SwitchKind.BREAKER)
.setRetained(true)
.setOpen(false)
.setNode1(2)
.setNode2(3)
.add();
vl2.getNodeBreakerView().newSwitch()
.setId("M")
.setKind(SwitchKind.BREAKER)
.setRetained(false)
.setOpen(false)
.setNode1(0)
.setNode2(4)
.add();

network.newLine()
.setId("N")
.setR(0.001)
.setX(0.1)
.setG1(0.0)
.setB1(0.0)
.setG2(0.0)
.setB2(0.0)
.setVoltageLevel1("B")
.setNode1(2)
.setVoltageLevel2("G")
.setNode2(4)
.add();

network.getBusView().getBuses().forEach(b -> {
if (b.getVoltageLevel() == vl1) {
b.setV(230.0).setAngle(0.5);
} else {
b.setV(220.0).setAngle(0.7);
}
});

assertEquals(2, network.getBusView().getBusStream().count());
for (Bus b : network.getBusView().getBuses()) {
assertTrue(b.isInMainConnectedComponent());
}

assertEquals(5, network.getBusBreakerView().getBusStream().count());
for (Bus b : network.getBusBreakerView().getBuses()) {
assertTrue(b.isInMainConnectedComponent());
if (b.getVoltageLevel() == vl1) {
assertEquals(230.0, b.getV(), 0.0);
assertEquals(0.5, b.getAngle(), 0.0);
} else {
assertEquals(220.0, b.getV(), 0.0);
assertEquals(0.7, b.getAngle(), 0.0);
}
}
}
}

0 comments on commit 014884b

Please sign in to comment.