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

Fix zero flows in result due to instant handling in SystematicSensitivityResult #1189

Merged
merged 1 commit into from
Nov 5, 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 @@ -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)));

}

}
Loading