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

Draft : SA : output a result for contingencies with no impact #981

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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 @@ -441,15 +441,25 @@ private static boolean isConnectedAfterContingencySide2(Map<LfBranch, DisabledBr
return status == null || status == DisabledBranchStatus.SIDE_1;
}

public enum ToLfContingencyConversionStatus {
OK,
ISOLATED_SLACK_BUS,
NO_IMPACT;
}

public Optional<LfContingency> toLfContingency(LfNetwork network) {
return toLfContingencyWithStatus(network).getKey();
}

public Pair<Optional<LfContingency>, ToLfContingencyConversionStatus> toLfContingencyWithStatus(LfNetwork network) {
// find branch to open because of direct impact of the contingency (including propagation is activated)
Map<LfBranch, DisabledBranchStatus> branchesToOpen = findBranchToOpenDirectlyImpactedByContingency(network);

// find branches to open and buses to lost not directly from the contingency impact but as a consequence of
// loss of connectivity once contingency applied on the network
ContingencyConnectivityLossImpact connectivityLossImpact = findBusesAndBranchesImpactedBecauseOfConnectivityLoss(network, branchesToOpen);
if (!connectivityLossImpact.ok) {
return Optional.empty();
return Pair.of(Optional.empty(), ToLfContingencyConversionStatus.ISOLATED_SLACK_BUS);
}
Set<LfBus> busesToLost = connectivityLossImpact.busesToLost(); // nothing else

Expand Down Expand Up @@ -521,11 +531,10 @@ public Optional<LfContingency> toLfContingency(LfNetwork network) {
&& lostHvdcs.isEmpty()
&& connectivityLossImpact.hvdcsWithoutPower().isEmpty()) {
LOGGER.debug("Contingency '{}' has no impact", contingency.getId());
return Optional.empty();
return Pair.of(Optional.empty(), ToLfContingencyConversionStatus.NO_IMPACT);
}

return Optional.of(new LfContingency(contingency.getId(), index, connectivityLossImpact.createdSynchronousComponents,
return Pair.of(Optional.of(new LfContingency(contingency.getId(), index, connectivityLossImpact.createdSynchronousComponents,
new DisabledNetwork(busesToLost, branchesToOpen, lostHvdcs), shunts, loads, generators,
connectivityLossImpact.hvdcsWithoutPower()));
connectivityLossImpact.hvdcsWithoutPower())), ToLfContingencyConversionStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -437,53 +437,65 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List<Propag
Iterator<PropagatedContingency> contingencyIt = propagatedContingencies.iterator();
while (contingencyIt.hasNext() && !Thread.currentThread().isInterrupted()) {
PropagatedContingency propagatedContingency = contingencyIt.next();
propagatedContingency.toLfContingency(lfNetwork)
.ifPresent(lfContingency -> { // only process contingencies that impact the network
ReportNode postContSimReportNode = Reports.createPostContingencySimulation(networkReportNode, lfContingency.getId());
lfNetwork.setReportNode(postContSimReportNode);

lfContingency.apply(loadFlowParameters.getBalanceType());

distributedMismatch(lfNetwork, lfContingency.getActivePowerLoss(), loadFlowParameters, openLoadFlowParameters);

var postContingencyResult = runPostContingencySimulation(lfNetwork, context, propagatedContingency.getContingency(),
lfContingency, preContingencyLimitViolationManager,
securityAnalysisParameters.getIncreasedViolationsParameters(),
preContingencyNetworkResult, createResultExtension);
postContingencyResults.add(postContingencyResult);

List<OperatorStrategy> operatorStrategiesForThisContingency = operatorStrategiesByContingencyId.get(lfContingency.getId());
if (operatorStrategiesForThisContingency != null) {
// we have at least an operator strategy for this contingency.
if (operatorStrategiesForThisContingency.size() == 1) {
runActionSimulation(lfNetwork, context,
operatorStrategiesForThisContingency.get(0), preContingencyLimitViolationManager,
securityAnalysisParameters.getIncreasedViolationsParameters(), lfActionById,
createResultExtension, lfContingency, postContingencyResult.getLimitViolationsResult(),
acParameters.getNetworkParameters())
.ifPresent(operatorStrategyResults::add);
} else {
// save post contingency state for later restoration after action
NetworkState postContingencyNetworkState = NetworkState.save(lfNetwork);
for (OperatorStrategy operatorStrategy : operatorStrategiesForThisContingency) {
runActionSimulation(lfNetwork, context,
operatorStrategy, preContingencyLimitViolationManager,
securityAnalysisParameters.getIncreasedViolationsParameters(), lfActionById,
createResultExtension, lfContingency, postContingencyResult.getLimitViolationsResult(),
acParameters.getNetworkParameters())
.ifPresent(result -> {
operatorStrategyResults.add(result);
postContingencyNetworkState.restore();
});

var lfContingencyWithStatus = propagatedContingency.toLfContingencyWithStatus(lfNetwork);

switch (lfContingencyWithStatus.getRight()) {
case ISOLATED_SLACK_BUS:
break;
case NO_IMPACT:
postContingencyResults.add(new PostContingencyResult(propagatedContingency.getContingency(), PostContingencyComputationStatus.NO_IMPACT, new ArrayList<>()));
break;
case OK:
propagatedContingency.toLfContingency(lfNetwork)
.ifPresent(lfContingency -> { // only process contingencies that impact the network
ReportNode postContSimReportNode = Reports.createPostContingencySimulation(networkReportNode, lfContingency.getId());
lfNetwork.setReportNode(postContSimReportNode);

lfContingency.apply(loadFlowParameters.getBalanceType());

distributedMismatch(lfNetwork, lfContingency.getActivePowerLoss(), loadFlowParameters, openLoadFlowParameters);

var postContingencyResult = runPostContingencySimulation(lfNetwork, context, propagatedContingency.getContingency(),
lfContingency, preContingencyLimitViolationManager,
securityAnalysisParameters.getIncreasedViolationsParameters(),
preContingencyNetworkResult, createResultExtension);
postContingencyResults.add(postContingencyResult);

List<OperatorStrategy> operatorStrategiesForThisContingency = operatorStrategiesByContingencyId.get(lfContingency.getId());
if (operatorStrategiesForThisContingency != null) {
// we have at least an operator strategy for this contingency.
if (operatorStrategiesForThisContingency.size() == 1) {
runActionSimulation(lfNetwork, context,
operatorStrategiesForThisContingency.get(0), preContingencyLimitViolationManager,
securityAnalysisParameters.getIncreasedViolationsParameters(), lfActionById,
createResultExtension, lfContingency, postContingencyResult.getLimitViolationsResult(),
acParameters.getNetworkParameters())
.ifPresent(operatorStrategyResults::add);
} else {
// save post contingency state for later restoration after action
NetworkState postContingencyNetworkState = NetworkState.save(lfNetwork);
for (OperatorStrategy operatorStrategy : operatorStrategiesForThisContingency) {
runActionSimulation(lfNetwork, context,
operatorStrategy, preContingencyLimitViolationManager,
securityAnalysisParameters.getIncreasedViolationsParameters(), lfActionById,
createResultExtension, lfContingency, postContingencyResult.getLimitViolationsResult(),
acParameters.getNetworkParameters())
.ifPresent(result -> {
operatorStrategyResults.add(result);
postContingencyNetworkState.restore();
});
}
}
}

if (contingencyIt.hasNext()) {
// restore base state
networkState.restore();
}
}
}

if (contingencyIt.hasNext()) {
// restore base state
networkState.restore();
}
});
});
break;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ public void analyse(Network network, List<PropagatedContingency> contingencies,
}
networkState.restore();
}, () -> {
// it means that the contingency has no impact.
// it means that the contingency has no impact or leads to an isolated slack bus
// we need to force the state vector to be re-initialized from base case network state
AcSolverUtil.initStateVector(lfNetwork, context.getEquationSystem(), context.getParameters().getVoltageInitializer());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1053,8 +1053,8 @@ void testSaWithDisconnectedLoadContingency() {

SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies);

// load is disconnected, contingency is skipped
assertFalse(getOptionalPostContingencyResult(result, "l2").isPresent());
// load is disconnected, contingency has no impact
assertEquals(PostContingencyComputationStatus.NO_IMPACT, getPostContingencyResult(result, "l2").getStatus());
}

@Test
Expand Down