Skip to content

Commit

Permalink
Security analysis: support new branch result API (#326)
Browse files Browse the repository at this point in the history
Co-authored-by: Bertrand Rix <bertrand.rix@artelys.com>
Co-authored-by: Anne Tilloy <anne.tilloy@rte-france.com>
  • Loading branch information
3 people authored Sep 16, 2021
1 parent af7ba75 commit 07776a0
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 17 deletions.
4 changes: 1 addition & 3 deletions src/main/java/com/powsybl/openloadflow/network/LfBranch.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ default List<AbstractLfBranch.LfLimit> getLimits2(LimitType type) {

void setDiscreteVoltageControl(DiscreteVoltageControl discreteVoltageControl);

default BranchResult createBranchResult() {
throw new PowsyblException("Unsupported type of branch for branch result: " + getId());
}
BranchResult createBranchResult(double preContingencyP1, double branchInContingencyP1);

boolean isDisabled();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,15 @@ public Evaluable getI2() {
}

@Override
public BranchResult createBranchResult() {
public BranchResult createBranchResult(double preContingencyP1, double branchInContingencyP1) {
double flowTransfer = Double.NaN;
if (preContingencyP1 != Double.NaN && branchInContingencyP1 != Double.NaN) {
flowTransfer = (p1.eval() * PerUnit.SB - preContingencyP1) / branchInContingencyP1;
}
double currentScale1 = PerUnit.ib(branch.getTerminal1().getVoltageLevel().getNominalV());
double currentScale2 = PerUnit.ib(branch.getTerminal2().getVoltageLevel().getNominalV());
return new BranchResult(getId(), p1.eval() * PerUnit.SB, q1.eval() * PerUnit.SB, currentScale1 * i1.eval(),
p2.eval() * PerUnit.SB, q2.eval() * PerUnit.SB, currentScale2 * i2.eval());
p2.eval() * PerUnit.SB, q2.eval() * PerUnit.SB, currentScale2 * i2.eval(), flowTransfer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
*/
package com.powsybl.openloadflow.network.impl;

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.DanglingLine;
import com.powsybl.iidm.network.LimitType;
import com.powsybl.openloadflow.network.*;
import com.powsybl.security.results.BranchResult;

import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -51,6 +53,11 @@ public boolean hasPhaseControlCapability() {
return false;
}

@Override
public BranchResult createBranchResult(double preContingencyP1, double branchInContingencyP1) {
throw new PowsyblException("Unsupported type of branch for branch result: " + getId());
}

@Override
public List<LfLimit> getLimits1(final LimitType type) {
switch (type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.powsybl.iidm.network.RatioTapChanger;
import com.powsybl.iidm.network.ThreeWindingsTransformer;
import com.powsybl.openloadflow.network.*;
import com.powsybl.security.results.BranchResult;

import java.util.*;

Expand Down Expand Up @@ -103,6 +104,11 @@ public boolean hasPhaseControlCapability() {
return leg.getPhaseTapChanger() != null;
}

@Override
public BranchResult createBranchResult(double preContingencyP1, double branchInContingencyP1) {
throw new PowsyblException("Unsupported type of branch for branch result: " + getId());
}

@Override
public List<LfLimit> getLimits1(final LimitType type) {
switch (type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public Evaluable getI2() {
}

@Override
public BranchResult createBranchResult() {
public BranchResult createBranchResult(double preContingencyP1, double branchInContingencyP1) {
throw new PowsyblException("Unsupported type of branch for branch result: " + aSwitch.getId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,22 @@ List<LfContingency> createContingencies(List<PropagatedContingency> propagatedCo
}

protected void addMonitorInfo(LfNetwork network, StateMonitor monitor, Collection<BranchResult> branchResultConsumer,
Collection<BusResults> busResultsConsumer, Collection<ThreeWindingsTransformerResult> threeWindingsTransformerResultConsumer) {
Collection<BusResults> busResultsConsumer, Collection<ThreeWindingsTransformerResult> threeWindingsTransformerResultConsumer,
Map<String, BranchResult> preContingencyBranchResults, String contingencyId) {
network.getBranches().stream().filter(lfBranch -> monitor.getBranchIds().contains(lfBranch.getId()))
.filter(lfBranch -> !lfBranch.isDisabled())
.forEach(lfBranch -> branchResultConsumer.add(lfBranch.createBranchResult()));
.forEach(lfBranch -> {
BranchResult branchResult;
if (contingencyId == null) {
branchResult = lfBranch.createBranchResult(Double.NaN, Double.NaN);
preContingencyBranchResults.put(lfBranch.getId(), branchResult);
} else {
double preContingencyP1 = preContingencyBranchResults.get(lfBranch.getId()) != null ? preContingencyBranchResults.get(lfBranch.getId()).getP1() : Double.NaN;
double branchInContingencyP1 = preContingencyBranchResults.get(contingencyId) != null ? preContingencyBranchResults.get(contingencyId).getP1() : Double.NaN;
branchResult = lfBranch.createBranchResult(preContingencyP1, branchInContingencyP1);
}
branchResultConsumer.add(branchResult);
});
network.getBuses().stream().filter(lfBus -> monitor.getVoltageLevelIds().contains(lfBus.getVoltageLevelId()))
.filter(lfBus -> !lfBus.isDisabled())
.forEach(lfBus -> busResultsConsumer.add(lfBus.createBusResult()));
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List<Propagated
// run pre-contingency simulation
try (AcloadFlowEngine engine = new AcloadFlowEngine(network, acParameters)) {
AcLoadFlowResult preContingencyLoadFlowResult = engine.run(Reporter.NO_OP);
Map<String, BranchResult> results = new LinkedHashMap<>();
addMonitorInfo(network, monitorIndex.getNoneStateMonitor(), preContingencyBranchResults, preContingencyBusResults,
preContingencyThreeWindingsTransformerResults);
preContingencyThreeWindingsTransformerResults, results, null);
addMonitorInfo(network, monitorIndex.getAllStateMonitor(), preContingencyBranchResults, preContingencyBusResults,
preContingencyThreeWindingsTransformerResults);
preContingencyThreeWindingsTransformerResults, results, null);
boolean preContingencyComputationOk = preContingencyLoadFlowResult.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED;
Map<Pair<String, Branch.Side>, LimitViolation> preContingencyLimitViolations = new LinkedHashMap<>();

Expand Down Expand Up @@ -150,7 +151,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List<Propagated

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

PostContingencyResult postContingencyResult = runPostContingencySimulation(network, engine, lfContingency, preContingencyLimitViolations);
PostContingencyResult postContingencyResult = runPostContingencySimulation(network, engine, lfContingency, preContingencyLimitViolations, results);
postContingencyResults.add(postContingencyResult);

if (contingencyIt.hasNext()) {
Expand All @@ -170,7 +171,8 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List<Propagated
}

private PostContingencyResult runPostContingencySimulation(LfNetwork network, AcloadFlowEngine engine, LfContingency lfContingency,
Map<Pair<String, Branch.Side>, LimitViolation> preContingencyLimitViolations) {
Map<Pair<String, Branch.Side>, LimitViolation> preContingencyLimitViolations,
Map<String, BranchResult> preContingencyBranchResults) {
LOGGER.info("Start post contingency '{}' simulation", lfContingency.getContingency().getId());

Stopwatch stopwatch = Stopwatch.createStarted();
Expand All @@ -192,10 +194,12 @@ private PostContingencyResult runPostContingencySimulation(LfNetwork network, Ac
network.getBranches().stream().filter(b -> !b.isDisabled()),
network.getBuses().stream().filter(b -> !b.isDisabled()),
postContingencyLimitViolations);
addMonitorInfo(network, monitorIndex.getAllStateMonitor(), branchResults, busResults, threeWindingsTransformerResults);

addMonitorInfo(network, monitorIndex.getAllStateMonitor(), branchResults, busResults, threeWindingsTransformerResults, preContingencyBranchResults, lfContingency.getContingency().getId());

StateMonitor stateMonitor = monitorIndex.getSpecificStateMonitors().get(lfContingency.getContingency().getId());
if (stateMonitor != null) {
addMonitorInfo(network, stateMonitor, branchResults, busResults, threeWindingsTransformerResults);
addMonitorInfo(network, stateMonitor, branchResults, busResults, threeWindingsTransformerResults, preContingencyBranchResults, lfContingency.getContingency().getId());
}
}

Expand Down
19 changes: 17 additions & 2 deletions src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
import com.powsybl.security.*;
import com.powsybl.security.detectors.LoadingLimitType;
import com.powsybl.security.monitor.StateMonitor;
import com.powsybl.security.results.BranchResult;
import com.powsybl.security.results.PostContingencyResult;
import com.powsybl.security.detectors.DefaultLimitViolationDetector;
import com.powsybl.sensitivity.SensitivityAnalysisParameters;

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

public class DcSecurityAnalysis extends AbstractSecurityAnalysis {

Expand Down Expand Up @@ -55,31 +57,44 @@ SecurityAnalysisReport runSync(final SecurityAnalysisParameters securityAnalysis

DefaultLimitViolationDetector detector = new DefaultLimitViolationDetector(1.0f, EnumSet.allOf(LoadingLimitType.class));

StateMonitor monitor = monitorIndex.getAllStateMonitor();
Map<String, BranchResult> preContingencyBranchResults = new HashMap<>();

List<LimitViolation> preContingencyLimitViolations = new ArrayList<>();
for (SensitivityValue2 sensValue : res.getValues(null)) {
SensitivityFactor2 factor = (SensitivityFactor2) sensValue.getFactorContext();
String branchId = factor.getFunctionId();
Branch<?> branch = network.getBranch(branchId);
preContingencyBranchResults.put(branchId, new BranchResult(branchId, sensValue.getFunctionReference(), Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN));
detector.checkActivePower(branch, Branch.Side.ONE, Math.abs(sensValue.getFunctionReference()), preContingencyLimitViolations::add);
}

LimitViolationsResult preContingencyResult = new LimitViolationsResult(true, preContingencyLimitViolations);

List<PostContingencyResult> postContingencyResults = new ArrayList<>();
for (Contingency contingency : contingencies) {
Map<String, BranchResult> postContingencyBranchResults = new HashMap<>();
List<SensitivityValue2> values = res.getValues(contingency.getId());
List<LimitViolation> violations = new ArrayList<>();
double branchInContingencyP1 = preContingencyBranchResults.get(contingency.getId()).getP1();

for (SensitivityValue2 v : values) {
SensitivityFactor2 factor = (SensitivityFactor2) v.getFactorContext();
String branchId = factor.getFunctionId();
Branch<?> branch = network.getBranch(branchId);

if (monitor.getBranchIds().contains(branchId)) {
BranchResult preContingencyBranchResult = preContingencyBranchResults.get(branchId);
double flowTransfer = (v.getFunctionReference() - preContingencyBranchResult.getP1()) / branchInContingencyP1;
postContingencyBranchResults.put(branchId, new BranchResult(branchId, v.getFunctionReference(), Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, flowTransfer));
}

detector.checkActivePower(branch, Branch.Side.ONE, Math.abs(v.getFunctionReference()), violations::add);
}

postContingencyResults.add(new PostContingencyResult(contingency, true, violations));
postContingencyResults.add(new PostContingencyResult(contingency, true, violations, postContingencyBranchResults, Collections.emptyMap(), Collections.emptyMap()));
}

return new SecurityAnalysisReport(new SecurityAnalysisResult(preContingencyResult, postContingencyResults));
return new SecurityAnalysisReport(new SecurityAnalysisResult(preContingencyResult, postContingencyResults, preContingencyBranchResults.values().stream().collect(Collectors.toList()), Collections.emptyList(), Collections.emptyList()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -598,10 +598,13 @@ void testSADcMode() {
fourBusNetwork.getLine("l34").newActivePowerLimits1().setPermanentLimit(0.15).add();
fourBusNetwork.getLine("l13").newActivePowerLimits1().setPermanentLimit(0.1).add();

List<StateMonitor> monitors = new ArrayList<>();
monitors.add(new StateMonitor(ContingencyContext.all(), Set.of("l14", "l12", "l23", "l34", "l13"), Collections.emptySet(), Collections.emptySet()));

OpenSecurityAnalysisProvider osaProvider = new OpenSecurityAnalysisProvider(new DenseMatrixFactory(), EvenShiloachGraphDecrementalConnectivity::new);
CompletableFuture<SecurityAnalysisReport> futureResult = osaProvider.run(fourBusNetwork, fourBusNetwork.getVariantManager().getWorkingVariantId(),
new DefaultLimitViolationDetector(), new LimitViolationFilter(), null, saParameters,
contingenciesProvider, Collections.emptyList(), Collections.emptyList());
contingenciesProvider, Collections.emptyList(), monitors);
SecurityAnalysisResult result = futureResult.join().getResult();

assertTrue(result.getPreContingencyResult().getLimitViolationsResult().isComputationOk());
Expand All @@ -613,6 +616,33 @@ void testSADcMode() {
assertEquals(4, result.getPostContingencyResults().get(3).getLimitViolationsResult().getLimitViolations().size());
assertEquals(4, result.getPostContingencyResults().get(4).getLimitViolationsResult().getLimitViolations().size());

//Branch result for first contingency
assertEquals(5, result.getPostContingencyResults().get(0).getBranchResults().size());

//Check branch results for flowTransfer computation for contingency on l14
PostContingencyResult postContl14 = result.getPostContingencyResults().stream().filter(r -> r.getContingency().getId().equals("l14")).findFirst().get();
assertEquals("l14", postContl14.getContingency().getId());

BranchResult brl14l12 = postContl14.getBranchResult("l12");
assertEquals(0.33, brl14l12.getP1(), 1e-2);
assertEquals(0.33, brl14l12.getFlowTransfer(), 1e-2);

BranchResult brl14l14 = postContl14.getBranchResult("l14");
assertEquals(0.0, brl14l14.getP1(), 1e-2);
assertEquals(-1.0, brl14l14.getFlowTransfer(), 1e-2);

BranchResult brl14l23 = postContl14.getBranchResult("l23");
assertEquals(1.33, brl14l23.getP1(), 1e-2);
assertEquals(0.33, brl14l23.getFlowTransfer(), 1e-2);

BranchResult brl14l34 = postContl14.getBranchResult("l34");
assertEquals(-1.0, brl14l34.getP1(), 1e-2);
assertEquals(1.0, brl14l34.getFlowTransfer(), 1e-2);

BranchResult brl14l13 = postContl14.getBranchResult("l13");
assertEquals(1.66, brl14l13.getP1(), 1e-2);
assertEquals(0.66, brl14l13.getFlowTransfer(), 1e-2);

StringWriter writer = new StringWriter();
Security.print(result, fourBusNetwork, writer, new AsciiTableFormatterFactory(), new TableFormatterConfig());
}
Expand Down Expand Up @@ -672,4 +702,57 @@ private static SecurityAnalysisResult runSecurityAnalysis(Network network, List<
monitors);
return futureResult.join().getResult();
}

@Test
void testSAmodeACAllBranchMonitoredFlowTransfer() {
Network network = FourBusNetworkFactory.create();
SecurityAnalysisParameters saParameters = new SecurityAnalysisParameters();
LoadFlowParameters lfParameters = new LoadFlowParameters();
OpenLoadFlowParameters olfParameters = new OpenLoadFlowParameters()
.setSlackBusSelectionMode(SlackBusSelectionMode.MOST_MESHED);
lfParameters.addExtension(OpenLoadFlowParameters.class, olfParameters);
saParameters.setLoadFlowParameters(lfParameters);

// Testing all contingencies at once
ContingenciesProvider contingenciesProvider = n -> n.getBranchStream()
.map(b -> new Contingency(b.getId(), new BranchContingency(b.getId())))
.collect(Collectors.toList());

Set<String> allBranchIds = network.getBranchStream().map(b -> b.getId()).collect(Collectors.toSet());

List<StateMonitor> monitors = new ArrayList<>();
monitors.add(new StateMonitor(ContingencyContext.all(), allBranchIds, Collections.emptySet(), Collections.emptySet()));

OpenSecurityAnalysisProvider osaProvider = new OpenSecurityAnalysisProvider(new DenseMatrixFactory(), EvenShiloachGraphDecrementalConnectivity::new);
CompletableFuture<SecurityAnalysisReport> futureResult = osaProvider.run(network, network.getVariantManager().getWorkingVariantId(),
new DefaultLimitViolationDetector(), new LimitViolationFilter(), null, saParameters,
contingenciesProvider, Collections.emptyList(), monitors);
SecurityAnalysisResult result = futureResult.join().getResult();

assertEquals(5, result.getPostContingencyResults().size());

for (PostContingencyResult r : result.getPostContingencyResults()) {
assertEquals(4, r.getBranchResults().size());
}

//Check branch results for flowTransfer computation for contingency on l14
PostContingencyResult postContl14 = result.getPostContingencyResults().stream().filter(r -> r.getContingency().getId().equals("l14")).findFirst().get();
assertEquals("l14", postContl14.getContingency().getId());

BranchResult brl14l12 = postContl14.getBranchResult("l12");
assertEquals(0.33, brl14l12.getP1(), 1e-2);
assertEquals(0.33, brl14l12.getFlowTransfer(), 1e-2);

BranchResult brl14l23 = postContl14.getBranchResult("l23");
assertEquals(1.33, brl14l23.getP1(), 1e-2);
assertEquals(0.33, brl14l23.getFlowTransfer(), 1e-2);

BranchResult brl14l34 = postContl14.getBranchResult("l34");
assertEquals(-1.0, brl14l34.getP1(), 1e-2);
assertEquals(1.0, brl14l34.getFlowTransfer(), 1e-2);

BranchResult brl14l13 = postContl14.getBranchResult("l13");
assertEquals(1.66, brl14l13.getP1(), 1e-2);
assertEquals(0.66, brl14l13.getFlowTransfer(), 1e-2);
}
}

0 comments on commit 07776a0

Please sign in to comment.