Skip to content

Commit

Permalink
Populate ConnectivityResult in SA post contingency results (#701)
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume Verger <guillaume.verger@artelys.com>
Co-authored-by: Anne Tilloy <anne.tilloy@rte-france.com>
Co-authored-by: Bertrand Rix <bertrand.rix@artelys.com>
  • Loading branch information
3 people authored and geofjamg committed Jan 31, 2023
1 parent 765e539 commit dde2151
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 22 deletions.
48 changes: 42 additions & 6 deletions src/main/java/com/powsybl/openloadflow/network/LfContingency.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class LfContingency {

private final int index;

private final int createdSynchronousComponentsCount;

private final Set<LfBus> disabledBuses;

private final Set<LfBranch> disabledBranches;
Expand All @@ -43,28 +45,46 @@ public class LfContingency {

private final Set<LfGenerator> lostGenerators;

private double activePowerLoss = 0;
private double disconnectedLoadActivePower;

private double disconnectedGenerationActivePower;

private Set<String> disconnectedElementIds;

public LfContingency(String id, int index, Set<LfBus> disabledBuses, Set<LfBranch> disabledBranches, Map<LfShunt, AdmittanceShift> shuntsShift,
public LfContingency(String id, int index, int createdSynchronousComponentsCount, Set<LfBus> disabledBuses, Set<LfBranch> disabledBranches, Map<LfShunt, AdmittanceShift> shuntsShift,
Map<LfBus, PowerShift> busesLoadShift, Set<LfGenerator> lostGenerators, Set<LfHvdc> disabledHvdcs, Set<String> originalPowerShiftIds) {
this.id = Objects.requireNonNull(id);
this.index = index;
this.createdSynchronousComponentsCount = createdSynchronousComponentsCount;
this.disabledBuses = Objects.requireNonNull(disabledBuses);
this.disabledBranches = Objects.requireNonNull(disabledBranches);
this.disabledHvdcs = Objects.requireNonNull(disabledHvdcs);
this.shuntsShift = Objects.requireNonNull(shuntsShift);
this.busesLoadShift = Objects.requireNonNull(busesLoadShift);
this.lostGenerators = Objects.requireNonNull(lostGenerators);
this.originalPowerShiftIds = Objects.requireNonNull(originalPowerShiftIds);
this.disconnectedLoadActivePower = 0.0;
this.disconnectedGenerationActivePower = 0.0;
this.disconnectedElementIds = new HashSet<>();

for (LfBus bus : disabledBuses) {
activePowerLoss += bus.getGenerationTargetP() - bus.getLoadTargetP();
disconnectedLoadActivePower += bus.getLoadTargetP();
disconnectedGenerationActivePower += bus.getGenerationTargetP();
disconnectedElementIds.addAll(bus.getGenerators().stream().map(LfGenerator::getId).collect(Collectors.toList()));
disconnectedElementIds.addAll(bus.getAggregatedLoads().getOriginalIds());
bus.getControllerShunt().ifPresent(shunt -> disconnectedElementIds.addAll(shunt.getOriginalIds()));
bus.getShunt().ifPresent(shunt -> disconnectedElementIds.addAll(shunt.getOriginalIds()));
}
for (Map.Entry<LfBus, PowerShift> e : busesLoadShift.entrySet()) {
activePowerLoss -= e.getValue().getActive();
disconnectedLoadActivePower += e.getValue().getActive();
}
for (LfGenerator generator : lostGenerators) {
activePowerLoss += generator.getTargetP();
disconnectedGenerationActivePower += generator.getTargetP();
disconnectedElementIds.add(generator.getId());
}
disconnectedElementIds.addAll(originalPowerShiftIds);
disconnectedElementIds.addAll(disabledBranches.stream().map(LfBranch::getId).collect(Collectors.toList()));
// FIXME: shuntsShift has to be included in the disconnected elements.
}

public String getId() {
Expand All @@ -75,6 +95,10 @@ public int getIndex() {
return index;
}

public int getCreatedSynchronousComponentsCount() {
return createdSynchronousComponentsCount;
}

public Set<LfBus> getDisabledBuses() {
return disabledBuses;
}
Expand All @@ -95,8 +119,20 @@ public Set<LfGenerator> getLostGenerators() {
return lostGenerators;
}

public Set<String> getDisconnectedElementIds() {
return disconnectedElementIds;
}

public double getActivePowerLoss() {
return activePowerLoss;
return disconnectedGenerationActivePower - disconnectedLoadActivePower;
}

public double getDisconnectedLoadActivePower() {
return disconnectedLoadActivePower;
}

public double getDisconnectedGenerationActivePower() {
return disconnectedGenerationActivePower;
}

public void apply(LoadFlowParameters.BalanceType balanceType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ public Optional<LfContingency> toLfContingency(LfNetwork network) {

// add to contingency description buses and branches that won't be part of the main connected
// component in post contingency state
int createdSynchronousComponents = connectivity.getNbConnectedComponents() - 1;
Set<LfBus> buses = connectivity.getVerticesRemovedFromMainComponent();
Set<LfBranch> branches = new HashSet<>(connectivity.getEdgesRemovedFromMainComponent());

Expand Down Expand Up @@ -352,6 +353,6 @@ public Optional<LfContingency> toLfContingency(LfNetwork network) {
return Optional.empty();
}

return Optional.of(new LfContingency(contingency.getId(), index, buses, branches, shunts, busesLoadShift, generators, hvdcs, originalPowerShiftIds));
return Optional.of(new LfContingency(contingency.getId(), index, createdSynchronousComponents, buses, branches, shunts, busesLoadShift, generators, hvdcs, originalPowerShiftIds));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.powsybl.openloadflow.network.impl.PropagatedContingency;
import com.powsybl.openloadflow.network.util.ActivePowerDistribution;
import com.powsybl.openloadflow.network.util.PreviousValueVoltageInitializer;
import com.powsybl.openloadflow.util.PerUnit;
import com.powsybl.openloadflow.util.Reports;
import com.powsybl.security.*;
import com.powsybl.security.action.Action;
Expand Down Expand Up @@ -247,12 +248,17 @@ private PostContingencyResult runPostContingencySimulation(LfNetwork network, Ac
LOGGER.info("Post contingency '{}' simulation done on network {} in {} ms", lfContingency.getId(),
network, stopwatch.elapsed(TimeUnit.MILLISECONDS));

var connectivityResult = new ConnectivityResult(lfContingency.getCreatedSynchronousComponentsCount(), 0,
lfContingency.getDisconnectedLoadActivePower() * PerUnit.SB,
lfContingency.getDisconnectedGenerationActivePower() * PerUnit.SB,
lfContingency.getDisconnectedElementIds());

return new PostContingencyResult(contingency, status,
new LimitViolationsResult(postContingencyLimitViolationManager.getLimitViolations()),
postContingencyNetworkResult.getBranchResults(),
postContingencyNetworkResult.getBusResults(),
postContingencyNetworkResult.getThreeWindingsTransformerResults(),
new ConnectivityResult(0, 0, 0, 0, Collections.emptySet()));
connectivityResult);
}

private Optional<OperatorStrategyResult> runActionSimulation(LfNetwork network, AcLoadFlowContext context, OperatorStrategy operatorStrategy,
Expand Down
71 changes: 57 additions & 14 deletions src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.powsybl.openloadflow.network.impl.Networks;
import com.powsybl.openloadflow.network.impl.PropagatedContingency;
import com.powsybl.openloadflow.sensi.OpenSensitivityAnalysisProvider;
import com.powsybl.openloadflow.util.PerUnit;
import com.powsybl.security.*;
import com.powsybl.security.action.Action;
import com.powsybl.security.detectors.DefaultLimitViolationDetector;
Expand All @@ -51,7 +52,9 @@ private static class DcSecurityAnalysisContext {
private final List<Contingency> contingencies;
private final DefaultLimitViolationDetector detector;
private final double dcPowerFactor;
private final Map<String, PostContingencyResult> postContingencyResultPerContingencyId = new HashMap<>();
private final Map<String, LimitViolationsResult> limitViolationsPerContingencyId = new LinkedHashMap<>();
private final Map<String, List<BranchResult>> branchResultsPerContingencyId = new LinkedHashMap<>();
private final Map<String, ConnectivityResult> connectivityResultPerContingencyId = new LinkedHashMap<>();

public DcSecurityAnalysisContext(SecurityAnalysisParameters saParameters,
List<Contingency> contingencyList,
Expand Down Expand Up @@ -94,8 +97,16 @@ DefaultLimitViolationDetector getDetector() {
return dcPowerFactor;
}

Map<String, PostContingencyResult> getPostContingencyResultPerContingencyId() {
return postContingencyResultPerContingencyId;
Map<String, LimitViolationsResult> getLimitViolationsPerContingencyId() {
return limitViolationsPerContingencyId;
}

Map<String, List<BranchResult>> getBranchResultsPerContingencyId() {
return branchResultsPerContingencyId;
}

Map<String, ConnectivityResult> getConnectivityResultPerContingencyId() {
return connectivityResultPerContingencyId;
}
}

Expand Down Expand Up @@ -134,10 +145,17 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete

PreContingencyResult preContingencyResult = createPreContingencyResults(context, result);

List<PostContingencyResult> postContingencyResults = createPostContingencyResults(context, result);
preparePostContingencyResults(context, result);

List<OperatorStrategyResult> operatorStrategyResult = createOperatorStrategyResults(context, operatorStrategies, actions);

List<PostContingencyResult> postContingencyResults = new ArrayList<>();
for (Contingency contingency : contingencies) {
postContingencyResults.add(new PostContingencyResult(contingency, PostContingencyComputationStatus.CONVERGED,
context.getLimitViolationsPerContingencyId().get(contingency.getId()), context.getBranchResultsPerContingencyId().get(contingency.getId()),
Collections.emptyList(), Collections.emptyList(), context.getConnectivityResultPerContingencyId().get(contingency.getId())));
}

return new SecurityAnalysisReport(new SecurityAnalysisResult(preContingencyResult, postContingencyResults, operatorStrategyResult));
}

Expand All @@ -164,9 +182,8 @@ private PreContingencyResult createPreContingencyResults(DcSecurityAnalysisConte
return new PreContingencyResult(LoadFlowResult.ComponentResult.Status.CONVERGED, limitViolations, branchResults, Collections.emptyList(), Collections.emptyList());
}

private List<PostContingencyResult> createPostContingencyResults(DcSecurityAnalysisContext context, SensitivityAnalysisResult res) {
private void preparePostContingencyResults(DcSecurityAnalysisContext context, SensitivityAnalysisResult res) {

List<PostContingencyResult> postContingencyResults = new ArrayList<>();
for (Contingency contingency : context.getContingencies()) {
Map<String, BranchResult> postContingencyBranchResults = new HashMap<>();
List<SensitivityValue> values = res.getValues(contingency.getId());
Expand Down Expand Up @@ -198,12 +215,9 @@ private List<PostContingencyResult> createPostContingencyResults(DcSecurityAnaly
}
});

PostContingencyResult pcResult = new PostContingencyResult(contingency, PostContingencyComputationStatus.CONVERGED, new ArrayList<>(violations.values()),
new ArrayList<>(postContingencyBranchResults.values()), Collections.emptyList(), Collections.emptyList(), new ConnectivityResult(0, 0, 0, 0, Collections.emptySet()));
context.getPostContingencyResultPerContingencyId().put(contingency.getId(), pcResult);
postContingencyResults.add(pcResult);
context.getLimitViolationsPerContingencyId().put(contingency.getId(), new LimitViolationsResult(new ArrayList<>(violations.values()), Collections.emptyList()));
context.getBranchResultsPerContingencyId().put(contingency.getId(), new ArrayList<>(postContingencyBranchResults.values()));
}
return postContingencyResults;
}

private List<OperatorStrategyResult> createOperatorStrategyResults(DcSecurityAnalysisContext context, List<OperatorStrategy> operatorStrategies, List<Action> actions) {
Expand Down Expand Up @@ -231,7 +245,7 @@ private List<OperatorStrategyResult> createOperatorStrategyResults(DcSecurityAna
try (LfNetworkList lfNetworks = Networks.load(network, dcParameters.getNetworkParameters(), allSwitchesToOpen, allSwitchesToClose, Reporter.NO_OP)) {
return lfNetworks.getLargest().filter(LfNetwork::isValid)
.map(largestNetwork -> runActionSimulations(context, largestNetwork, dcParameters, propagatedContingencies,
operatorStrategies, actionsById, neededActions))
operatorStrategies, actionsById, neededActions))
.orElse(Collections.emptyList());
}
}
Expand Down Expand Up @@ -281,8 +295,7 @@ private List<OperatorStrategyResult> runActionSimulations(DcSecurityAnalysisCont
break;
}
for (OperatorStrategy operatorStrategy : operatorStrategiesForThisContingency) {
var postContingencyResult = context.getPostContingencyResultPerContingencyId().get(propagatedContingency.getContingency().getId());
if (checkCondition(operatorStrategy, postContingencyResult.getLimitViolationsResult())) {
if (checkCondition(operatorStrategy, context.getLimitViolationsPerContingencyId().get(propagatedContingency.getContingency().getId()))) {
propagatedContingency.toLfContingency(lfNetwork)
.ifPresent(lfContingency -> {
lfContingency.apply(context.getParameters().getLoadFlowParameters().getBalanceType());
Expand All @@ -294,9 +307,39 @@ private List<OperatorStrategyResult> runActionSimulations(DcSecurityAnalysisCont
}
}
}

completeConnectivityResults(context, lfNetwork, propagatedContingencies, networkState);

return operatorStrategyResults;
}

private void completeConnectivityResults(DcSecurityAnalysisContext context, LfNetwork lfNetwork,
List<PropagatedContingency> propagatedContingencies,
NetworkState networkState) {

// some connectivity results have not been built yet and we have to.
// after some contingencies, no operator strategies have been applied.
// we apply the contingency on the network just to complete the connectivity results.
Iterator<PropagatedContingency> contingencyIt = propagatedContingencies.iterator();
while (contingencyIt.hasNext() && !Thread.currentThread().isInterrupted()) {
PropagatedContingency propagatedContingency = contingencyIt.next();
context.getConnectivityResultPerContingencyId().computeIfAbsent(propagatedContingency.getContingency().getId(), id ->
propagatedContingency.toLfContingency(lfNetwork)
.map(lfContingency -> {
lfContingency.apply(context.getParameters().getLoadFlowParameters().getBalanceType());
// we build the connectivity result linked to this contingency by opportunity.
ConnectivityResult connectivityResult = new ConnectivityResult(lfContingency.getCreatedSynchronousComponentsCount(), 0,
lfContingency.getDisconnectedLoadActivePower() * PerUnit.SB,
lfContingency.getDisconnectedGenerationActivePower() * PerUnit.SB,
lfContingency.getDisconnectedElementIds());
networkState.restore();
return connectivityResult;
})
.orElse(new ConnectivityResult(0, 0, 0, 0, Collections.emptySet()))
);
}
}

@Override
protected PostContingencyComputationStatus runActionLoadFlow(DcLoadFlowContext context) {
DcLoadFlowResult dcLoadFlowResult = new DcLoadFlowEngine(context).run();
Expand Down
Loading

0 comments on commit dde2151

Please sign in to comment.