Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Flow decomposition] Fix net position computation with dangling lines #134

Merged
merged 5 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,12 @@ Map<Country, Double> run(Network network) {
static Map<Country, Double> computeNetPositions(Network network) {
Map<Country, Double> netPositions = new EnumMap<>(Country.class);

network.getLineStream().forEach(line -> {
Country countrySide1 = NetworkUtil.getTerminalCountry(line.getTerminal1());
Country countrySide2 = NetworkUtil.getTerminalCountry(line.getTerminal2());
if (countrySide1.equals(countrySide2)) {
return;
}
addLeavingFlow(netPositions, line, countrySide1);
addLeavingFlow(netPositions, line, countrySide2);
network.getDanglingLineStream().forEach(danglingLine -> {
Country country = NetworkUtil.getTerminalCountry(danglingLine.getTerminal());
addLeavingFlow(netPositions, danglingLine, country);
});

network.getTieLineStream().forEach(line -> {
network.getLineStream().forEach(line -> {
Country countrySide1 = NetworkUtil.getTerminalCountry(line.getTerminal1());
Country countrySide2 = NetworkUtil.getTerminalCountry(line.getTerminal2());
if (countrySide1.equals(countrySide2)) {
Expand Down Expand Up @@ -65,24 +60,17 @@ private static void addLeavingFlow(Map<Country, Double> netPositions, Line line,
netPositions.put(country, previousValue + getLeavingFlow(line, country));
}

private static void addLeavingFlow(Map<Country, Double> netPositions, TieLine line, Country country) {
double previousValue = getPreviousValue(netPositions, country);
netPositions.put(country, previousValue + getLeavingFlow(line, country));
}

private static void addLeavingFlow(Map<Country, Double> netPositions, HvdcLine hvdcLine, Country country) {
double previousValue = getPreviousValue(netPositions, country);
netPositions.put(country, previousValue + getLeavingFlow(hvdcLine, country));
}

private static double getLeavingFlow(Line line, Country country) {
double flowSide1 = line.getTerminal1().isConnected() && !Double.isNaN(line.getTerminal1().getP()) ? line.getTerminal1().getP() : 0;
double flowSide2 = line.getTerminal2().isConnected() && !Double.isNaN(line.getTerminal2().getP()) ? line.getTerminal2().getP() : 0;
double directFlow = (flowSide1 - flowSide2) / 2;
return country.equals(NetworkUtil.getTerminalCountry(line.getTerminal1())) ? directFlow : -directFlow;
private static void addLeavingFlow(Map<Country, Double> netPositions, DanglingLine danglingLine, Country country) {
double previousValue = getPreviousValue(netPositions, country);
netPositions.put(country, previousValue + getLeavingFlow(danglingLine));
}

private static double getLeavingFlow(TieLine line, Country country) {
private static double getLeavingFlow(Line line, Country country) {
double flowSide1 = line.getTerminal1().isConnected() && !Double.isNaN(line.getTerminal1().getP()) ? line.getTerminal1().getP() : 0;
double flowSide2 = line.getTerminal2().isConnected() && !Double.isNaN(line.getTerminal2().getP()) ? line.getTerminal2().getP() : 0;
double directFlow = (flowSide1 - flowSide2) / 2;
Expand All @@ -95,4 +83,8 @@ private static double getLeavingFlow(HvdcLine hvdcLine, Country country) {
double directFlow = (flowSide1 - flowSide2) / 2;
return country.equals(NetworkUtil.getTerminalCountry(hvdcLine.getConverterStation1().getTerminal())) ? directFlow : -directFlow;
}

private static double getLeavingFlow(DanglingLine danglingLine) {
return danglingLine.getTerminal().isConnected() && !Double.isNaN(danglingLine.getTerminal().getP()) ? danglingLine.getTerminal().getP() : 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void testSingleN1PostContingencyState() {
TestUtils.assertCoherenceTotalFlow(flowDecompositionParameters.isRescaleEnabled(), flowDecompositionResults);

Map<String, DecomposedFlow> decomposedFlowMap = flowDecompositionResults.getDecomposedFlowMap();
validateFlowDecompositionOnXnec(xnecId, branchId, contingencyId, decomposedFlowMap.get(xnecId), -1269.932, -22.027);
validateFlowDecompositionOnXnec(xnecId, branchId, contingencyId, decomposedFlowMap.get(xnecId), -1269.932, 31.943);
}

@Test
Expand All @@ -69,8 +69,8 @@ void testNStateAndN1PostContingencyState() {
TestUtils.assertCoherenceTotalFlow(flowDecompositionParameters.isRescaleEnabled(), flowDecompositionResults);

Map<String, DecomposedFlow> decomposedFlowMap = flowDecompositionResults.getDecomposedFlowMap();
validateFlowDecompositionOnXnec(xnecId1, branchId, contingencyId1, decomposedFlowMap.get(xnecId1), -300.420, -15.496);
validateFlowDecompositionOnXnec(xnecId2, branchId, contingencyId2, decomposedFlowMap.get(xnecId2), -1269.932, -22.027);
validateFlowDecompositionOnXnec(xnecId1, branchId, contingencyId1, decomposedFlowMap.get(xnecId1), -300.420, 22.472);
validateFlowDecompositionOnXnec(xnecId2, branchId, contingencyId2, decomposedFlowMap.get(xnecId2), -1269.932, 31.943);
}

@Test
Expand All @@ -95,7 +95,7 @@ void testSingleN2PostContingencyState() {
TestUtils.assertCoherenceTotalFlow(flowDecompositionParameters.isRescaleEnabled(), flowDecompositionResults);

Map<String, DecomposedFlow> decomposedFlowMap = flowDecompositionResults.getDecomposedFlowMap();
validateFlowDecompositionOnXnec(xnecId, branchId, contingencyId, decomposedFlowMap.get(xnecId), -406.204, 3.329);
validateFlowDecompositionOnXnec(xnecId, branchId, contingencyId, decomposedFlowMap.get(xnecId), -406.204, 48.362);
}

@Test
Expand Down Expand Up @@ -125,9 +125,9 @@ void testNStateN1AndN2PostContingencyState() {
TestUtils.assertCoherenceTotalFlow(flowDecompositionParameters.isRescaleEnabled(), flowDecompositionResults);

Map<String, DecomposedFlow> decomposedFlowMap = flowDecompositionResults.getDecomposedFlowMap();
validateFlowDecompositionOnXnec(xnecId1, branchId, contingencyId1, decomposedFlowMap.get(xnecId1), -300.420, -15.496);
validateFlowDecompositionOnXnec(xnecId2, branchId, contingencyId2, decomposedFlowMap.get(xnecId2), -1269.932, -22.027);
validateFlowDecompositionOnXnec(xnecId3, branchId, contingencyId3, decomposedFlowMap.get(xnecId3), -406.204, 3.329);
validateFlowDecompositionOnXnec(xnecId1, branchId, contingencyId1, decomposedFlowMap.get(xnecId1), -300.420, 22.472);
validateFlowDecompositionOnXnec(xnecId2, branchId, contingencyId2, decomposedFlowMap.get(xnecId2), -1269.932, 31.943);
validateFlowDecompositionOnXnec(xnecId3, branchId, contingencyId3, decomposedFlowMap.get(xnecId3), -406.204, 48.362);
}

private static void validateFlowDecompositionOnXnec(String xnecId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.powsybl.iidm.network.Country;
import com.powsybl.iidm.network.Network;
import com.powsybl.loadflow.LoadFlow;
import com.powsybl.loadflow.LoadFlowParameters;
import org.junit.jupiter.api.Test;

import java.util.Map;
Expand All @@ -18,43 +19,107 @@
/**
* @author Sebastien Murgey {@literal <sebastien.murgey at rte-france.com>}
* @author Peter Mitri {@literal <peter.mitri at rte-france.com>}
* @author Hugo Schindler{@literal <hugo.schindler@rte-france.com>}
*/
class NetPositionTest {
private static final double DOUBLE_TOLERANCE = 1e-3;

@Test
void testLines() {
Network network = Network.read("testCase.xiidm", getClass().getResourceAsStream("testCase.xiidm"));
private static void assertNetPosition(Network network, double netPositionBe, double netPositionNl, double netPositionDe) {
Map<Country, Double> netPositions = NetPositionComputer.computeNetPositions(network);
assertEquals(1000.0, netPositions.get(Country.FR), DOUBLE_TOLERANCE);
assertEquals(1500.0, netPositions.get(Country.BE), DOUBLE_TOLERANCE);
assertEquals(0.0, netPositions.get(Country.NL), DOUBLE_TOLERANCE);
assertEquals(-2500.0, netPositions.get(Country.DE), DOUBLE_TOLERANCE);
assertEquals(netPositionBe, netPositions.get(Country.BE), DOUBLE_TOLERANCE);
assertEquals(netPositionNl, netPositions.get(Country.NL), DOUBLE_TOLERANCE);
assertEquals(netPositionDe, netPositions.get(Country.DE), DOUBLE_TOLERANCE);
double sumAllNetPositions = netPositions.values().stream().mapToDouble(Double::doubleValue).sum();
assertEquals(0.0, sumAllNetPositions, DOUBLE_TOLERANCE);
}

private static void assertNetPositionForHvdc(Network network, double countryNetPosition) {
Map<Country, Double> netPositions = NetPositionComputer.computeNetPositions(network);
assertEquals(countryNetPosition, netPositions.get(Country.FR), DOUBLE_TOLERANCE);
assertEquals(-countryNetPosition, netPositions.get(Country.DE), DOUBLE_TOLERANCE);
double sumAllNetPositions = netPositions.values().stream().mapToDouble(Double::doubleValue).sum();
assertEquals(0.0, sumAllNetPositions, DOUBLE_TOLERANCE);
}

@Test
void testLines() {
Network network = Network.read("testCase.xiidm", getClass().getResourceAsStream("testCase.xiidm"));
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
assertNetPosition(network, 1500.0, 0.0, -2500.0);
}

@Test
void testLinesDisconnected() {
Network network = Network.read("testCase.xiidm", getClass().getResourceAsStream("testCase.xiidm"));
network.getBranch("NNL2AA1 BBE3AA1 1").getTerminal1().disconnect();
network.getBranch("NNL2AA1 BBE3AA1 1").getTerminal2().disconnect();
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
assertNetPosition(network, 1500.0, 0.0, -2500.0);
}

@Test
void testLinesNaN() {
Network network = Network.read("testCase.xiidm", getClass().getResourceAsStream("testCase.xiidm"));
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
network.getBranch("NNL2AA1 BBE3AA1 1").getTerminal1().setP(Double.NaN);
network.getBranch("NNL2AA1 BBE3AA1 1").getTerminal2().setP(Double.NaN);
assertNetPosition(network, 324.666, 1175.334, -2500.0);
}

@Test
void testDanglingLinesBalanced() {
Network network = Network.read("TestCaseDangling.xiidm", getClass().getResourceAsStream("TestCaseDangling.xiidm"));
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
assertNetPosition(network, 2300.0, -500.0, -2800.0);
}

@Test
void testDanglingLines() {
void testDanglingLinesDisconnected() {
Network network = Network.read("TestCaseDangling.xiidm", getClass().getResourceAsStream("TestCaseDangling.xiidm"));
LoadFlow.run(network);
network.getDanglingLine("BBE2AA1 X_BEFR1 1").getTerminal().disconnect();
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
assertNetPosition(network, 2300.0, -500.0, -2800.0);
}

@Test
void testDanglingLinesNaN() {
Network network = Network.read("TestCaseDangling.xiidm", getClass().getResourceAsStream("TestCaseDangling.xiidm"));
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
network.getDanglingLine("BBE2AA1 X_BEFR1 1").getTerminal().setP(Double.NaN);
assertNetPosition(network, 2300.0, -500.0, -2800.0);
}

@Test
void testDanglingLinesUnbalanced() {
Network network = Network.read("NETWORK_SINGLE_LOAD_TWO_GENERATORS_WITH_UNBOUNDED_XNODE.uct", getClass().getResourceAsStream("NETWORK_SINGLE_LOAD_TWO_GENERATORS_WITH_UNBOUNDED_XNODE.uct"));
LoadFlow.run(network, new LoadFlowParameters().setDc(true));
Map<Country, Double> netPositions = NetPositionComputer.computeNetPositions(network);
assertEquals(1000.0, netPositions.get(Country.FR), DOUBLE_TOLERANCE);
assertEquals(2300.0, netPositions.get(Country.BE), DOUBLE_TOLERANCE);
assertEquals(-500.0, netPositions.get(Country.NL), DOUBLE_TOLERANCE);
assertEquals(-2800.0, netPositions.get(Country.DE), DOUBLE_TOLERANCE);
assertEquals(100, netPositions.get(Country.FR), DOUBLE_TOLERANCE);
assertEquals(0, netPositions.get(Country.BE), DOUBLE_TOLERANCE);
double sumAllNetPositions = netPositions.values().stream().mapToDouble(Double::doubleValue).sum();
assertEquals(0.0, sumAllNetPositions, DOUBLE_TOLERANCE);
assertEquals(100, sumAllNetPositions, DOUBLE_TOLERANCE);
}

@Test
void testHvdcLines() {
Network network = Network.read("TestCaseHvdc.xiidm", getClass().getResourceAsStream("TestCaseHvdc.xiidm"));
Map<Country, Double> netPositions = NetPositionComputer.computeNetPositions(network);
assertEquals(272.0, netPositions.get(Country.FR), DOUBLE_TOLERANCE);
assertEquals(-272.0, netPositions.get(Country.DE), DOUBLE_TOLERANCE);
double sumAllNetPositions = netPositions.values().stream().mapToDouble(Double::doubleValue).sum();
assertEquals(0.0, sumAllNetPositions, DOUBLE_TOLERANCE);
assertNetPositionForHvdc(network, 272.0);
}

@Test
void testHvdcLinesDisconnected() {
Network network = Network.read("TestCaseHvdc.xiidm", getClass().getResourceAsStream("TestCaseHvdc.xiidm"));
network.getHvdcLine("hvdc_line_FR_1_DE").getConverterStation1().getTerminal().disconnect();
network.getHvdcLine("hvdc_line_FR_1_DE").getConverterStation2().getTerminal().disconnect();
assertNetPositionForHvdc(network, 200.0);
}

@Test
void testHvdcLinesNaN() {
Network network = Network.read("TestCaseHvdc.xiidm", getClass().getResourceAsStream("TestCaseHvdc.xiidm"));
network.getHvdcLine("hvdc_line_FR_1_DE").getConverterStation1().getTerminal().setP(Double.NaN);
network.getHvdcLine("hvdc_line_FR_1_DE").getConverterStation2().getTerminal().setP(Double.NaN);
assertNetPositionForHvdc(network, 200.0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
##C 2007.05.01
This is a test network with only two branches.
Each branch is linking a generator with a central load.
Used to validate:
- Basic network importer
- XNEC automatic selection
- GLSK automatic generation
- Zone automatic extraction
##N
##ZFR
FGEN1 11 GEN 0 3 400.00 0.00000 0.00000 -100.00 0.00000 1000.00 -1000.0 1000.00 -1000.0
##ZBE
BGEN2 11 GEN 0 2 400.00 0.00000 0.00000 -100.00 0.00000 1000.00 -1000.0 1000.00 -1000.0
BLOAD 11 LOAD 0 0 100.000 0.00000 0.00000 0.00000
##ZXX
X 11 XNODE 0 0 100.000 0.00000 0.00000 0.00000 1000.00 -1000.0 1000.00 -1000.0
##L
FGEN1 11 BLOAD 11 1 0 1.0000 0.0500 0.000000 480 LINE
BLOAD 11 BGEN2 11 1 0 1.0000 0.0500 0.000000 480 LINE
BLOAD 11 X 11 1 0 1.0000 0.0500 0.000000 480 LINE
Loading