From 51b5c35d9df8f1ec69fed6aeb8fa0e4e6c842b09 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Wed, 6 Jul 2022 19:30:07 +0200 Subject: [PATCH] Security analysis functional logs (#576) Signed-off-by: Geoffroy Jamgotchian --- .../ac/outerloop/AcloadFlowEngine.java | 2 + .../openloadflow/network/LfNetwork.java | 12 ++-- .../sa/AbstractSecurityAnalysis.java | 6 +- .../openloadflow/sa/AcSecurityAnalysis.java | 23 +++++-- .../openloadflow/sa/DcSecurityAnalysis.java | 4 +- .../sa/OpenSecurityAnalysisProvider.java | 5 +- .../powsybl/openloadflow/util/Reports.java | 47 +++++++++---- ...cLoadFlowEurostagTutorialExample1Test.java | 2 +- .../openloadflow/sa/LfContingencyTest.java | 7 +- .../sa/OpenSecurityAnalysisGraphTest.java | 4 +- .../sa/OpenSecurityAnalysisTest.java | 68 +++++++++++++------ src/test/resources/esgTutoReport.txt | 14 ++-- src/test/resources/saReport.txt | 31 +++++++++ 13 files changed, 164 insertions(+), 61 deletions(-) create mode 100644 src/test/resources/saReport.txt diff --git a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java index 182b03ab63..e7ab5ba9d9 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/ac/outerloop/AcloadFlowEngine.java @@ -151,6 +151,8 @@ public AcLoadFlowResult run() { LOGGER.info("Ac loadflow complete on network {} (result={})", context.getNetwork(), result); + Reports.reportAcLfComplete(context.getNetwork().getReporter(), result.getNewtonRaphsonStatus().name()); + return result; } diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index d86c5ddfeb..adeeb2c4b2 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -79,7 +79,7 @@ public class LfNetwork extends AbstractPropertyBag implements PropertyBag { private GraphDecrementalConnectivity connectivity; - private final Reporter reporter; + private Reporter reporter; public LfNetwork(int numCC, int numSC, SlackBusSelector slackBusSelector, GraphDecrementalConnectivityFactory connectivityFactory, Reporter reporter) { @@ -107,6 +107,10 @@ public Reporter getReporter() { return reporter; } + public void setReporter(Reporter reporter) { + this.reporter = Objects.requireNonNull(reporter); + } + private void invalidateSlack() { slackBus = null; } @@ -427,7 +431,7 @@ public void writeJson(Writer writer) { } private void reportSize(Reporter reporter) { - Reports.reportNetworkSize(reporter, numCC, numSC, busesById.values().size(), branches.size()); + Reports.reportNetworkSize(reporter, busesById.values().size(), branches.size()); LOGGER.info("Network {} has {} buses and {} branches", this, busesById.values().size(), branches.size()); } @@ -444,7 +448,7 @@ public void reportBalance(Reporter reporter) { reactiveLoad += b.getLoadTargetQ() * PerUnit.SB; } - Reports.reportNetworkBalance(reporter, numCC, numSC, activeGeneration, activeLoad, reactiveGeneration, reactiveLoad); + Reports.reportNetworkBalance(reporter, activeGeneration, activeLoad, reactiveGeneration, reactiveLoad); LOGGER.info("Network {} balance: active generation={} MW, active load={} MW, reactive generation={} MVar, reactive load={} MVar", this, activeGeneration, activeLoad, reactiveGeneration, reactiveLoad); } @@ -468,7 +472,7 @@ private void validateBuses(boolean dc, Reporter reporter) { } if (!hasAtLeastOneBusVoltageControlled) { LOGGER.error("Network {} must have at least one bus voltage controlled", this); - Reports.reportNetworkMustHaveAtLeastOneBusVoltageControlled(reporter, numCC, numSC); + Reports.reportNetworkMustHaveAtLeastOneBusVoltageControlled(reporter); valid = false; } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java index 9d6f02f062..53670a572c 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java @@ -6,6 +6,7 @@ */ package com.powsybl.openloadflow.sa; +import com.powsybl.commons.reporter.Reporter; import com.powsybl.computation.CompletableFutureTask; import com.powsybl.computation.ComputationManager; import com.powsybl.contingency.ContingenciesProvider; @@ -40,12 +41,15 @@ public abstract class AbstractSecurityAnalysis { protected final StateMonitorIndex monitorIndex; + protected final Reporter reporter; + protected AbstractSecurityAnalysis(Network network, MatrixFactory matrixFactory, GraphDecrementalConnectivityFactory connectivityFactory, - List stateMonitors) { + List stateMonitors, Reporter reporter) { this.network = Objects.requireNonNull(network); this.matrixFactory = Objects.requireNonNull(matrixFactory); this.connectivityFactory = Objects.requireNonNull(connectivityFactory); this.monitorIndex = new StateMonitorIndex(stateMonitors); + this.reporter = Objects.requireNonNull(reporter); } public CompletableFuture run(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index f005270dbf..16d1733e64 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -28,6 +28,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.Reports; import com.powsybl.security.LimitViolationsResult; import com.powsybl.security.SecurityAnalysisParameters; import com.powsybl.security.SecurityAnalysisReport; @@ -42,8 +43,8 @@ public class AcSecurityAnalysis extends AbstractSecurityAnalysis { protected AcSecurityAnalysis(Network network, MatrixFactory matrixFactory, GraphDecrementalConnectivityFactory connectivityFactory, - List stateMonitors) { - super(network, matrixFactory, connectivityFactory, stateMonitors); + List stateMonitors, Reporter reporter) { + super(network, matrixFactory, connectivityFactory, stateMonitors, reporter); } private static SecurityAnalysisResult createNoResult() { @@ -57,6 +58,8 @@ private static SecurityAnalysisResult createNoResult() { @Override SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, ContingenciesProvider contingenciesProvider, ComputationManager computationManager) { + var saReporter = Reports.createAcSecurityAnalysis(reporter, network.getId()); + Stopwatch stopwatch = Stopwatch.createStarted(); LoadFlowParameters lfParameters = securityAnalysisParameters.getLoadFlowParameters(); @@ -75,10 +78,10 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete lfParameters.isShuntCompensatorVoltageControlOn(), lfParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, lfParameters.isHvdcAcEmulation(), securityAnalysisParametersExt.isContingencyPropagation()); - AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, lfParameters, lfParametersExt, matrixFactory, connectivityFactory, Reporter.NO_OP, true, false); + AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, lfParameters, lfParametersExt, matrixFactory, connectivityFactory, saReporter, true, false); // create networks including all necessary switches - List lfNetworks = createNetworks(allSwitchesToOpen, acParameters.getNetworkParameters()); + List lfNetworks = createNetworks(allSwitchesToOpen, acParameters.getNetworkParameters(), saReporter); // run simulation on largest network SecurityAnalysisResult result; @@ -100,7 +103,8 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete return new SecurityAnalysisReport(result); } - List createNetworks(Set allSwitchesToOpen, LfNetworkParameters networkParameters) { + List createNetworks(Set allSwitchesToOpen, LfNetworkParameters networkParameters, + Reporter saReporter) { List lfNetworks; String tmpVariantId = "olf-tmp-" + UUID.randomUUID(); network.getVariantManager().cloneVariant(network.getVariantManager().getWorkingVariantId(), tmpVariantId); @@ -108,7 +112,7 @@ List createNetworks(Set allSwitchesToOpen, LfNetworkParameter network.getSwitchStream().filter(sw -> sw.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) .forEach(sw -> sw.setRetained(false)); allSwitchesToOpen.forEach(sw -> sw.setRetained(true)); - lfNetworks = Networks.load(network, networkParameters, Reporter.NO_OP); + lfNetworks = Networks.load(network, networkParameters, saReporter); } finally { network.getVariantManager().removeVariant(tmpVariantId); } @@ -131,6 +135,10 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List { // only process contingencies that impact the network + Reporter postContSimReporter = Reports.createPostContingencySimulation(networkReporter, lfContingency.getId()); + network.setReporter(postContSimReporter); + lfContingency.apply(loadFlowParameters.getBalanceType()); distributedMismatch(network, lfContingency.getActivePowerLoss(), loadFlowParameters, openLoadFlowParameters); diff --git a/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java index 7361b1cd84..222e347a03 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java @@ -31,8 +31,8 @@ public class DcSecurityAnalysis extends AbstractSecurityAnalysis { protected DcSecurityAnalysis(Network network, MatrixFactory matrixFactory, GraphDecrementalConnectivityFactory connectivityFactory, - List stateMonitors) { - super(network, matrixFactory, connectivityFactory, stateMonitors); + List stateMonitors, Reporter reporter) { + super(network, matrixFactory, connectivityFactory, stateMonitors, reporter); } @Override diff --git a/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java b/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java index 11a325084e..02ab28b30c 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java +++ b/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java @@ -62,12 +62,13 @@ public CompletableFuture run(Network network, String wor Objects.requireNonNull(securityAnalysisParameters); Objects.requireNonNull(contingenciesProvider); Objects.requireNonNull(stateMonitors); + Objects.requireNonNull(reporter); AbstractSecurityAnalysis securityAnalysis; if (securityAnalysisParameters.getLoadFlowParameters().isDc()) { - securityAnalysis = new DcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors); + securityAnalysis = new DcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors, reporter); } else { - securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors); + securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors, reporter); } return securityAnalysis.run(workingVariantId, securityAnalysisParameters, contingenciesProvider, computationManager); diff --git a/src/main/java/com/powsybl/openloadflow/util/Reports.java b/src/main/java/com/powsybl/openloadflow/util/Reports.java index 1516ba9a18..10274ea703 100644 --- a/src/main/java/com/powsybl/openloadflow/util/Reports.java +++ b/src/main/java/com/powsybl/openloadflow/util/Reports.java @@ -21,27 +21,24 @@ public final class Reports { private static final String NETWORK_NUM_CC = "networkNumCc"; private static final String NETWORK_NUM_SC = "networkNumSc"; private static final String ITERATION = "iteration"; + private static final String NETWORK_ID = "networkId"; private Reports() { } - public static void reportNetworkSize(Reporter reporter, int networkNumCc, int networkNumSc, int busCount, int branchCount) { + public static void reportNetworkSize(Reporter reporter, int busCount, int branchCount) { reporter.report(Report.builder() .withKey("networkSize") - .withDefaultMessage("Network CC${networkNumCc} SC${networkNumSc} has ${busCount} buses and ${branchCount} branches") - .withValue(NETWORK_NUM_CC, networkNumCc) - .withValue(NETWORK_NUM_SC, networkNumSc) + .withDefaultMessage("Network has ${busCount} buses and ${branchCount} branches") .withValue("busCount", busCount) .withValue("branchCount", branchCount) .build()); } - public static void reportNetworkBalance(Reporter reporter, int networkNumCc, int networkNumSc, double activeGeneration, double activeLoad, double reactiveGeneration, double reactiveLoad) { + public static void reportNetworkBalance(Reporter reporter, double activeGeneration, double activeLoad, double reactiveGeneration, double reactiveLoad) { reporter.report(Report.builder() .withKey("networkBalance") - .withDefaultMessage("Network CC${networkNumCc} SC${networkNumSc} balance: active generation=${activeGeneration} MW, active load=${activeLoad} MW, reactive generation=${reactiveGeneration} MVar, reactive load=${reactiveLoad} MVar") - .withValue(NETWORK_NUM_CC, networkNumCc) - .withValue(NETWORK_NUM_SC, networkNumSc) + .withDefaultMessage("Network balance: active generation=${activeGeneration} MW, active load=${activeLoad} MW, reactive generation=${reactiveGeneration} MVar, reactive load=${reactiveLoad} MVar") .withValue("activeGeneration", activeGeneration) .withValue("activeLoad", activeLoad) .withValue("reactiveGeneration", reactiveGeneration) @@ -49,12 +46,10 @@ public static void reportNetworkBalance(Reporter reporter, int networkNumCc, int .build()); } - public static void reportNetworkMustHaveAtLeastOneBusVoltageControlled(Reporter reporter, int networkNumCc, int networkNumSc) { + public static void reportNetworkMustHaveAtLeastOneBusVoltageControlled(Reporter reporter) { reporter.report(Report.builder() .withKey("networkMustHaveAtLeastOneBusVoltageControlled") - .withDefaultMessage("Network CC${networkNumCc} SC${networkNumSc} must have at least one bus voltage controlled") - .withValue(NETWORK_NUM_CC, networkNumCc) - .withValue(NETWORK_NUM_SC, networkNumSc) + .withDefaultMessage("Network must have at least one bus voltage controlled") .build()); } @@ -142,9 +137,17 @@ public static void reportGeneratorsDiscardedFromVoltageControlBecauseMaxReactive .build()); } + public static void reportAcLfComplete(Reporter reporter, String nrStatus) { + reporter.report(Report.builder() + .withKey("acLfComplete") + .withDefaultMessage("AC load flow complete with NR status '${nrStatus}'") + .withValue("nrStatus", nrStatus) + .build()); + } + public static Reporter createLoadFlowReporter(Reporter reporter, String networkId) { - return reporter.createSubReporter("loadFlow", "Load flow on network ${networkId}", - "networkId", networkId); + return reporter.createSubReporter("loadFlow", "Load flow on network '${networkId}'", + NETWORK_ID, networkId); } public static Reporter createLfNetworkReporter(Reporter reporter, int networkNumCc, int networkNumSc) { @@ -163,6 +166,20 @@ public static Reporter createOuterLoopReporter(Reporter reporter, String outerLo public static Reporter createSensitivityAnalysis(Reporter reporter, String networkId) { return reporter.createSubReporter("sensitivityAnalysis", - "Sensitivity analysis on network ${networkId}", "networkId", networkId); + "Sensitivity analysis on network '${networkId}'", NETWORK_ID, networkId); + } + + public static Reporter createAcSecurityAnalysis(Reporter reporter, String networkId) { + return reporter.createSubReporter("acSecurityAnalysis", + "AC security analysis on network '${networkId}'", NETWORK_ID, networkId); + } + + public static Reporter createPreContingencySimulation(Reporter reporter) { + return reporter.createSubReporter("preContingencySimulation", "Pre-contingency simulation"); + } + + public static Reporter createPostContingencySimulation(Reporter reporter, String contingencyId) { + return reporter.createSubReporter("postContingencySimulation", "Post-contingency simulation '${contingencyId}'", + "contingencyId", contingencyId); } } diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowEurostagTutorialExample1Test.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowEurostagTutorialExample1Test.java index 8b8c34f50f..c564c6fc16 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowEurostagTutorialExample1Test.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowEurostagTutorialExample1Test.java @@ -288,7 +288,7 @@ void noGeneratorTest() { ReporterModel postLoadingReporter = createNetworkReporter.getSubReporters().get(0); assertEquals("postLoadingProcessing", postLoadingReporter.getTaskKey()); assertEquals(1, postLoadingReporter.getReports().size()); - assertEquals("Network CC${networkNumCc} SC${networkNumSc} must have at least one bus voltage controlled", + assertEquals("Network must have at least one bus voltage controlled", postLoadingReporter.getReports().iterator().next().getDefaultMessage()); } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfContingencyTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfContingencyTest.java index 1ebff4d52e..00cc7e6077 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfContingencyTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfContingencyTest.java @@ -8,6 +8,7 @@ import com.powsybl.commons.AbstractConverterTest; import com.powsybl.commons.PowsyblException; +import com.powsybl.commons.reporter.Reporter; import com.powsybl.contingency.BranchContingency; import com.powsybl.contingency.Contingency; import com.powsybl.contingency.GeneratorContingency; @@ -65,7 +66,7 @@ void test() throws IOException { LfNetwork mainNetwork = lfNetworks.get(0); assertEquals(2, lfNetworks.size()); - new AcSecurityAnalysis(network, new DenseMatrixFactory(), connectivityFactory, Collections.emptyList()); + new AcSecurityAnalysis(network, new DenseMatrixFactory(), connectivityFactory, Collections.emptyList(), Reporter.NO_OP); String branchId = "LINE_S3S4"; Contingency contingency = new Contingency(branchId, new BranchContingency(branchId)); @@ -94,7 +95,7 @@ void testGeneratorNotFound() { assertEquals(2, lfNetworks.size()); GraphDecrementalConnectivityFactory connectivityFactory = new EvenShiloachGraphDecrementalConnectivityFactory<>(); - new AcSecurityAnalysis(network, new DenseMatrixFactory(), connectivityFactory, Collections.emptyList()); + new AcSecurityAnalysis(network, new DenseMatrixFactory(), connectivityFactory, Collections.emptyList(), Reporter.NO_OP); String generatorId = "GEN"; Contingency contingency = new Contingency(generatorId, new GeneratorContingency(generatorId)); @@ -110,7 +111,7 @@ void testLoadNotFound() { assertEquals(2, lfNetworks.size()); GraphDecrementalConnectivityFactory connectivityFactory = new EvenShiloachGraphDecrementalConnectivityFactory<>(); - new AcSecurityAnalysis(network, new DenseMatrixFactory(), connectivityFactory, Collections.emptyList()); + new AcSecurityAnalysis(network, new DenseMatrixFactory(), connectivityFactory, Collections.emptyList(), Reporter.NO_OP); String loadId = "LOAD"; Contingency contingency = new Contingency(loadId, new LoadContingency(loadId)); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java index 060709aea8..d76ff41888 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java @@ -137,7 +137,7 @@ private void printResult(List> result) { List> getLoadFlowContingencies(GraphDecrementalConnectivityFactory connectivityFactory) { var matrixFactory = new DenseMatrixFactory(); - AcSecurityAnalysis securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, connectivityFactory, Collections.emptyList()); + AcSecurityAnalysis securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, connectivityFactory, Collections.emptyList(), Reporter.NO_OP); LoadFlowParameters lfParameters = securityAnalysisParameters.getLoadFlowParameters(); OpenLoadFlowParameters lfParametersExt = OpenLoadFlowParameters.get(securityAnalysisParameters.getLoadFlowParameters()); @@ -157,7 +157,7 @@ List> getLoadFlowContingencies(GraphDecrementalConnectivityF lfParameters, lfParametersExt, matrixFactory, connectivityFactory, Reporter.NO_OP, true, false); // create networks including all necessary switches - List lfNetworks = securityAnalysis.createNetworks(allSwitchesToOpen, acParameters.getNetworkParameters()); + List lfNetworks = securityAnalysis.createNetworks(allSwitchesToOpen, acParameters.getNetworkParameters(), Reporter.NO_OP); // run simulation on each network start = System.currentTimeMillis(); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index d7c0bf10fa..c58088db98 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -6,8 +6,10 @@ */ package com.powsybl.openloadflow.sa; +import com.google.common.io.ByteStreams; import com.powsybl.commons.PowsyblException; import com.powsybl.commons.reporter.Reporter; +import com.powsybl.commons.reporter.ReporterModel; import com.powsybl.computation.ComputationManager; import com.powsybl.contingency.*; import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory; @@ -36,12 +38,16 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.CompletionException; import java.util.concurrent.ForkJoinPool; import java.util.stream.Collectors; import java.util.stream.Stream; +import static com.powsybl.commons.TestUtil.normalizeLineSeparator; import static java.lang.Double.NaN; import static java.util.Collections.emptySet; import static org.junit.jupiter.api.Assertions.*; @@ -123,6 +129,11 @@ private SecurityAnalysisResult runSecurityAnalysis(Network network, List contingencies, List monitors, SecurityAnalysisParameters saParameters) { + return runSecurityAnalysis(network, contingencies, monitors, saParameters, Reporter.NO_OP); + } + + private SecurityAnalysisResult runSecurityAnalysis(Network network, List contingencies, List monitors, + SecurityAnalysisParameters saParameters, Reporter reporter) { ContingenciesProvider provider = n -> contingencies; SecurityAnalysisReport report = securityAnalysisProvider.run(network, network.getVariantManager().getWorkingVariantId(), @@ -133,7 +144,7 @@ private SecurityAnalysisResult runSecurityAnalysis(Network network, List createNetworkMonitors(Network network) { return List.of(new StateMonitor(ContingencyContext.all(), allBranchIds, allVoltageLevelIds, Collections.emptySet())); } - private static List allBranches(Network network) { + private static List createAllBranchesContingencies(Network network) { return network.getBranchStream() .map(b -> new Contingency(b.getId(), new BranchContingency(b.getId()))) .collect(Collectors.toList()); @@ -406,7 +417,7 @@ void testFourSubstations() { Network network = FourSubstationsNodeBreakerFactory.create(); // Testing all contingencies at once - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies); @@ -460,7 +471,7 @@ void testSaWithSeveralConnectedComponents() { Network network = ConnectedComponentNetworkFactory.createTwoUnconnectedCC(); // Testing all contingencies at once - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies); @@ -513,7 +524,7 @@ void testSaWithStateMonitorNotExistingBranchBus() { new StateMonitor(ContingencyContext.all(), Collections.singleton("l1"), Collections.singleton("bus"), Collections.singleton("three windings")) ); - SecurityAnalysisResult result = runSecurityAnalysis(network, allBranches(network), monitors); + SecurityAnalysisResult result = runSecurityAnalysis(network, createAllBranchesContingencies(network), monitors); assertEquals(0, result.getPreContingencyResult().getPreContingencyBusResults().size()); assertEquals(0, result.getPreContingencyResult().getPreContingencyBranchResults().size()); @@ -527,7 +538,7 @@ void testSaWithStateMonitorDisconnectBranch() { List monitors = new ArrayList<>(); monitors.add(new StateMonitor(ContingencyContext.all(), Collections.singleton("l24"), Collections.singleton("b1_vl"), emptySet())); - SecurityAnalysisResult result = runSecurityAnalysis(network, allBranches(network), monitors); + SecurityAnalysisResult result = runSecurityAnalysis(network, createAllBranchesContingencies(network), monitors); assertEquals(1, result.getPreContingencyResult().getPreContingencyBusResults().size()); @@ -539,7 +550,7 @@ void testSaWithStateMonitorDisconnectBranch() { network = DistributedSlackNetworkFactory.create(); network.getBranch("l24").getTerminal2().disconnect(); - result = runSecurityAnalysis(network, allBranches(network), monitors); + result = runSecurityAnalysis(network, createAllBranchesContingencies(network), monitors); assertEquals(0, result.getPreContingencyResult().getPreContingencyBranchResults().size()); @@ -547,7 +558,7 @@ void testSaWithStateMonitorDisconnectBranch() { network.getBranch("l24").getTerminal2().disconnect(); network.getBranch("l24").getTerminal1().disconnect(); - result = runSecurityAnalysis(network, allBranches(network), monitors); + result = runSecurityAnalysis(network, createAllBranchesContingencies(network), monitors); assertEquals(0, result.getPreContingencyResult().getPreContingencyBranchResults().size()); } @@ -559,7 +570,7 @@ void testSaWithStateMonitorDanglingLine() { List monitors = new ArrayList<>(); monitors.add(new StateMonitor(ContingencyContext.all(), Collections.singleton("dl1"), Collections.singleton("vl1"), emptySet())); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); CompletionException exception = assertThrows(CompletionException.class, () -> runSecurityAnalysis(network, contingencies, monitors)); assertEquals("Unsupported type of branch for branch result: dl1", exception.getCause().getMessage()); } @@ -573,7 +584,7 @@ void testSaWithStateMonitorLfLeg() { new StateMonitor(ContingencyContext.all(), emptySet(), emptySet(), Collections.singleton("3wt")) ); - SecurityAnalysisResult result = runSecurityAnalysis(network, allBranches(network), monitors); + SecurityAnalysisResult result = runSecurityAnalysis(network, createAllBranchesContingencies(network), monitors); assertEquals(1, result.getPreContingencyResult().getPreContingencyThreeWindingsTransformerResults().size()); assertAlmostEquals(new ThreeWindingsTransformerResult("3wt", 161, 82, 258, @@ -590,7 +601,7 @@ void testSaDcMode() { setSlackBusId(lfParameters, "b1_vl_0"); securityAnalysisParameters.setLoadFlowParameters(lfParameters); - List contingencies = allBranches(fourBusNetwork); + List contingencies = createAllBranchesContingencies(fourBusNetwork); fourBusNetwork.getLine("l14").newActivePowerLimits1().setPermanentLimit(0.1).add(); fourBusNetwork.getLine("l12").newActivePowerLimits1().setPermanentLimit(0.2).add(); @@ -651,7 +662,7 @@ void testSaDcModeWithIncreasedParameters() { increasedViolationsParameters.setFlowProportionalThreshold(0); securityAnalysisParameters.setIncreasedViolationsParameters(increasedViolationsParameters); - List contingencies = allBranches(fourBusNetwork); + List contingencies = createAllBranchesContingencies(fourBusNetwork); fourBusNetwork.getLine("l14").newActivePowerLimits1().setPermanentLimit(0.1).add(); fourBusNetwork.getLine("l12").newActivePowerLimits1().setPermanentLimit(0.2).add(); @@ -704,7 +715,7 @@ void testSaDcModeWithIncreasedParameters() { void testSaModeAcAllBranchMonitoredFlowTransfer() { Network network = FourBusNetworkFactory.create(); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); List monitors = createAllBranchesMonitors(network); @@ -741,7 +752,7 @@ void testSaModeAcAllBranchMonitoredFlowTransfer() { void testSaWithRemoteSharedControl() { Network network = VoltageControlNetworkFactory.createWithIdenticalTransformers(); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); List monitors = createAllBranchesMonitors(network); @@ -769,7 +780,7 @@ void testSaWithTransformerRemoteSharedControl() { saParameters.addExtension(OpenSecurityAnalysisParameters.class, new OpenSecurityAnalysisParameters() .setCreateResultExtension(true)); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); List monitors = createAllBranchesMonitors(network); @@ -820,7 +831,7 @@ void testSaWithShuntRemoteSharedControl() { LoadFlowParameters lfParameters = new LoadFlowParameters() .setShuntCompensatorVoltageControlOn(true); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); List monitors = createAllBranchesMonitors(network); @@ -1337,7 +1348,7 @@ void testWithNonImpedantLineConnectedToSlackBus() { network.getLine("L1-2-1").setR(0).setX(0); network.getLine("L4-5-1").setR(0).setX(0); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); List monitors = Collections.emptyList(); @@ -1543,7 +1554,7 @@ void testDcPermanentCurrentLimitViolations() { setSlackBusId(lfParameters, "b1_vl_0"); securityAnalysisParameters.setLoadFlowParameters(lfParameters); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); network.getLine("l14").newCurrentLimits1().setPermanentLimit(60.0).add(); network.getLine("l12").newCurrentLimits1().setPermanentLimit(120.0).add(); @@ -1592,7 +1603,7 @@ void testDcTemporaryCurrentLimitViolations() { setSlackBusId(lfParameters, "b1_vl_0"); securityAnalysisParameters.setLoadFlowParameters(lfParameters); - List contingencies = allBranches(network); + List contingencies = createAllBranchesContingencies(network); network.getLine("l14").newCurrentLimits1().setPermanentLimit(60.0) .beginTemporaryLimit().setName("60").setAcceptableDuration(Integer.MAX_VALUE).setValue(200.0).endTemporaryLimit() @@ -1665,4 +1676,23 @@ void testDanglingLineContingency() { assertEquals(75.18, result.getPreContingencyResult().getPreContingencyBranchResult("l1").getP1(), LoadFlowAssert.DELTA_POWER); assertEquals(3.333, getPostContingencyResult(result, "dl1").getBranchResult("l1").getP1(), LoadFlowAssert.DELTA_POWER); } + + @Test + void reportTest() throws IOException { + var network = EurostagTutorialExample1Factory.create(); + + List contingencies = createAllBranchesContingencies(network); + + ReporterModel reporter = new ReporterModel("TestSecurityAnalysis", "Test security analysis report"); + + runSecurityAnalysis(network, contingencies, Collections.emptyList(), new SecurityAnalysisParameters(), reporter); + + String refLogExport = normalizeLineSeparator(new String(ByteStreams.toByteArray(Objects.requireNonNull(getClass().getResourceAsStream("/saReport.txt"))), StandardCharsets.UTF_8)); + + StringWriter writer = new StringWriter(); + reporter.export(writer); + String logExport = normalizeLineSeparator(writer.toString()); + + assertEquals(refLogExport, logExport); + } } diff --git a/src/test/resources/esgTutoReport.txt b/src/test/resources/esgTutoReport.txt index 7f29867e24..0260f573f3 100644 --- a/src/test/resources/esgTutoReport.txt +++ b/src/test/resources/esgTutoReport.txt @@ -1,9 +1,10 @@ + Test ESG tutorial report - + Load flow on network sim1 + + Load flow on network 'sim1' + Network CC0 SC0 + AC load flow complete with NR status 'CONVERGED' + Post loading processing - Network CC0 SC0 has 4 buses and 4 branches - Network CC0 SC0 balance: active generation=607.0 MW, active load=600.0 MW, reactive generation=0.0 MVar, reactive load=200.0 MVar + Network has 4 buses and 4 branches + Network balance: active generation=607.0 MW, active load=600.0 MW, reactive generation=0.0 MVar, reactive load=200.0 MVar + Outer loop Distributed slack on generation Iteration 0: slack bus active power (-1.4404045651219555 MW) distributed in 1 iterations Iteration 1: already balanced @@ -11,9 +12,10 @@ + Outer loop Distributed slack on generation Iteration 1: already balanced + Outer loop Reactive limits - + Sensitivity analysis on network sim1 + + Sensitivity analysis on network 'sim1' + Network CC0 SC0 + AC load flow complete with NR status 'CONVERGED' + Post loading processing - Network CC0 SC0 has 4 buses and 4 branches - Network CC0 SC0 balance: active generation=607.0 MW, active load=600.0 MW, reactive generation=0.0 MVar, reactive load=200.0 MVar + Network has 4 buses and 4 branches + Network balance: active generation=607.0 MW, active load=600.0 MW, reactive generation=0.0 MVar, reactive load=200.0 MVar + Outer loop Reactive limits diff --git a/src/test/resources/saReport.txt b/src/test/resources/saReport.txt new file mode 100644 index 0000000000..ddebf764ec --- /dev/null +++ b/src/test/resources/saReport.txt @@ -0,0 +1,31 @@ ++ Test security analysis report + + AC security analysis on network 'sim1' + + Network CC0 SC0 + + Post loading processing + Network has 4 buses and 4 branches + Network balance: active generation=607.0 MW, active load=600.0 MW, reactive generation=0.0 MVar, reactive load=200.0 MVar + + Pre-contingency simulation + AC load flow complete with NR status 'CONVERGED' + + Outer loop Distributed slack on generation + Iteration 0: failed to distribute slack bus active power mismatch, -1.4404045651219555 MW remains + + Outer loop Reactive limits + + Post-contingency simulation 'NHV1_NHV2_1' + AC load flow complete with NR status 'CONVERGED' + + Outer loop Distributed slack on generation + Iteration 0: failed to distribute slack bus active power mismatch, 4.366500677028373 MW remains + + Outer loop Reactive limits + + Post-contingency simulation 'NHV1_NHV2_2' + AC load flow complete with NR status 'CONVERGED' + + Outer loop Distributed slack on generation + Iteration 0: failed to distribute slack bus active power mismatch, 4.366500677028373 MW remains + + Outer loop Reactive limits + + Post-contingency simulation 'NGEN_NHV1' + AC load flow complete with NR status 'CONVERGED' + + Outer loop Distributed slack on generation + Iteration 0: failed to distribute slack bus active power mismatch, 602.1113525187852 MW remains + + Outer loop Reactive limits + + Post-contingency simulation 'NHV2_NLOAD' + AC load flow complete with NR status 'CONVERGED' + + Outer loop Distributed slack on generation + Iteration 0: failed to distribute slack bus active power mismatch, -606.3549396476619 MW remains + + Outer loop Reactive limits