SearchTreeRaoSteps.java
/*
* Copyright (c) 2024, 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.openrao.tests.steps;
import com.powsybl.glsk.commons.ZonalData;
import com.powsybl.iidm.network.Network;
import com.powsybl.openrao.commons.OpenRaoException;
import com.powsybl.openrao.commons.PhysicalParameter;
import com.powsybl.openrao.commons.Unit;
import com.powsybl.openrao.data.crac.api.Crac;
import com.powsybl.openrao.data.crac.api.Instant;
import com.powsybl.openrao.data.crac.api.InstantKind;
import com.powsybl.openrao.data.crac.api.State;
import com.powsybl.openrao.data.crac.api.cnec.Cnec;
import com.powsybl.openrao.data.crac.api.cnec.FlowCnec;
import com.powsybl.iidm.network.TwoSides;
import com.powsybl.openrao.data.crac.api.networkaction.NetworkAction;
import com.powsybl.openrao.data.crac.api.rangeaction.PstRangeAction;
import com.powsybl.openrao.data.crac.api.rangeaction.RangeAction;
import com.powsybl.openrao.data.crac.loopflowextension.LoopFlowThreshold;
import com.powsybl.openrao.data.raoresult.api.ComputationStatus;
import com.powsybl.openrao.data.raoresult.api.RaoResult;
import com.powsybl.openrao.data.refprog.referenceprogram.ReferenceProgram;
import com.powsybl.openrao.data.refprog.referenceprogram.ReferenceProgramBuilder;
import com.powsybl.openrao.loopflowcomputation.LoopFlowComputation;
import com.powsybl.openrao.loopflowcomputation.LoopFlowComputationImpl;
import com.powsybl.openrao.loopflowcomputation.LoopFlowResult;
import com.powsybl.openrao.raoapi.parameters.RaoParameters;
import com.powsybl.sensitivity.SensitivityAnalysisParameters;
import com.powsybl.sensitivity.SensitivityVariableSet;
import com.powsybl.openrao.tests.utils.RaoUtils;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static com.powsybl.openrao.raoapi.parameters.extensions.LoadFlowAndSensitivityParameters.getSensitivityWithLoadFlowParameters;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Viktor Terrier {@literal <viktor.terrier at rte-france.com>}
*/
public class SearchTreeRaoSteps {
private static final String SEARCH_TREE_RAO = "SearchTreeRao";
private static final double TOLERANCE_FLOW_IN_AMPERE = 5.0;
private static final double TOLERANCE_FLOW_IN_MEGAWATT = 5.0;
private static final double TOLERANCE_FLOW_RELATIVE = 1.5 / 100;
private static final double TOLERANCE_PTDF = 1e-3;
private static final double TOLERANCE_RANGEACTION_SETPOINT = 5.0;
private Crac crac;
private RaoResult raoResult;
private LoopFlowResult loopFlowResult;
private Network network;
private State preventiveState;
private static double flowAmpereTolerance(double expectedValue) {
return Math.max(TOLERANCE_FLOW_IN_AMPERE, TOLERANCE_FLOW_RELATIVE * Math.abs(expectedValue));
}
private static double flowMegawattTolerance(Double expectedValue) {
return Math.max(TOLERANCE_FLOW_IN_MEGAWATT, TOLERANCE_FLOW_RELATIVE * Math.abs(expectedValue));
}
@When("I launch search_tree_rao")
public void iLaunchSearchTreeRao() {
iLaunchSearchTreeRao(null);
}
@When("I launch search_tree_rao with a time limit of {int} seconds")
public void iLaunchSearchTreeRaoWithTimeLimit(int timeLimit) {
launchRao(timeLimit);
}
@When("I launch search_tree_rao at {string}")
public void iLaunchSearchTreeRao(String timestamp) {
launchRao(null, null, timestamp, SEARCH_TREE_RAO);
}
@When("I launch search_tree_rao at {string} on {string}")
public void iLaunchSearchTreeRaoAtTimestampOnContingency(String timestamp, String contingencyId) {
launchRao(contingencyId, null, timestamp, SEARCH_TREE_RAO);
}
@When("I launch search_tree_rao at {string} on preventive state")
public void iLaunchSearchTreeRaoOnPreventiveState(String timestamp) {
launchRao(null, InstantKind.PREVENTIVE, timestamp, SEARCH_TREE_RAO);
}
@When("I launch search_tree_rao at {string} after {string} at {string}")
public void iLaunchSearchTreeRao(String timestamp, String contingencyId, String instantKind) {
launchRao(contingencyId, InstantKind.valueOf(instantKind.toUpperCase()), timestamp, SEARCH_TREE_RAO);
}
@When("I launch search_tree_rao on preventive state")
public void iLaunchSearchTreeRaoOnPreventiveState() {
launchRao(null, InstantKind.PREVENTIVE, null, SEARCH_TREE_RAO);
}
@When("I launch search_tree_rao after {string} at {string}")
public void iLaunchSearchTreeRao(String contingencyId, String instantKind) {
launchRao(contingencyId, InstantKind.valueOf(instantKind.toUpperCase()), null, null, SEARCH_TREE_RAO, null);
}
@When("I launch loopflow search_tree_rao with default loopflow limit as {double} percent of pmax")
public void iLaunchSearchTreeRaoWithDefaultLoopflowLimit(double percentage) {
launchRao(null, null, null, percentage, SEARCH_TREE_RAO, null);
}
@When("I launch loopflow search_tree_rao at {string} with default loopflow limit as {double} percent of pmax")
public void iLaunchSearchTreeRaoWithDefaultLoopflowLimit(String timestamp, double percentage) {
launchRao(null, null, timestamp, percentage, SEARCH_TREE_RAO, null);
}
@When("I launch loopflow_computation with OpenLoadFlow")
public void iLaunchLoopflowComputation() {
iLaunchLoopflowComputation(null);
}
@When("I launch loopflow_computation with OpenLoadFlow at {string}")
public void iLaunchLoopflowComputation(String timestamp) {
launchLoopflowComputation(timestamp, "OpenLoadFlow", "OpenLoadFlow");
}
@Then("the calculation succeeds")
public void theCalculationSucceeds() {
assertEquals(ComputationStatus.DEFAULT, raoResult.getComputationStatus());
}
@Then("the calculation partially fails")
public void theCalculationPartiallyFails() {
assertEquals(ComputationStatus.PARTIAL_FAILURE, raoResult.getComputationStatus());
}
@Then("the calculation fails")
public void theCalculationFails() {
assertEquals(ComputationStatus.FAILURE, raoResult.getComputationStatus());
}
@Then("its security status should be {string}")
public void statusShouldBe(String status) {
assertEquals(status.equalsIgnoreCase("secured"), raoResult.isSecure(PhysicalParameter.FLOW));
}
@Then("the value of the objective function initially should be {double}")
public void objectiveFunctionValueInitialShouldBe(double expectedValue) {
assertEquals(expectedValue, raoResult.getCost(null), flowAmpereTolerance(expectedValue));
}
@Then("the value of the objective function after PRA should be {double}")
public void objectiveFunctionValueAfterPraShouldBe(double expectedValue) {
assertEquals(expectedValue, raoResult.getCost(crac.getPreventiveInstant()), flowAmpereTolerance(expectedValue));
}
@Then("the value of the objective function after ARA should be {double}")
public void objectiveFunctionValueAfterAraShouldBe(double expectedValue) {
Instant instant = crac.hasAutoInstant() ? crac.getInstant(InstantKind.AUTO) : crac.getOutageInstant();
assertEquals(expectedValue, raoResult.getCost(instant), flowAmpereTolerance(expectedValue));
}
@Then("the value of the objective function after CRA should be {double}")
public void objectiveFunctionValueAfterCraShouldBe(double expectedValue) {
assertEquals(expectedValue, raoResult.getCost(crac.getLastInstant()), flowAmpereTolerance(expectedValue));
}
@Then("the value of the objective function before optimisation should be {double}")
public void objectiveFunctionValueBeforeOptShouldBe(double expectedValue) {
assertEquals(expectedValue, raoResult.getCost(null), flowAmpereTolerance(expectedValue));
}
@Then("{int} remedial actions are used in preventive")
public void countPra(int expectedCount) {
assertEquals(expectedCount, raoResult.getActivatedNetworkActionsDuringState(preventiveState).size() + raoResult.getActivatedRangeActionsDuringState(preventiveState).size());
}
@Then("{int} network actions are used in preventive")
public void countNetworkActionPra(int expectedCount) {
assertEquals(expectedCount, raoResult.getActivatedNetworkActionsDuringState(preventiveState).size());
}
@Then("{int} �� {int} remedial actions are used in preventive")
public void countPra(int expectedCount, int tolerance) {
assertEquals(expectedCount, raoResult.getActivatedNetworkActionsDuringState(preventiveState).size() + raoResult.getActivatedRangeActionsDuringState(preventiveState).size(), tolerance);
}
@Then("{int} remedial actions are used after {string} at {string}")
public void countCra(int expectedCount, String contingencyId, String instant) {
State state = getState(contingencyId, instant);
assertEquals(expectedCount, raoResult.getActivatedRangeActionsDuringState(state).size() + raoResult.getActivatedNetworkActionsDuringState(state).size());
}
@Then("the remedial action {string} is used in preventive")
public void remedialActionUsedInPreventive(String remedialAction) {
assertTrue(raoResult.isActivatedDuringState(preventiveState, crac.getRemedialAction(remedialAction)));
}
@Then("the remedial action {string} is used after {string} at {string}")
public void remedialActionUsed(String remedialAction, String contingencyId, String instant) {
assertTrue(raoResult.isActivatedDuringState(getState(contingencyId, instant), crac.getRemedialAction(remedialAction)));
}
@Then("the remedial action {string} is not used after {string} at {string}")
public void remedialActionNotUsed(String remedialAction, String contingencyId, String instant) {
assertFalse(raoResult.isActivatedDuringState(getState(contingencyId, instant), crac.getRemedialAction(remedialAction)));
}
@Then("line {string} in network file with PRA has connection status to {string}")
public void lineConnectionStatusInNetworkWithPra(String line, String isConnectedStr) {
boolean isConnected = Boolean.parseBoolean(isConnectedStr);
assertEquals(network.getBranch(line).getTerminal1().isConnected(), isConnected);
assertEquals(network.getBranch(line).getTerminal2().isConnected(), isConnected);
}
@Then("PST {string} in network file with PRA is on tap {int}")
public void pstTapInNetworkWithPra(String pst, int tap) {
assertEquals(tap, network.getTwoWindingsTransformer(pst).getPhaseTapChanger().getTapPosition());
}
@Then("the remedial action {string} is not used in preventive")
public void remedialActionNotUsedInPreventive(String remedialAction) {
RangeAction<?> rangeAction = crac.getRangeAction(remedialAction);
if (!Objects.isNull(rangeAction)) {
assertFalse(raoResult.isActivatedDuringState(preventiveState, rangeAction));
} else {
NetworkAction networkAction = crac.getNetworkAction(remedialAction);
assertFalse(raoResult.isActivatedDuringState(preventiveState, networkAction));
}
}
@Then("the tap of PstRangeAction {string} should be {int} in preventive")
public void theTapOfPstRangeActionShouldBe(String pstRangeActionId, int chosenPstTap) {
assertEquals(chosenPstTap, raoResult.getOptimizedTapOnState(preventiveState, (PstRangeAction) crac.getRangeAction(pstRangeActionId)));
}
@Then("the tap of PstRangeAction {string} should be {int} �� {int} in preventive")
public void theTapOfPstRangeActionShouldBe(String pstRangeActionId, int chosenPstTap, int tolerance) {
assertEquals(chosenPstTap, raoResult.getOptimizedTapOnState(preventiveState, (PstRangeAction) crac.getRangeAction(pstRangeActionId)), tolerance);
}
@Then("the tap of PstRangeAction {string} should be {int} after {string} at {string}")
public void theTapOfPstRangeActionShouldBe(String pstRangeActionId, int chosenPstTap, String contingencyId, String instant) {
PstRangeAction rangeAction = (PstRangeAction) crac.getRangeAction(pstRangeActionId);
assertEquals(chosenPstTap, raoResult.getOptimizedTapOnState(getState(contingencyId, instant), rangeAction));
}
@Then("the setpoint of RangeAction {string} should be {double} MW in preventive")
public void theSetpointOfRangeActionShouldBe(String rangeActionId, double chosenSetpoint) {
assertEquals(chosenSetpoint, raoResult.getOptimizedSetPointOnState(preventiveState, crac.getRangeAction(rangeActionId)), TOLERANCE_RANGEACTION_SETPOINT);
}
@Then("the initial setpoint of RangeAction {string} should be {double}")
public void theInitialSetpointOfRangeActionShouldBe(String rangeActionId, double chosenSetpoint) {
assertEquals(chosenSetpoint, raoResult.getPreOptimizationSetPointOnState(preventiveState, crac.getRangeAction(rangeActionId)), TOLERANCE_RANGEACTION_SETPOINT);
}
@Then("the initial tap of PstRangeAction {string} should be {int}")
public void theInitialTapOfPstRangeActionShouldBe(String pstRangeActionId, int chosenTap) {
assertEquals(chosenTap, raoResult.getPreOptimizationTapOnState(preventiveState, crac.getPstRangeAction(pstRangeActionId)));
}
@Then("the setpoint of RangeAction {string} should be {double} MW after {string} at {string}")
public void theSetpointOfRangeActionShouldBe(String rangeActionId, double chosenSetpoint, String contingencyId, String instant) {
RangeAction<?> rangeAction = crac.getRangeAction(rangeActionId);
assertEquals(chosenSetpoint, raoResult.getOptimizedSetPointOnState(getState(contingencyId, instant), rangeAction), TOLERANCE_RANGEACTION_SETPOINT);
}
@Then("the setpoint of RangeAction {string} should be {double} before {string} at {string}")
public void theSetpointOfRangeActionShouldBeBefore(String rangeActionId, double chosenSetpoint, String contingencyId, String instant) {
RangeAction<?> rangeAction = crac.getRangeAction(rangeActionId);
assertEquals(chosenSetpoint, raoResult.getPreOptimizationSetPointOnState(getState(contingencyId, instant), rangeAction), TOLERANCE_RANGEACTION_SETPOINT);
}
@Then("the tap of PstRangeAction {string} should be {int} before {string} at {string}")
public void theSetpointOfRangeActionShouldBeBefore(String pstRangeActionId, int chosenTap, String contingencyId, String instant) {
PstRangeAction pstRangeAction = crac.getPstRangeAction(pstRangeActionId);
assertEquals(chosenTap, raoResult.getPreOptimizationTapOnState(getState(contingencyId, instant), pstRangeAction));
}
private State getState(String contingencyId, String instantId) {
if (instantId.equalsIgnoreCase("preventive")) {
return crac.getPreventiveState();
} else {
return crac.getState(contingencyId, crac.getInstant(instantId));
}
}
/*
Margins in A
*/
@Then("the initial margin on cnec {string} should be {double} A")
public void initialMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(null, crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the margin on cnec {string} after PRA should be {double} A")
public void afterPraMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the margin on cnec {string} after ARA should be {double} A")
public void afterAraMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(crac.getInstant(InstantKind.AUTO), crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the margin on cnec {string} after CRA should be {double} A")
public void afterCraMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(crac.getInstant(InstantKind.CURATIVE), crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the worst margin is {double} A")
public void worstMarginInA(double expectedMargin) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.AMPERE, false);
assertEquals(expectedMargin, worstCnec.getValue(), flowAmpereTolerance(expectedMargin));
}
@Then("the worst margin is {double} A with a tolerance of {double} A")
public void worstMarginInA(double expectedMargin, double delta) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.AMPERE, false);
assertEquals(expectedMargin, worstCnec.getValue(), delta);
}
@Then("the worst margin is {double} A on cnec {string}")
public void worstMarginAndCnecInA(double expectedMargin, String expectedCnecName) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.AMPERE, false);
assertNotNull(worstCnec.getKey());
assertEquals(expectedMargin, worstCnec.getValue(), flowAmpereTolerance(expectedMargin));
assertEquals(expectedCnecName, worstCnec.getKey().getId());
}
/*
Margins in MW
*/
@Then("the initial margin on cnec {string} should be {double} MW")
public void initialMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(null, crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the margin on cnec {string} after PRA should be {double} MW")
public void afterPraMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the margin on cnec {string} after ARA should be {double} MW")
public void afterAraMarginInMW(String cnecId, Double expectedMargin) {
Instant instant = crac.hasAutoInstant() ? crac.getInstant(InstantKind.AUTO) : crac.getOutageInstant();
assertEquals(expectedMargin, raoResult.getMargin(instant, crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the margin on cnec {string} after CRA should be {double} MW")
public void afterCraMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getMargin(crac.getInstant(InstantKind.CURATIVE), crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the worst margin is {double} MW")
public void worstMarginInMW(double expectedMargin) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.MEGAWATT, false);
assertEquals(expectedMargin, worstCnec.getValue(), flowMegawattTolerance(expectedMargin));
}
@Then("the worst margin is {double} MW on cnec {string}")
public void worstMarginAndCnecInMW(double expectedMargin, String expectedCnecName) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.MEGAWATT, false);
assertNotNull(worstCnec.getKey());
assertEquals(expectedMargin, worstCnec.getValue(), flowMegawattTolerance(expectedMargin));
assertEquals(expectedCnecName, worstCnec.getKey().getId());
}
/*
Relative margins in A
*/
@Then("the initial relative margin on cnec {string} should be {double} A")
public void initialRelativeMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(null, crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the relative margin on cnec {string} after PRA should be {double} A")
public void afterPraRelativeMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the relative margin on cnec {string} after ARA should be {double} A")
public void afterAraRelativeMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(crac.getInstant(InstantKind.AUTO), crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the relative margin on cnec {string} after CRA should be {double} A")
public void afterCraRelativeMarginInA(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(crac.getInstant(InstantKind.CURATIVE), crac.getFlowCnec(cnecId), Unit.AMPERE), flowAmpereTolerance(expectedMargin));
}
@Then("the worst relative margin is {double} A")
public void worstRelativeMarginInA(double expectedMargin) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.AMPERE, true);
assertEquals(expectedMargin, worstCnec.getValue(), flowAmpereTolerance(expectedMargin));
}
@Then("the worst relative margin is {double} A on cnec {string}")
public void worstRelativeMarginAndCnecInA(double expectedMargin, String expectedCnecName) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.AMPERE, true);
assertNotNull(worstCnec.getKey());
assertEquals(expectedMargin, worstCnec.getValue(), flowAmpereTolerance(expectedMargin));
assertEquals(expectedCnecName, worstCnec.getKey().getId());
}
/*
Relative margins in MW
*/
@Then("the initial relative margin on cnec {string} should be {double} MW")
public void initialRelativeMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(null, crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the relative margin on cnec {string} after PRA should be {double} MW")
public void afterPraRelativeMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the relative margin on cnec {string} after ARA should be {double} MW")
public void afterAraRelativeMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(crac.getInstant(InstantKind.AUTO), crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the relative margin on cnec {string} after CRA should be {double} MW")
public void afterCraRelativeMarginInMW(String cnecId, Double expectedMargin) {
assertEquals(expectedMargin, raoResult.getRelativeMargin(crac.getInstant(InstantKind.CURATIVE), crac.getFlowCnec(cnecId), Unit.MEGAWATT), flowMegawattTolerance(expectedMargin));
}
@Then("the worst relative margin is {double} MW")
public void worstRelativeMarginInMW(double expectedMargin) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.MEGAWATT, true);
assertEquals(expectedMargin, worstCnec.getValue(), flowMegawattTolerance(expectedMargin));
}
@Then("the worst relative margin is {double} MW on cnec {string}")
public void worstRelativeMarginAndCnecInMW(double expectedMargin, String expectedCnecName) {
Pair<FlowCnec, Double> worstCnec = getWorstCnec(Unit.MEGAWATT, true);
assertNotNull(worstCnec.getKey());
assertEquals(expectedMargin, worstCnec.getValue(), flowMegawattTolerance(expectedMargin));
assertEquals(expectedCnecName, worstCnec.getKey().getId());
}
/*
Flows in A
*/
// TODO : add steps to check flows on both sides
@Then("the initial flow on cnec {string} should be {double} A")
public void initialFlowInA(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(null, crac.getFlowCnec(cnecId), side, Unit.AMPERE), flowAmpereTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after PRA should be {double} A")
public void afterPraFlowInA(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), side, Unit.AMPERE), flowAmpereTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after ARA should be {double} A")
public void afterAraFlowInA(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(crac.getInstant(InstantKind.AUTO), crac.getFlowCnec(cnecId), side, Unit.AMPERE), flowAmpereTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after CRA should be {double} A")
public void afterCraFlowInA(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(crac.getInstant(InstantKind.CURATIVE), crac.getFlowCnec(cnecId), side, Unit.AMPERE), flowAmpereTolerance(expectedFlow));
}
/*
Flows in MW
*/
@Then("the initial flow on cnec {string} should be {double} MW")
public void initialFlowInMW(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(null, crac.getFlowCnec(cnecId), side, Unit.MEGAWATT), flowMegawattTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after PRA should be {double} MW")
public void afterPraFlowInMW(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), side, Unit.MEGAWATT), flowMegawattTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after ARA should be {double} MW")
public void afterAraFlowInMW(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
assertEquals(expectedFlow, raoResult.getFlow(crac.getInstant(InstantKind.AUTO), crac.getFlowCnec(cnecId), side, Unit.MEGAWATT), flowMegawattTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after CRA should be {double} MW")
public void afterCraFlowInMW(String cnecId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
Instant lastCurativeInstant = crac.getInstants(InstantKind.CURATIVE).stream().sorted(Comparator.comparingInt(instant -> -instant.getOrder())).toList().get(0);
assertEquals(expectedFlow, raoResult.getFlow(lastCurativeInstant, crac.getFlowCnec(cnecId), side, Unit.MEGAWATT), flowMegawattTolerance(expectedFlow));
}
@Then("the flow on cnec {string} after {string} instant remedial actions should be {double} MW")
public void afterInstantFlowInMW(String cnecId, String instantId, Double expectedFlow) {
TwoSides side = crac.getFlowCnec(cnecId).getMonitoredSides().iterator().next();
Instant instant = crac.getInstant(instantId);
assertEquals(expectedFlow, raoResult.getFlow(instant, crac.getFlowCnec(cnecId), side, Unit.MEGAWATT), flowMegawattTolerance(expectedFlow));
}
/*
Thresholds
*/
private void testThreshold(String upperOrLower, String cnecId, Double expectedBound, Unit unit) {
FlowCnec cnec = crac.getFlowCnec(cnecId);
if (cnec.getMonitoredSides().size() != 1) {
throw new OpenRaoException("Cannot chose side");
}
TwoSides side = cnec.getMonitoredSides().iterator().next();
Double bound = null;
if (upperOrLower.equalsIgnoreCase("upper")) {
bound = crac.getFlowCnec(cnecId).getUpperBound(side, unit).orElseThrow();
} else if (upperOrLower.equalsIgnoreCase("lower")) {
bound = crac.getFlowCnec(cnecId).getLowerBound(side, unit).orElseThrow();
}
assertEquals(expectedBound, bound, flowAmpereTolerance(expectedBound));
}
@Then("the {string} threshold on cnec {string} should be {double} A")
public void thresholdOnCnecInA(String upperOrLower, String cnecId, Double expectedBound) {
testThreshold(upperOrLower, cnecId, expectedBound, Unit.AMPERE);
}
@Then("the {string} threshold on cnec {string} should be {double} MW")
public void thresholdOnCnecInMW(String upperOrLower, String cnecId, Double expectedBound) {
testThreshold(upperOrLower, cnecId, expectedBound, Unit.MEGAWATT);
}
/*
Loopflows
*/
@Then("the initial loopflow on cnec {string} should be {double} MW")
public void initialLoopflowInMW(String cnecId, Double expectedFlow) {
assertEquals(expectedFlow,
crac.getFlowCnec(cnecId).getMonitoredSides().stream()
.map(side -> raoResult.getLoopFlow(null, crac.getFlowCnec(cnecId), side, Unit.MEGAWATT))
.max(Double::compareTo).orElseThrow(),
flowMegawattTolerance(expectedFlow));
}
@Then("the loopflow on cnec {string} after PRA should be {double} MW")
public void afterPraLoopflowInMW(String cnecId, Double expectedFlow) {
assertEquals(expectedFlow,
crac.getFlowCnec(cnecId).getMonitoredSides().stream()
.map(side -> raoResult.getLoopFlow(crac.getPreventiveInstant(), crac.getFlowCnec(cnecId), side, Unit.MEGAWATT))
.max(Double::compareTo).orElseThrow(),
flowMegawattTolerance(expectedFlow));
}
@Then("the loopflow on cnec {string} after ARA should be {double} MW")
public void afterAraLoopflowInMW(String cnecId, Double expectedFlow) {
assertEquals(expectedFlow,
crac.getFlowCnec(cnecId).getMonitoredSides().stream()
.map(side -> raoResult.getLoopFlow(crac.getInstant(InstantKind.AUTO), crac.getFlowCnec(cnecId), side, Unit.MEGAWATT))
.max(Double::compareTo).orElseThrow(),
flowMegawattTolerance(expectedFlow));
}
@Then("the loopflow on cnec {string} after CRA should be {double} MW")
public void afterCraLoopflowInMW(String cnecId, Double expectedFlow) {
assertEquals(expectedFlow,
crac.getFlowCnec(cnecId).getMonitoredSides().stream()
.map(side -> raoResult.getLoopFlow(crac.getInstant(InstantKind.CURATIVE), crac.getFlowCnec(cnecId), side, Unit.MEGAWATT))
.max(Double::compareTo).orElseThrow(),
flowMegawattTolerance(expectedFlow));
}
@Then("the loopflow on cnec {string} after loopflow computation should be {double} MW")
public void loopflowComputationLoopflowInMW(String cnecId, Double expectedFlow) {
assertEquals(expectedFlow,
crac.getFlowCnec(cnecId).getMonitoredSides().stream()
.map(side -> loopFlowResult.getLoopFlow(crac.getFlowCnec(cnecId), side))
.max(Double::compareTo).orElseThrow(),
flowMegawattTolerance(expectedFlow));
}
@Then("the loopflow threshold on cnec {string} should be {double} MW")
public void loopflowThresholdInMW(String cnecId, Double expectedFlow) {
FlowCnec cnec = crac.getFlowCnec(cnecId);
assertEquals(expectedFlow, cnec.getExtension(LoopFlowThreshold.class).getThresholdWithReliabilityMargin(Unit.MEGAWATT), flowMegawattTolerance(expectedFlow));
}
/*
PTDF sums
*/
@Then("the absolute PTDF sum on cnec {string} initially should be {double}")
public void absPtdfSum(String cnecId, Double expectedPtdfSum) {
FlowCnec cnec = crac.getFlowCnec(cnecId);
assertEquals(expectedPtdfSum, raoResult.getPtdfZonalSum(null, cnec, cnec.getMonitoredSides().iterator().next()), TOLERANCE_PTDF);
}
@Then("the absolute PTDF sum on cnec {string} after {string} should be {double}")
public void absPtdfSumAfterInstant(String cnecId, String instantKind, Double expectedPtdfSum) {
FlowCnec cnec = crac.getFlowCnec(cnecId);
assertEquals(expectedPtdfSum, raoResult.getPtdfZonalSum(crac.getInstant(InstantKind.valueOf(instantKind.toUpperCase())), cnec, cnec.getMonitoredSides().iterator().next()), TOLERANCE_PTDF);
}
private void launchRao(int timeLimit) {
launchRao(null, null, null, null, SEARCH_TREE_RAO, timeLimit);
}
private void launchRao(String contingencyId, InstantKind instantKind, String timestamp, String raoType) {
launchRao(contingencyId, instantKind, timestamp, 0.0, raoType, null);
}
private void launchRao(String contingencyId, InstantKind instantKind, String timestamp, Double loopflowLimitAsPmaxPercentageInput, String raoType, Integer timeLimit) {
try {
CommonTestData.loadData(timestamp);
network = CommonTestData.getNetwork();
crac = CommonTestData.getCrac();
preventiveState = crac.getPreventiveState();
raoResult = RaoUtils.runRao(contingencyId, instantKind, raoType, loopflowLimitAsPmaxPercentageInput, timeLimit);
CommonTestData.setRaoResult(raoResult);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private void launchLoopflowComputation(String timestamp, String sensitivityProvider, String loadFlowProvider) {
try {
CommonTestData.loadData(timestamp);
network = CommonTestData.getNetwork();
crac = CommonTestData.getCrac();
RaoParameters raoParameters = CommonTestData.getRaoParameters();
SensitivityAnalysisParameters sensitivityAnalysisParameters = getSensitivityWithLoadFlowParameters(raoParameters);
ReferenceProgram referenceProgram = CommonTestData.getReferenceProgram() != null ? CommonTestData.getReferenceProgram() : ReferenceProgramBuilder.buildReferenceProgram(network, loadFlowProvider, sensitivityAnalysisParameters.getLoadFlowParameters());
ZonalData<SensitivityVariableSet> glsks = CommonTestData.getLoopflowGlsks();
// run loopFlowComputation
LoopFlowComputation loopFlowComputation = new LoopFlowComputationImpl(glsks, referenceProgram);
this.loopFlowResult = loopFlowComputation.calculateLoopFlows(network, sensitivityProvider, sensitivityAnalysisParameters, crac.getFlowCnecs(), crac.getOutageInstant());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private Pair<FlowCnec, Double> getWorstCnec(Unit unit, boolean relative) {
Set<FlowCnec> flowCnecs = crac.getFlowCnecs().stream().filter(Cnec::isOptimized).collect(Collectors.toSet());
double worstMargin = Double.MAX_VALUE;
FlowCnec worstCnec = null;
double margin;
//Filter flow cnecs from failed perimeters
Set<State> failedStates = crac.getStates().stream()
.filter(state -> raoResult.getComputationStatus(state).equals(ComputationStatus.FAILURE))
.collect(Collectors.toSet());
for (FlowCnec flowCnec : flowCnecs) {
if (failedStates.contains(flowCnec.getState())) {
continue;
}
try {
if (relative) {
margin = raoResult.getRelativeMargin(flowCnec.getState().getInstant(), flowCnec, unit);
} else {
margin = raoResult.getMargin(flowCnec.getState().getInstant(), flowCnec, unit);
}
if (Double.isNaN(margin)) {
// Try getting margin before flowCnec's state afterOptimizing state
// This could happen for instance if optimization on said state failed
if (relative) {
margin = raoResult.getRelativeMargin(crac.getInstantBefore(flowCnec.getState().getInstant()), flowCnec, unit);
} else {
margin = raoResult.getMargin(crac.getInstantBefore(flowCnec.getState().getInstant()), flowCnec, unit);
}
}
} catch (OpenRaoException e) {
margin = Double.MAX_VALUE;
}
if (margin < worstMargin) {
worstMargin = margin;
worstCnec = flowCnec;
}
}
return new ImmutablePair<>(worstCnec, worstMargin);
}
/*
RaoResult infos
*/
@Then("the execution details should be {string}")
public void getOptimizationSteps(String string) {
assertEquals(string, raoResult.getExecutionDetails());
}
}