Skip to content

Commit

Permalink
modified method in systematicSensitivityResult for second preventive …
Browse files Browse the repository at this point in the history
…computations (#1189)

Signed-off-by: Philippe Edwards <philippe.edwards@rte-france.com>
  • Loading branch information
phiedw authored Nov 5, 2024
1 parent a12da95 commit b16ec59
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,13 @@ private StateResult getCnecStateResult(Cnec<?> cnec) {
private StateResult getCnecStateResult(Cnec<?> cnec, Instant instant) {
Optional<Contingency> optionalContingency = cnec.getState().getContingency();
if (optionalContingency.isPresent()) {
String contingencyId = optionalContingency.get().getId();
int maxAdmissibleInstantOrder = instant == null ? 1 : Math.max(1, instant.getOrder()); // when dealing with post-contingency CNECs, a null instant refers to the outage instant
List<Integer> possibleInstants = postContingencyResults.keySet().stream()
.filter(instantOrder -> instantOrder <= cnec.getState().getInstant().getOrder() && instantOrder <= maxAdmissibleInstantOrder)
.sorted(Comparator.reverseOrder())
.filter(instantOrder -> postContingencyResults.get(instantOrder).containsKey(contingencyId))
.toList();
String contingencyId = optionalContingency.get().getId();
return possibleInstants.isEmpty() ? null : postContingencyResults.get(possibleInstants.get(0)).get(contingencyId);
} else {
return nStateResult; // when dealing with preventive CNECs, a null instant refers to the initial instant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.powsybl.iidm.network.TwoSides;
import com.powsybl.openrao.data.cracapi.CracFactory;
import com.powsybl.openrao.data.cracapi.State;
import com.powsybl.openrao.data.cracapi.cnec.FlowCnecAdder;
import com.powsybl.openrao.data.cracapi.rangeaction.HvdcRangeAction;
import com.powsybl.glsk.commons.ZonalData;
import com.powsybl.openrao.data.cracapi.Crac;
Expand Down Expand Up @@ -293,4 +294,82 @@ void testPartialContingencyFailures() {
assertEquals(SystematicSensitivityResult.SensitivityComputationStatus.FAILURE, result.getStatus(contingencyState));
}

//This test simulates what happens after a second preventive, where some curative results are stored in outage results.
//We do this to avoid recomputing multiple times the same contingency while no remedial action was applied in later instants.
@Test
void testCurativeResultAtOutageInstant() {
setUpWith12Nodes();

FlowCnecAdder cnecAdder = crac.newFlowCnec()
.withId("cnec2stateOutageContingency2")
.withNetworkElement("FFR2AA1 DDE3AA1 1")
.withInstant(OUTAGE_INSTANT_ID)
.withContingency("Contingency FR1 FR2")
.withOptimized(true)
.withOperator("operator2")
.withReliabilityMargin(95.)
.withNominalVoltage(380.)
.withIMax(5000.);
Set.of(TwoSides.ONE, TwoSides.TWO).forEach(side ->
cnecAdder.newThreshold()
.withUnit(Unit.MEGAWATT)
.withSide(TwoSides.ONE)
.withMin(-1800.)
.withMax(1800.)
.add());
cnecAdder.add();

outageInstantOrder = crac.getInstant(OUTAGE_INSTANT_ID).getOrder();
int curativeInstantOrder = crac.getInstant(CURATIVE_INSTANT_ID).getOrder();

//run sensi on outage instant for outageCnec
FlowCnec outageCnec = crac.getFlowCnec("cnec2stateOutageContingency2");
Contingency outageContingency = outageCnec.getState().getContingency().orElseThrow();
SensitivityFactor outageSensitivityFactor = new SensitivityFactor(
SensitivityFunctionType.BRANCH_ACTIVE_POWER_1,
outageCnec.getNetworkElement().getId(),
SensitivityVariableType.TRANSFORMER_PHASE,
"BBE2AA1 BBE3AA1 1",
false,
new ContingencyContext(outageContingency.getId(), ContingencyContextType.SPECIFIC)
);
SensitivityAnalysisResult sensitivityAnalysisResult = SensitivityAnalysis.find().run(network,
List.of(outageSensitivityFactor),
List.of(outageContingency),
new ArrayList<>(),
SensitivityAnalysisParameters.load());
SystematicSensitivityResult result = new SystematicSensitivityResult().completeData(sensitivityAnalysisResult, outageInstantOrder);

//run sensi on curative instant for curativeCnec
FlowCnec curativeCnec = crac.getFlowCnec("cnec1stateCurativeContingency1");
Contingency curativeContingency = curativeCnec.getState().getContingency().orElseThrow();
SensitivityFactor curativeSensitivityFactor = new SensitivityFactor(
SensitivityFunctionType.BRANCH_ACTIVE_POWER_1,
curativeCnec.getNetworkElement().getId(),
SensitivityVariableType.TRANSFORMER_PHASE,
"BBE2AA1 BBE3AA1 1",
false,
new ContingencyContext(curativeContingency.getId(), ContingencyContextType.SPECIFIC)
);
sensitivityAnalysisResult = SensitivityAnalysis.find().run(network,
List.of(curativeSensitivityFactor),
List.of(curativeContingency),
new ArrayList<>(),
SensitivityAnalysisParameters.load());
result.completeData(sensitivityAnalysisResult, curativeInstantOrder);

//correct flows are available for both factors for all instants
//0 represents a missing value (this is due to the way load flow engines represent an open line, we need 0 as a default value)
assertEquals(-20, result.getReferenceFlow(outageCnec, TwoSides.ONE));
assertEquals(-20, result.getReferenceFlow(outageCnec, TwoSides.ONE, crac.getInstant(OUTAGE_INSTANT_ID)));
assertEquals(-20, result.getReferenceFlow(outageCnec, TwoSides.ONE, crac.getInstant(AUTO_INSTANT_ID)));
assertEquals(-20, result.getReferenceFlow(outageCnec, TwoSides.ONE, crac.getInstant(CURATIVE_INSTANT_ID)));

assertEquals(-20, result.getReferenceFlow(curativeCnec, TwoSides.ONE));
assertEquals(0, result.getReferenceFlow(curativeCnec, TwoSides.ONE, crac.getInstant(OUTAGE_INSTANT_ID)));
assertEquals(0, result.getReferenceFlow(curativeCnec, TwoSides.ONE, crac.getInstant(AUTO_INSTANT_ID)));
assertEquals(-20, result.getReferenceFlow(curativeCnec, TwoSides.ONE, crac.getInstant(CURATIVE_INSTANT_ID)));

}

}

0 comments on commit b16ec59

Please sign in to comment.