Skip to content

Remove network results and violation detection on disabled branches on one side in fast DC Security Analysis #1213

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

3 changes: 2 additions & 1 deletion docs/security/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ The `dcFastMode` property allows to use fast DC security analysis, based on Wood
when DC mode is activated.

Please note that fast mode has a few limitations:
- Contingencies applied on branches opened on one side are ignored.
- Contingencies applied on branches opened on one side are ignored. Also, if a contingency causes the loss of one side of a branch,
it is considered completely disabled, and no results are reported for this branch.
- AC emulation of HVDC lines is disabled, as it is not yet supported.
Instead, the [active power setpoint](../loadflow/loadflow.md#computing-hvdc-power-flow) mode is used to control the active power flow through these lines.
- Only PST remedial actions are supported for now.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,12 @@ private static List<ConnectivityAnalysisResult> computeConnectivityData(LfNetwor

GraphConnectivity<LfBus, LfBranch> connectivity = lfNetwork.getConnectivity();
for (PropagatedContingency contingency : potentiallyBreakingConnectivityContingencies) {
List<ComputedContingencyElement> breakingConnectivityCandidates = contingency.getBranchIdsToOpen().keySet().stream().map(contingencyElementByBranch::get).collect(Collectors.toList());
List<ComputedContingencyElement> breakingConnectivityCandidates = contingency.getBranchIdsToOpen().keySet().stream().sorted().map(contingencyElementByBranch::get).collect(Collectors.toList());

// we confirm the breaking of connectivity by network connectivity
Set<ComputedContingencyElement> breakingConnectivityElements;
// the traversal order of the set must be deterministic to ensure consistent element selection when multiple elements can restore connectivity
// without this, fast DC post contingency states may vary for buses disconnected from main connected component, depending on which elements were selected
LinkedHashSet<ComputedContingencyElement> breakingConnectivityElements;
connectivity.startTemporaryChanges();
try {
ComputedContingencyElement.applyToConnectivity(lfNetwork, connectivity, breakingConnectivityCandidates);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
Expand All @@ -43,11 +44,11 @@ protected AbstractNetworkResult(LfNetwork network, StateMonitorIndex monitorInde
this.createResultExtension = createResultExtension;
}

protected void addResults(StateMonitor monitor, Consumer<LfBranch> branchConsumer) {
protected void addResults(StateMonitor monitor, Consumer<LfBranch> branchConsumer, Predicate<LfBranch> isBranchDisabled) {
Objects.requireNonNull(monitor);
if (!monitor.getBranchIds().isEmpty()) {
network.getBranches().stream()
.filter(lfBranch -> !lfBranch.isDisabled())
.filter(lfBranch -> !isBranchDisabled.test(lfBranch))
.forEach(lfBranch -> {
for (String originalId : lfBranch.getOriginalIds()) {
if (monitor.getBranchIds().contains(originalId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.iidm.network.*;
import com.powsybl.openloadflow.network.LfBranch;
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.network.LfElement;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.util.Evaluable;
import com.powsybl.openloadflow.util.PerUnit;
Expand All @@ -20,6 +21,7 @@

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;

/**
Expand Down Expand Up @@ -60,10 +62,19 @@ public List<LimitViolation> getLimitViolations() {
* @param network network on which the violation limits are checked
*/
public void detectViolations(LfNetwork network) {
detectViolations(network, LfElement::isDisabled);
}

/**
* Detect violations on branches and on buses
* @param network network on which the violation limits are checked
* @param isBranchDisabled predicate to evaluate if a branch of the network is disabled or not
*/
public void detectViolations(LfNetwork network, Predicate<LfBranch> isBranchDisabled) {
Objects.requireNonNull(network);

// Detect violation limits on branches
network.getBranches().stream().filter(b -> !b.isDisabled()).forEach(this::detectBranchViolations);
network.getBranches().stream().filter(b -> !isBranchDisabled.test(b)).forEach(this::detectBranchViolations);

// Detect violation limits on buses
network.getBuses().stream().filter(b -> !b.isDisabled()).forEach(this::detectBusViolations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.ContingencyElement;
import com.powsybl.contingency.ContingencyElementType;
import com.powsybl.openloadflow.network.LfBranch;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.security.monitor.StateMonitor;
import com.powsybl.security.monitor.StateMonitorIndex;
Expand All @@ -18,6 +19,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
Expand All @@ -43,7 +45,7 @@ protected void clear() {
branchResults.clear();
}

public void addResults(StateMonitor monitor) {
public void addResults(StateMonitor monitor, Predicate<LfBranch> isBranchDisabled) {
addResults(monitor, branch -> {
var preContingencyBranchResult = preContingencyMonitorInfos.getBranchResult(branch.getId());
double preContingencyBranchP1 = preContingencyBranchResult != null ? preContingencyBranchResult.getP1() : Double.NaN;
Expand All @@ -61,17 +63,21 @@ public void addResults(StateMonitor monitor) {
}
}
branchResults.addAll(branch.createBranchResult(preContingencyBranchP1, preContingencyBranchOfContingencyP1, createResultExtension));
});
}, isBranchDisabled);
}

@Override
public void update() {
update(LfBranch::isDisabled);
}

public void update(Predicate<LfBranch> isBranchDisabled) {
clear();
StateMonitor stateMonitor = monitorIndex.getSpecificStateMonitors().get(contingency.getId());
if (stateMonitor != null) {
addResults(stateMonitor);
addResults(stateMonitor, isBranchDisabled);
} else {
addResults(monitorIndex.getAllStateMonitor());
addResults(monitorIndex.getAllStateMonitor(), isBranchDisabled);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
*/
package com.powsybl.openloadflow.sa;

import com.powsybl.openloadflow.network.LfBranch;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.security.monitor.StateMonitor;
import com.powsybl.security.monitor.StateMonitorIndex;
import com.powsybl.security.results.BranchResult;

import java.util.*;
import java.util.function.Predicate;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
Expand All @@ -31,18 +33,22 @@ protected void clear() {
branchResults.clear();
}

private void addResults(StateMonitor monitor) {
private void addResults(StateMonitor monitor, Predicate<LfBranch> isBranchDisabled) {
addResults(monitor, branch -> {
branch.createBranchResult(Double.NaN, Double.NaN, createResultExtension)
.forEach(branchResult -> branchResults.put(branchResult.getBranchId(), branchResult));
});
}, isBranchDisabled);
}

@Override
public void update() {
update(LfBranch::isDisabled);
}

public void update(Predicate<LfBranch> isBranchDisabled) {
clear();
addResults(monitorIndex.getNoneStateMonitor());
addResults(monitorIndex.getAllStateMonitor());
addResults(monitorIndex.getNoneStateMonitor(), isBranchDisabled);
addResults(monitorIndex.getAllStateMonitor(), isBranchDisabled);
}

public BranchResult getBranchResult(String branchId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -206,7 +207,8 @@ private void filterActions(List<Action> actions) {
private PostContingencyResult computePostContingencyResultFromPostContingencyStates(DcLoadFlowContext loadFlowContext, Contingency contingency, LfContingency lfContingency,
LimitViolationManager preContingencyLimitViolationManager, PreContingencyNetworkResult preContingencyNetworkResult,
boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
double[] postContingencyStates, List<LimitReduction> limitReductions) {
double[] postContingencyStates, Predicate<LfBranch> isBranchDisabledDueToContingency,
List<LimitReduction> limitReductions) {

// update network state with post contingency states
LfNetwork lfNetwork = loadFlowContext.getNetwork();
Expand All @@ -217,11 +219,11 @@ private PostContingencyResult computePostContingencyResultFromPostContingencySta

// update post contingency network result
var postContingencyNetworkResult = new PostContingencyNetworkResult(lfNetwork, monitorIndex, createResultExtension, preContingencyNetworkResult, contingency);
postContingencyNetworkResult.update();
postContingencyNetworkResult.update(isBranchDisabledDueToContingency);

// detect violations
var postContingencyLimitViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, limitReductions, violationsParameters);
postContingencyLimitViolationManager.detectViolations(lfNetwork);
postContingencyLimitViolationManager.detectViolations(lfNetwork, isBranchDisabledDueToContingency);

// connectivity result due to the application of the lf contingency
var connectivityResult = new ConnectivityResult(
Expand All @@ -244,15 +246,16 @@ private PostContingencyResult computePostContingencyResultFromPostContingencySta
*/
private PostContingencyResult processPostContingencyResult(DcLoadFlowContext context, PropagatedContingency contingency, LfContingency lfContingency, Supplier<double[]> postContingencyStatesSupplier,
LimitViolationManager preContingencyLimitViolationManager, PreContingencyNetworkResult preContingencyNetworkResult,
boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
Predicate<LfBranch> isBranchDisabledDueToContingency, boolean createResultExtension,
SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
List<LimitReduction> limitReductions) {
logPostContingencyStart(context.getNetwork(), lfContingency);
Stopwatch stopwatch = Stopwatch.createStarted();

double[] postContingencyStates = postContingencyStatesSupplier.get();
PostContingencyResult postContingencyResult = computePostContingencyResultFromPostContingencyStates(context, contingency.getContingency(),
lfContingency, preContingencyLimitViolationManager, preContingencyNetworkResult, createResultExtension,
violationsParameters, postContingencyStates, limitReductions);
violationsParameters, postContingencyStates, isBranchDisabledDueToContingency, limitReductions);

stopwatch.stop();
logPostContingencyEnd(context.getNetwork(), lfContingency, stopwatch);
Expand All @@ -266,7 +269,7 @@ private PostContingencyResult processPostContingencyResult(DcLoadFlowContext con
private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(DcLoadFlowContext loadFlowContext, LfContingency lfContingency, OperatorStrategy operatorStrategy,
List<LfAction> operatorStrategyLfActions, LimitViolationManager preContingencyLimitViolationManager,
boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
double[] postContingencyAndOperatorStrategyStates, List<LimitReduction> limitReductions) {
double[] postContingencyAndOperatorStrategyStates, Predicate<LfBranch> isBranchDisabledDueToContingency, List<LimitReduction> limitReductions) {
// update network state with post contingency and post operator strategy states
LfNetwork lfNetwork = loadFlowContext.getNetwork();
loadFlowContext.getEquationSystem().getStateVector().set(postContingencyAndOperatorStrategyStates);
Expand All @@ -278,11 +281,11 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA

// update network result
var postActionsNetworkResult = new PreContingencyNetworkResult(lfNetwork, monitorIndex, createResultExtension);
postActionsNetworkResult.update();
postActionsNetworkResult.update(isBranchDisabledDueToContingency);

// detect violations
var postActionsViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, limitReductions, violationsParameters);
postActionsViolationManager.detectViolations(lfNetwork);
postActionsViolationManager.detectViolations(lfNetwork, isBranchDisabledDueToContingency);

return new OperatorStrategyResult(operatorStrategy, PostContingencyComputationStatus.CONVERGED,
new LimitViolationsResult(postActionsViolationManager.getLimitViolations()),
Expand All @@ -297,8 +300,8 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA
private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext context, LfContingency contingency, OperatorStrategy operatorStrategy,
Function<List<LfAction>, double[]> postContingencyAndOperatorStrategyStatesSupplier,
LimitViolationManager preContingencyLimitViolationManager, PostContingencyResult postContingencyResult,
Map<String, LfAction> lfActionById, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
List<LimitReduction> limitReductions) {
Map<String, LfAction> lfActionById, Predicate<LfBranch> isBranchDisabledDueToContingency, boolean createResultExtension,
SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, List<LimitReduction> limitReductions) {
// get the actions associated to the operator strategy
List<String> actionIds = checkCondition(operatorStrategy, postContingencyResult.getLimitViolationsResult());
List<LfAction> operatorStrategyLfActions = actionIds.stream()
Expand All @@ -311,7 +314,7 @@ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext c

double[] postContingencyAndOperatorStrategyStates = postContingencyAndOperatorStrategyStatesSupplier.apply(operatorStrategyLfActions);
OperatorStrategyResult operatorStrategyResult = computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(context, contingency, operatorStrategy, operatorStrategyLfActions,
preContingencyLimitViolationManager, createResultExtension, violationsParameters, postContingencyAndOperatorStrategyStates, limitReductions);
preContingencyLimitViolationManager, createResultExtension, violationsParameters, postContingencyAndOperatorStrategyStates, isBranchDisabledDueToContingency, limitReductions);

stopwatch.stop();
logActionEnd(context.getNetwork(), operatorStrategy, stopwatch);
Expand All @@ -333,9 +336,13 @@ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext cont
ReportNode postContSimReportNode = Reports.createPostContingencySimulation(lfNetwork.getReportNode(), contingency.getContingency().getId());
lfNetwork.setReportNode(postContSimReportNode);

// predicate to determine if a branch is disabled or not due to the contingency
// note that branches with one side opened due to the contingency are considered are disabled
Predicate<LfBranch> isBranchDisabled = branch -> lfContingency.getDisabledNetwork().getBranchesStatus().containsKey(branch);

// process post contingency result with supplier giving post contingency states
PostContingencyResult postContingencyResult = processPostContingencyResult(context, contingency, lfContingency, toPostContingencyStates, preContingencyLimitViolationManager,
preContingencyNetworkResult, createResultExtension, violationsParameters, limitReductions);
preContingencyNetworkResult, isBranchDisabled, createResultExtension, violationsParameters, limitReductions);
postContingencyResults.add(postContingencyResult);

// restore pre contingency states for next calculation
Expand All @@ -349,7 +356,7 @@ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext cont

// process operator strategy result with supplier giving post contingency and post operator strategy states
OperatorStrategyResult operatorStrategyResult = processOperatorStrategyResult(context, lfContingency, operatorStrategy, toPostContingencyAndOperatorStrategyStates, preContingencyLimitViolationManager,
postContingencyResult, lfActionById, createResultExtension, violationsParameters, limitReductions);
postContingencyResult, lfActionById, isBranchDisabled, createResultExtension, violationsParameters, limitReductions);
operatorStrategyResults.add(operatorStrategyResult);

// restore pre contingency states for next calculation
Expand Down
Loading