Skip to content
Open
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 @@ -63,7 +63,7 @@ public static final class ConnectivityAnalysisResult {
public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfOperatorStrategy operatorStrategy, LfNetwork network, Set<String> elementsToReconnect,
DisabledElements disabledElements, Set<LfBus> slackConnectedComponentBuses,
int createdSynchronousComponents) {
this.propagatedContingency = Objects.requireNonNull(propagatedContingency);
this.propagatedContingency = propagatedContingency;
this.operatorStrategy = operatorStrategy;
this.network = Objects.requireNonNull(network);
this.elementsToReconnect = elementsToReconnect;
Expand Down Expand Up @@ -153,9 +153,10 @@ private static void detectPotentialConnectivityBreak(LfNetwork lfNetwork, DenseM
private static boolean isConnectivityPotentiallyModifiedByContingencyAndOperatorStrategy(LfNetwork lfNetwork, States states, PropagatedContingency contingency,
Map<String, ComputedContingencyElement> contingencyElementByBranch, List<LfAction> operatorStrategyLfActions,
Map<LfAction, List<ComputedElement>> actionElementByBranch, EquationSystem<DcVariableType, DcEquationType> equationSystem) {
List<ComputedContingencyElement> contingencyElements = contingency.getBranchIdsToOpen().keySet().stream()
.map(contingencyElementByBranch::get)
.collect(Collectors.toList());
List<ComputedContingencyElement> contingencyElements = contingency != null ? contingency.getBranchIdsToOpen().keySet().stream()
.map(contingencyElementByBranch::get)
.toList()
: Collections.emptyList();
// The sensitivity criterion only considers actions that disable branches in order to compute a "worst-case" scenario,
// i.e. that if the criterion is not met, there is no connectivity break.
// As the actions removed either have no impact or can only close branches (and therefore affect the criterion negatively),
Expand Down Expand Up @@ -208,7 +209,7 @@ private static Optional<ConnectivityAnalysisResult> computeConnectivityAnalysisR
// concatenate all computed elements, to apply them on the connectivity
List<LfAction> lfActions = operatorStrategy == null ? Collections.emptyList() : operatorStrategy.getActions().stream().filter(LfAction::isValid).toList();
List<ComputedElement> modifyingConnectivityCandidates = Stream.concat(
contingency.getBranchIdsToOpen().keySet().stream().map(contingencyElementByBranch::get),
contingency != null ? contingency.getBranchIdsToOpen().keySet().stream().map(contingencyElementByBranch::get) : Stream.empty(),
lfActions.stream().map(actionElementByBranch::get).flatMap(Collection::stream)
).sorted(Comparator.comparing(element -> element.getLfBranch().getId())).toList();

Expand Down Expand Up @@ -356,6 +357,13 @@ public static ConnectivityBreakAnalysisResults run(DcLoadFlowContext loadFlowCon
public static ConnectivityAnalysisResult processPostContingencyAndPostOperatorStrategyConnectivityAnalysisResult(DcLoadFlowContext loadFlowContext, ConnectivityAnalysisResult postContingencyConnectivityAnalysisResult,
Map<String, ComputedContingencyElement> contingencyElementByBranch, DenseMatrix contingenciesStates,
LfOperatorStrategy operatorStrategy, Map<LfAction, List<ComputedElement>> actionElementsIndexByLfAction, DenseMatrix actionsStates) {
Objects.requireNonNull(loadFlowContext);
Objects.requireNonNull(postContingencyConnectivityAnalysisResult);
Objects.requireNonNull(contingencyElementByBranch);
Objects.requireNonNull(contingenciesStates);
Objects.requireNonNull(actionElementsIndexByLfAction);
Objects.requireNonNull(actionsStates);

// if there is no topological action, no need to process anything as the connectivity has not changed from post contingency result
boolean hasAnyTopologicalAction = operatorStrategy.getActions().stream().anyMatch(lfAction -> lfAction instanceof AbstractLfBranchAction<?>);
if (!hasAnyTopologicalAction) {
Expand All @@ -373,15 +381,16 @@ public static ConnectivityAnalysisResult processPostContingencyAndPostOperatorSt
}

// compute the connectivity result for the contingency and the associated actions
String contingencyId = contingency != null ? contingency.getContingency().getId() : "";
return computeConnectivityAnalysisResult(lfNetwork, contingency, contingencyElementByBranch, operatorStrategy, actionElementsIndexByLfAction)
.map(postContingencyAndOperatorStrategyConnectivityAnalysisResult -> {
LOGGER.debug("After graph based connectivity analysis, the contingency '{}' and operator strategy '{}' break connectivity",
contingency.getContingency().getId(), operatorStrategy.getIndexedOperatorStrategy().value().getId());
contingencyId, operatorStrategy.getIndexedOperatorStrategy().value().getId());
return postContingencyAndOperatorStrategyConnectivityAnalysisResult;
})
.orElseGet(() -> {
LOGGER.debug("After graph based connectivity analysis, the contingency '{}' and operator strategy '{}' do not break connectivity",
contingency.getContingency().getId(), operatorStrategy.getIndexedOperatorStrategy().value().getId());
contingencyId, operatorStrategy.getIndexedOperatorStrategy().value().getId());
return ConnectivityAnalysisResult.createNonBreakingConnectivityAnalysisResult(postContingencyConnectivityAnalysisResult.propagatedContingency, operatorStrategy, postContingencyConnectivityAnalysisResult.network);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ public static Map<String, List<Indexed<OperatorStrategy>>> indexByContingencyId(
case SPECIFIC ->
operatorStrategiesByContingencyId.computeIfAbsent(operatorStrategy.getContingencyContext().getContingencyId(), key -> new ArrayList<>())
.add(indexedOperatorStrategy);
case NONE -> {
// nothing to do
}
case NONE ->
operatorStrategiesByContingencyId.computeIfAbsent(null, key -> new ArrayList<>())
.add(indexedOperatorStrategy);
}
} else {
if (checkOperatorStrategies) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,14 @@ private void calculateSensitivityValuesForContingencyAndOperatorStrategy(DcLoadF
DenseMatrix flowStates, PropagatedContingency contingency, LfOperatorStrategy operatorStrategy, Map<String, ComputedContingencyElement> contingencyElementByBranch, Map<LfAction, List<ComputedElement>> actionElementByLfAction,
Set<LfBus> disabledBuses, List<ParticipatingElement> participatingElements, Set<String> elementsToReconnect,
SensitivityResultWriter resultWriter, ReportNode reportNode, Set<LfBranch> partialDisabledBranches, boolean rhsChangedAfterConnectivityBreak) {
List<LfSensitivityFactor<DcVariableType, DcEquationType>> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId());
List<ComputedContingencyElement> contingencyElements = contingency.getBranchIdsToOpen().keySet().stream()
.filter(element -> !elementsToReconnect.contains(element))
.map(contingencyElementByBranch::get)
.collect(Collectors.toList());
List<LfSensitivityFactor<DcVariableType, DcEquationType>> factors = contingency != null
? validFactorHolder.getFactorsForContingency(contingency.getContingency().getId())
: validFactorHolder.getFactorsForBaseNetwork();
List<ComputedContingencyElement> contingencyElements = contingency != null ? contingency.getBranchIdsToOpen().keySet().stream()
.filter(element -> !elementsToReconnect.contains(element))
.map(contingencyElementByBranch::get)
.toList()
: Collections.emptyList();

List<LfAction> actions = operatorStrategy != null ? operatorStrategy.getActions().stream().filter(LfAction::isValid).toList()
: Collections.emptyList();
Expand All @@ -239,7 +242,7 @@ private void calculateSensitivityValuesForContingencyAndOperatorStrategy(DcLoadF
WoodburyEngine engine = new WoodburyEngine(loadFlowContext.getParameters().getEquationSystemCreationParameters(),
contingencyElements, contingenciesStates, actionElements, actionsStates);
int operatorStrategyIndex = operatorStrategy != null ? operatorStrategy.getIndex() : -1;
if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLose().isEmpty()) {
if (contingency != null && contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLose().isEmpty()) {
DenseMatrix newFlowStates = flowStates;
// we need to recompute the factor states because the connectivity changed
if (rhsChangedAfterConnectivityBreak) {
Expand Down Expand Up @@ -276,31 +279,35 @@ private void calculateSensitivityValuesForContingencyAndOperatorStrategy(DcLoadF
List<ParticipatingElement> newParticipatingElements = participatingElements;
boolean participatingElementsChanged = false;
boolean rhsChangedAfterGlskRescaling = false;
LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null);
if (lfContingency != null) {
lfContingency.apply(lfParameters.getBalanceType());
if (isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty()) {
// deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0
Set<LfGenerator> participatingGeneratorsToRemove = lfContingency.getLostGenerators();
newParticipatingElements = participatingElements.stream()
.filter(participatingElement -> !participatingGeneratorsToRemove.contains(participatingElement.getElement()))
.map(participatingElement -> new ParticipatingElement(participatingElement.getElement(), participatingElement.getFactor()))
.collect(Collectors.toList());
normalizeParticipationFactors(newParticipatingElements);
participatingElementsChanged = true;
} else if (isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLose().isEmpty()) {
newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt);
participatingElementsChanged = true;
}
if (factorGroups.hasMultiVariables()) {
Set<LfBus> impactedBuses = lfContingency.getLoadAndGeneratorBuses();
rhsChangedAfterGlskRescaling = rescaleGlsk(factorGroups, impactedBuses);
if (contingency != null) {
LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null);
if (lfContingency != null) {
lfContingency.apply(lfParameters.getBalanceType());
if (isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty()) {
// deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0
Set<LfGenerator> participatingGeneratorsToRemove = lfContingency.getLostGenerators();
newParticipatingElements = participatingElements.stream()
.filter(participatingElement -> !participatingGeneratorsToRemove.contains(participatingElement.getElement()))
.map(participatingElement -> new ParticipatingElement(participatingElement.getElement(), participatingElement.getFactor()))
.collect(Collectors.toList());
normalizeParticipationFactors(newParticipatingElements);
participatingElementsChanged = true;
} else if (isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLose().isEmpty()) {
newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt);
participatingElementsChanged = true;
}
if (factorGroups.hasMultiVariables()) {
Set<LfBus> impactedBuses = lfContingency.getLoadAndGeneratorBuses();
rhsChangedAfterGlskRescaling = rescaleGlsk(factorGroups, impactedBuses);
}
// write contingency status
resultWriter.writeStateStatus(contingency.getIndex(), operatorStrategyIndex, SensitivityAnalysisResult.Status.SUCCESS);
} else {
// write contingency status
resultWriter.writeStateStatus(contingency.getIndex(), operatorStrategyIndex, SensitivityAnalysisResult.Status.NO_IMPACT);
}
// write contingency status
resultWriter.writeStateStatus(contingency.getIndex(), operatorStrategyIndex, SensitivityAnalysisResult.Status.SUCCESS);
} else {
// write contingency status
resultWriter.writeStateStatus(contingency.getIndex(), operatorStrategyIndex, SensitivityAnalysisResult.Status.NO_IMPACT);
resultWriter.writeStateStatus(-1, operatorStrategyIndex, SensitivityAnalysisResult.Status.SUCCESS);
}

// we need to recompute the factor states because the rhs or the participating elements have changed
Expand All @@ -320,7 +327,9 @@ private void calculateSensitivityValuesForContingencyAndOperatorStrategy(DcLoadF

private static Set<String> findDisabledBranchIds(PropagatedContingency contingency, List<LfAction> actions) {
Set<String> disableBranchIds = new HashSet<>();
disableBranchIds.addAll(contingency.getBranchIdsToOpen().keySet());
if (contingency != null) {
disableBranchIds.addAll(contingency.getBranchIdsToOpen().keySet());
}
for (LfAction action : actions) {
if (action instanceof AbstractLfBranchAction<?> branchAction) {
if (!branchAction.getDisabledBranches().isEmpty()) {
Expand Down Expand Up @@ -609,6 +618,36 @@ public void analyse(Network network, String workingVariantId, List<Contingency>

// process operator strategies
if (parameters.getOperatorStrategiesCalculationMode() != SensitivityOperatorStrategiesCalculationMode.NONE) {
// pre-contingency operator strategies (preventive actions)
List<Indexed<OperatorStrategy>> preContingencyOperatorStrategies = operatorStrategiesByContingencyId.getOrDefault(null, Collections.emptyList());
if (!preContingencyOperatorStrategies.isEmpty()) {
LOGGER.info("Running pre-contingency operator strategies...");

for (Indexed<OperatorStrategy> operatorStrategyForBaseCase : preContingencyOperatorStrategies) {
if (Thread.currentThread().isInterrupted()) {
stopwatch.stop();
throw new PowsyblException("Computation was interrupted");
}
workingFlowStates.copyValuesFrom(baseFlowStates);
workingFactorStates.copyValuesFrom(baseFactorStates);

List<String> operatorStrategyActionIds = operatorStrategyForBaseCase.value().getConditionalActions().stream().flatMap(conditionalActions -> conditionalActions.getActionIds().stream()).toList();
List<LfAction> operatorStrategyLfActions = operatorStrategyActionIds.stream().map(lfActionById::get).toList();
LfOperatorStrategy lfOperatorStrategy = new LfOperatorStrategy(operatorStrategyForBaseCase, operatorStrategyLfActions);
var postActionsConnectivityAnalysisResult = ConnectivityBreakAnalysis.processPostContingencyAndPostOperatorStrategyConnectivityAnalysisResult(loadFlowContext,
ConnectivityBreakAnalysis.ConnectivityAnalysisResult.createNonBreakingConnectivityAnalysisResult(null, lfOperatorStrategy, lfNetwork),
connectivityBreakAnalysisResults.contingencyElementByBranch(),
connectivityBreakAnalysisResults.contingenciesStates(),
lfOperatorStrategy,
actionElementsIndexByLfAction,
actionsStates);

processContingencyAndOperatorStrategy(postActionsConnectivityAnalysisResult, loadFlowContext, lfParameters, lfParametersExt,
validFactorHolder, factorGroups, participatingElements, connectivityBreakAnalysisResults.contingencyElementByBranch(), actionElementsIndexByLfAction,
workingFlowStates, workingFactorStates, connectivityBreakAnalysisResults.contingenciesStates(), actionsStates, resultWriter, sensiReportNode);
}
}

LOGGER.info("Running operator strategies connectivity analysis...");
Stopwatch operatorStrategyStopwatch = Stopwatch.createStarted();
List<ConnectivityBreakAnalysis.ConnectivityAnalysisResult> postActionsConnectivityAnalysisResults = new ArrayList<>();
Expand Down
Loading
Loading