RescalingTests.java
/*
* Copyright (c) 2022, 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.flow_decomposition;
import com.powsybl.flow_decomposition.rescaler.DecomposedFlowRescalerAcerMethodology;
import com.powsybl.flow_decomposition.rescaler.DecomposedFlowRescalerMaxCurrentOverload;
import com.powsybl.flow_decomposition.rescaler.DecomposedFlowRescalerNoOp;
import com.powsybl.flow_decomposition.rescaler.DecomposedFlowRescalerProportional;
import com.powsybl.flow_decomposition.xnec_provider.XnecProviderAllBranches;
import com.powsybl.flow_decomposition.xnec_provider.XnecProviderByIds;
import com.powsybl.iidm.network.Country;
import com.powsybl.iidm.network.Network;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Sebastien Murgey {@literal <sebastien.murgey at rte-france.com>}
* @author Hugo Schindler {@literal <hugo.schindler at rte-france.com>}
* @author Caio Luke {@literal <caio.luke at artelys.com>}
*/
class RescalingTests {
private static final double EPSILON = 1e-5;
private void checkRescaleAcReference(double acReferenceFlow, double dcReferenceFlow, DecomposedFlow rescaledFlow, double expectedAllocatedFlow, double expectedPstFlow, double expectedLoopFlowBE, double expectedLoopFlowES) {
double expectedInternalFlow = -300;
double expectedLoopFlowGE = -100;
assertEquals(Math.abs(acReferenceFlow), rescaledFlow.getTotalFlow(), EPSILON);
assertEquals(expectedAllocatedFlow, rescaledFlow.getAllocatedFlow(), EPSILON);
assertEquals(expectedPstFlow, rescaledFlow.getPstFlow(), EPSILON);
assertEquals(expectedLoopFlowBE, rescaledFlow.getLoopFlow(Country.BE), EPSILON);
assertEquals(expectedLoopFlowGE, rescaledFlow.getLoopFlow(Country.GE), EPSILON);
assertEquals(expectedLoopFlowES, rescaledFlow.getLoopFlow(Country.ES), EPSILON);
assertEquals(expectedInternalFlow, rescaledFlow.getInternalFlow(), EPSILON);
assertEquals(acReferenceFlow, rescaledFlow.getAcTerminal1ReferenceFlow(), EPSILON);
assertEquals(dcReferenceFlow, rescaledFlow.getDcReferenceFlow(), EPSILON);
}
private void checkRescaleSmallerAcReference(double acReferenceFlow, double dcReferenceFlow, DecomposedFlow rescaledFlow) {
checkRescaleAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow, 80, 160, 400, 560);
}
private void checkRescaleBiggerAcReference(double acReferenceFlow, double dcReferenceFlow, DecomposedFlow rescaledFlow) {
checkRescaleAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow, 120, 240, 600, 840);
}
private DecomposedFlow getDecomposedFlow(double acReferenceFlow, double dcReferenceFlow) {
double allocatedFlow = 100;
double pstFlow = 200.;
double internalFlow = -300.;
Map<Country, Double> loopFlowsPerCountry = new TreeMap<>();
loopFlowsPerCountry.put(Country.BE, 500.);
loopFlowsPerCountry.put(Country.GE, -100.);
loopFlowsPerCountry.put(Country.ES, 700.);
Country country1 = Country.FR;
Country country2 = Country.FR;
return new DecomposedFlowBuilder()
.withBranchId("")
.withContingencyId("")
.withCountry1(country1)
.withCountry2(country2)
.withAcTerminal1ReferenceFlow(acReferenceFlow)
.withAcTerminal2ReferenceFlow(acReferenceFlow)
.withDcReferenceFlow(dcReferenceFlow)
.withFlowPartition(new FlowPartition(internalFlow, allocatedFlow, loopFlowsPerCountry, pstFlow, 0))
.build();
}
private DecomposedFlow getRescaledFlow(double acReferenceFlow, double dcReferenceFlow) {
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
assertEquals(Math.abs(dcReferenceFlow), decomposedFlow.getTotalFlow(), EPSILON);
return new DecomposedFlowRescalerAcerMethodology().rescale(decomposedFlow);
}
@Test
void testAcerNormalizationWithPositiveBiggerReferenceFlows() {
double acReferenceFlow = 1400.;
double dcReferenceFlow = 1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleBiggerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithNegativeAbsoluteBiggerReferenceFlows() {
double acReferenceFlow = -1400.;
double dcReferenceFlow = 1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleBiggerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithPositiveSmallerReferenceFlows() {
double acReferenceFlow = 800.;
double dcReferenceFlow = 1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleSmallerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithNegativeAbsoluteSmallerReferenceFlows() {
double acReferenceFlow = -800.;
double dcReferenceFlow = 1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleSmallerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithNegativeBiggerReferenceFlows() {
double acReferenceFlow = -1400.;
double dcReferenceFlow = -1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleBiggerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithPositiveAbsoluteBiggerReferenceFlows() {
double acReferenceFlow = 1400.;
double dcReferenceFlow = -1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleBiggerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithNegativeSmallerReferenceFlows() {
double acReferenceFlow = -800.;
double dcReferenceFlow = -1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleSmallerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testAcerNormalizationWithPositiveAbsoluteSmallerReferenceFlows() {
double acReferenceFlow = 800.;
double dcReferenceFlow = -1100.;
DecomposedFlow rescaledFlow = getRescaledFlow(acReferenceFlow, dcReferenceFlow);
checkRescaleSmallerAcReference(acReferenceFlow, dcReferenceFlow, rescaledFlow);
}
@Test
void testReLUNormalizationWithFlowDecompositionResultsWithPstNetwork() {
String networkFileName = "NETWORK_PST_FLOW_WITH_COUNTRIES.uct";
testNormalizationWithFlowDecompositionResults(networkFileName, FlowDecompositionParameters.RescaleMode.ACER_METHODOLOGY);
}
@Test
void testNoNormalizationWithFlowDecompositionResultsWithPstNetwork() {
String networkFileName = "NETWORK_PST_FLOW_WITH_COUNTRIES.uct";
testNormalizationWithFlowDecompositionResults(networkFileName, FlowDecompositionParameters.RescaleMode.NONE);
}
@Test
void testProportionalNormalizationWithFlowDecompositionResultsWithPstNetwork() {
String networkFileName = "NETWORK_PST_FLOW_WITH_COUNTRIES.uct";
testNormalizationWithFlowDecompositionResults(networkFileName, FlowDecompositionParameters.RescaleMode.PROPORTIONAL);
}
static void testNormalizationWithFlowDecompositionResults(String networkFileName, FlowDecompositionParameters.RescaleMode rescaleMode) {
Network network = TestUtils.importNetwork(networkFileName);
FlowDecompositionParameters flowDecompositionParameters = new FlowDecompositionParameters()
.setEnableLossesCompensation(FlowDecompositionParameters.ENABLE_LOSSES_COMPENSATION)
.setLossesCompensationEpsilon(FlowDecompositionParameters.DISABLE_LOSSES_COMPENSATION_EPSILON)
.setSensitivityEpsilon(FlowDecompositionParameters.DISABLE_SENSITIVITY_EPSILON)
.setRescaleMode(rescaleMode);
FlowDecompositionComputer flowDecompositionComputer = new FlowDecompositionComputer(flowDecompositionParameters);
XnecProvider xnecProvider = new XnecProviderAllBranches();
FlowDecompositionResults flowDecompositionResults = flowDecompositionComputer.run(xnecProvider, network);
TestUtils.assertCoherenceTotalFlow(rescaleMode, flowDecompositionResults);
}
@Test
void testRescalingDoesNotOccurWhenAcDiverge() {
String networkFileName = "NETWORK_LOOP_FLOW_WITH_COUNTRIES.uct";
Network network = TestUtils.importNetwork(networkFileName);
String xnecId = "BLOAD 11 FLOAD 11 1";
FlowDecompositionParameters flowDecompositionParameters = new FlowDecompositionParameters()
.setEnableLossesCompensation(FlowDecompositionParameters.ENABLE_LOSSES_COMPENSATION)
.setLossesCompensationEpsilon(FlowDecompositionParameters.DISABLE_LOSSES_COMPENSATION_EPSILON)
.setSensitivityEpsilon(FlowDecompositionParameters.DISABLE_SENSITIVITY_EPSILON)
.setRescaleMode(FlowDecompositionParameters.RescaleMode.ACER_METHODOLOGY);
FlowDecompositionComputer flowDecompositionComputer = new FlowDecompositionComputer(flowDecompositionParameters);
XnecProvider xnecProvider = XnecProviderByIds.builder().addNetworkElementsOnBasecase(Set.of(xnecId)).build();
FlowDecompositionResults flowDecompositionResults = flowDecompositionComputer.run(xnecProvider, network);
assertTrue(Double.isNaN(flowDecompositionResults.getDecomposedFlowMap().get(xnecId).getAcTerminal1ReferenceFlow()));
assertFalse(Double.isNaN(flowDecompositionResults.getDecomposedFlowMap().get(xnecId).getAllocatedFlow()));
}
@Test
void testRescalingNoOpDoesNotRescale() {
double acReferenceFlow = 1.0;
double dcReferenceFlow = 0.9;
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerNoOp().rescale(decomposedFlow);
// check that same object is returned by rescaler
assertSame(decomposedFlow, decomposedFlowRescaled);
}
@Test
void testRescalingAcerMethodologyDoesNotRescaleNaN() {
double acReferenceFlow = Double.NaN;
double dcReferenceFlow = 0.9;
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerAcerMethodology().rescale(decomposedFlow);
// check that same object is returned by rescaler
assertSame(decomposedFlow, decomposedFlowRescaled);
}
@Test
void testRescalingProportionalDoesNotRescaleNaN() {
double acReferenceFlow = Double.NaN;
double dcReferenceFlow = 0.9;
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerProportional().rescale(decomposedFlow);
// check that same object is returned by rescaler
assertSame(decomposedFlow, decomposedFlowRescaled);
}
@Test
void testRescalingProportionalDoesNotRescaleWithSmallFlow() {
double acReferenceFlow = 1.0;
double dcReferenceFlow = 0.001;
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerProportional(0.5).rescale(decomposedFlow);
// check that same object is returned by rescaler
assertSame(decomposedFlow, decomposedFlowRescaled);
}
@Test
void testRescalingMaxCurrentOverloadDoesNotRescaleNaN() {
double acReferenceFlow = Double.NaN;
double dcReferenceFlow = 0.9;
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerMaxCurrentOverload().rescale(decomposedFlow);
// check that same object is returned by rescaler
assertSame(decomposedFlow, decomposedFlowRescaled);
}
@Test
void testRescalingMaxCurrentOverloadDoesNotRescaleWithSmallFlow() {
double acReferenceFlow = 1.0;
double dcReferenceFlow = 0.001;
DecomposedFlow decomposedFlow = getDecomposedFlow(acReferenceFlow, dcReferenceFlow);
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerMaxCurrentOverload(0.5).rescale(decomposedFlow);
// check that same object is returned by rescaler
assertSame(decomposedFlow, decomposedFlowRescaled);
}
private DecomposedFlow getDecomposedFlowForMaxCurrentOverload(String branchId) {
double acReferenceFlow1 = 100;
double acReferenceFlow2 = 90;
double dcReferenceFlow = 120;
double acCurrentTerminal1 = 50;
double acCurrentTerminal2 = 40;
double allocatedFlow = 100;
double pstFlow = 200.;
double internalFlow = -300.;
Map<Country, Double> loopFlowsPerCountry = Map.of(
Country.BE, 500.,
Country.GE, -100.,
Country.ES, 700.
);
Country country1 = Country.FR;
Country country2 = Country.FR;
return new DecomposedFlowBuilder()
.withBranchId(branchId)
.withContingencyId("")
.withCountry1(country1)
.withCountry2(country2)
.withAcTerminal1ReferenceFlow(acReferenceFlow1)
.withAcTerminal2ReferenceFlow(acReferenceFlow2)
.withDcReferenceFlow(dcReferenceFlow)
.withAcCurrentTerminal1(acCurrentTerminal1)
.withAcCurrentTerminal2(acCurrentTerminal2)
.withFlowPartition(new FlowPartition(internalFlow, allocatedFlow, loopFlowsPerCountry, pstFlow, 0))
.build();
}
@Test
void testRescalingMaxCurrentOverloadWithCurrentLimits() {
Network network = TestUtils.importNetwork("19700101_0000_FO4_UX1.uct");
DecomposedFlow decomposedFlow = getDecomposedFlowForMaxCurrentOverload("BB000011 BD000011 1");
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerMaxCurrentOverload().rescale(decomposedFlow, network);
final double expectedRescaledInternalFlow = -82.27241335952168;
assertTrue(Math.abs(decomposedFlowRescaled.getInternalFlow() - expectedRescaledInternalFlow) < 1E-6);
}
@Test
void testRescalingMaxCurrentOverloadWithoutCurrentLimits() {
Network network = TestUtils.importNetwork("19700101_0000_FO4_UX1.uct");
DecomposedFlow decomposedFlow = getDecomposedFlowForMaxCurrentOverload("BB000011 BB000021 1");
DecomposedFlow decomposedFlowRescaled = new DecomposedFlowRescalerMaxCurrentOverload().rescale(decomposedFlow, network);
final double expectedRescaledInternalFlow = -47.63139720814412;
assertTrue(Math.abs(decomposedFlowRescaled.getInternalFlow() - expectedRescaledInternalFlow) < 1E-6);
}
}