From 71740ff45ff1fc42b0770d6a59b1b9b536f697cb Mon Sep 17 00:00:00 2001 From: Lisrte Date: Thu, 12 Dec 2024 16:19:15 +0100 Subject: [PATCH] Fix LimitViolationsResult in dynamic SA (#407) * Add 'constraints' option in JobsXml * Add DSA integration tests from Dynawo NRT * Mutualize Dynawo simulation input files writing Signed-off-by: lisrte --- .../dynawo/it/DynawoSecurityAnalysisTest.java | 50 +++++----- .../dynawo/it/DynawoSimulationTest.java | 12 +-- .../src/test/resources/ieee14/IEEE14.iidm | 28 ++++-- .../convergence/criteria.crt | 48 ++++++++++ .../convergence/results.json | 94 +++++++++++++++++++ .../dynamicModels.groovy | 32 +++++++ .../failed-criteria/criteria.crt | 34 +++++++ .../{ => failed-criteria}/results.json | 19 +++- .../timeline_report.txt | 52 ---------- .../ieee14/{disconnectline => }/models.par | 0 .../ieee14/{disconnectline => }/network.par | 0 .../ieee14/{disconnectline => }/solvers.par | 0 .../DynawoSecurityAnalysisHandler.java | 14 +-- .../security/SecurityAnalysisContext.java | 15 +++ .../xml/SecurityAnalysisJobsXmlTest.java | 35 +++++++ .../src/test/resources/saJobs.xml | 22 +++++ .../com/powsybl/dynawo/DynawoFilesUtils.java | 72 ++++++++++++++ .../dynawo/DynawoSimulationContext.java | 4 + .../dynawo/DynawoSimulationHandler.java | 42 +-------- .../java/com/powsybl/dynawo/xml/JobsXml.java | 5 + 20 files changed, 433 insertions(+), 145 deletions(-) create mode 100644 dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/criteria.crt create mode 100644 dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/results.json create mode 100644 dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/dynamicModels.groovy create mode 100644 dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/criteria.crt rename dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/{ => failed-criteria}/results.json (72%) delete mode 100644 dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/timeline_report.txt rename dynawo-integration-tests/src/test/resources/ieee14/{disconnectline => }/models.par (100%) rename dynawo-integration-tests/src/test/resources/ieee14/{disconnectline => }/network.par (100%) rename dynawo-integration-tests/src/test/resources/ieee14/{disconnectline => }/solvers.par (100%) create mode 100644 dynawo-security-analysis/src/test/java/com/powsybl/dynawo/security/xml/SecurityAnalysisJobsXmlTest.java create mode 100644 dynawo-security-analysis/src/test/resources/saJobs.xml create mode 100644 dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoFilesUtils.java diff --git a/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSecurityAnalysisTest.java b/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSecurityAnalysisTest.java index 02b7adfa6..7d65e480c 100644 --- a/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSecurityAnalysisTest.java +++ b/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSecurityAnalysisTest.java @@ -6,12 +6,10 @@ */ package com.powsybl.dynawo.it; -import com.google.common.io.ByteStreams; import com.powsybl.commons.datasource.ResourceDataSource; import com.powsybl.commons.datasource.ResourceSet; import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.test.ComparisonUtils; -import com.powsybl.commons.test.TestUtil; import com.powsybl.contingency.Contingency; import com.powsybl.dynamicsimulation.DynamicSimulationParameters; import com.powsybl.dynamicsimulation.groovy.DynamicModelGroovyExtension; @@ -32,17 +30,17 @@ import com.powsybl.security.dynamic.DynamicSecurityAnalysisRunParameters; import com.powsybl.security.json.SecurityAnalysisResultSerializer; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; import java.util.Objects; - -import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.stream.Stream; /** * @author Laurent Issertial @@ -62,31 +60,33 @@ void setUp() throws Exception { provider = new DynawoSecurityAnalysisProvider(new DynawoAlgorithmsConfig(Path.of("/dynaflow-launcher"), true)); parameters = new DynamicSecurityAnalysisParameters() .setDynamicSimulationParameters(new DynamicSimulationParameters(0, 100)) - .setDynamicContingenciesParameters(new DynamicSecurityAnalysisParameters.ContingenciesParameters(50)); + .setDynamicContingenciesParameters(new DynamicSecurityAnalysisParameters.ContingenciesParameters(10)); dynawoSimulationParameters = new DynawoSimulationParameters(); parameters.getDynamicSimulationParameters().addExtension(DynawoSimulationParameters.class, dynawoSimulationParameters); } - @Test - void testIeee14() throws IOException { + @ParameterizedTest + @MethodSource("provideSimulationParameter") + void testIeee14DSA(String criteriaPath, List contingencies, String resultsPath) throws IOException { Network network = Network.read(new ResourceDataSource("IEEE14", new ResourceSet("/ieee14", "IEEE14.iidm"))); GroovyDynamicModelsSupplier dynamicModelsSupplier = new GroovyDynamicModelsSupplier( - getResourceAsStream("/ieee14/disconnectline/dynamicModels.groovy"), + getResourceAsStream("/ieee14/dynamic-security-analysis/dynamicModels.groovy"), GroovyExtension.find(DynamicModelGroovyExtension.class, DynawoSimulationProvider.NAME)); - List modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/models.par")); - ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/network.par"), "8"); - ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/solvers.par"), "2"); + List modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/models.par")); + ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/network.par"), "8"); + ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/solvers.par"), "2"); dynawoSimulationParameters.setModelsParameters(modelsParameters) .setNetworkParameters(networkParameters) .setSolverParameters(solverParameters) - .setSolverType(DynawoSimulationParameters.SolverType.IDA); + .setSolverType(DynawoSimulationParameters.SolverType.IDA) + .setCriteriaFilePath(Path.of(Objects.requireNonNull(getClass() + .getResource(criteriaPath)).getPath())); ReportNode reportNode = ReportNode.newRootReportNode() .withMessageTemplate("root", "Root message") .build(); - List contingencies = List.of(Contingency.load("_LOAD__11_EC")); DynamicSecurityAnalysisRunParameters runParameters = new DynamicSecurityAnalysisRunParameters() .setComputationManager(computationManager) @@ -98,16 +98,20 @@ void testIeee14() throws IOException { .join() .getResult(); - StringWriter swReporterAs = new StringWriter(); - reportNode.print(swReporterAs); - InputStream refStreamReporterAs = Objects.requireNonNull(getClass().getResourceAsStream("/ieee14/dynamic-security-analysis/timeline_report.txt")); - String refLogExportAs = TestUtil.normalizeLineSeparator(new String(ByteStreams.toByteArray(refStreamReporterAs), StandardCharsets.UTF_8)); - String logExportAs = TestUtil.normalizeLineSeparator(swReporterAs.toString()); - assertEquals(refLogExportAs, logExportAs); - StringWriter serializedResult = new StringWriter(); SecurityAnalysisResultSerializer.write(result, serializedResult); - InputStream expected = Objects.requireNonNull(getClass().getResourceAsStream("/ieee14/dynamic-security-analysis/results.json")); + InputStream expected = Objects.requireNonNull(getClass().getResourceAsStream(resultsPath)); ComparisonUtils.assertTxtEquals(expected, serializedResult.toString()); } + + private static Stream provideSimulationParameter() { + return Stream.of( + Arguments.of("/ieee14/dynamic-security-analysis/convergence/criteria.crt", + List.of(Contingency.line("_BUS____1-BUS____5-1_AC"), Contingency.generator("_GEN____2_SM")), + "/ieee14/dynamic-security-analysis/convergence/results.json"), + Arguments.of("/ieee14/dynamic-security-analysis/failed-criteria/criteria.crt", + List.of(Contingency.line("_BUS____1-BUS____5-1_AC")), + "/ieee14/dynamic-security-analysis/failed-criteria/results.json") + ); + } } diff --git a/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java b/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java index 2e5a30996..2281d2dbe 100644 --- a/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java +++ b/dynawo-integration-tests/src/test/java/com/powsybl/dynawo/it/DynawoSimulationTest.java @@ -248,9 +248,9 @@ void testIeee14DynawoSuppliers() { DynamicModelsSupplier dynamicModelsSupplier = DynawoModelsSupplier.load(getResourceAsStream("/ieee14/disconnectline/dynamicModels.json")); EventModelsSupplier eventModelsSupplier = DynawoEventModelsSupplier.load(getResourceAsStream("/ieee14/disconnectline/eventModels.json")); - List modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/models.par")); - ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/network.par"), "8"); - ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/solvers.par"), "2"); + List modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/models.par")); + ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/network.par"), "8"); + ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/solvers.par"), "2"); dynawoSimulationParameters.setModelsParameters(modelsParameters) .setNetworkParameters(networkParameters) .setSolverParameters(solverParameters) @@ -324,9 +324,9 @@ private Supplier setupIEEE14Simulation(ReportNode repor getResourceAsStream("/ieee14/disconnectline/outputVariables.groovy"), GroovyExtension.find(OutputVariableGroovyExtension.class, DynawoSimulationProvider.NAME)); - List modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/models.par")); - ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/network.par"), "8"); - ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/disconnectline/solvers.par"), "2"); + List modelsParameters = ParametersXml.load(getResourceAsStream("/ieee14/models.par")); + ParametersSet networkParameters = ParametersXml.load(getResourceAsStream("/ieee14/network.par"), "8"); + ParametersSet solverParameters = ParametersXml.load(getResourceAsStream("/ieee14/solvers.par"), "2"); dynawoSimulationParameters.setModelsParameters(modelsParameters) .setNetworkParameters(networkParameters) .setSolverParameters(solverParameters) diff --git a/dynawo-integration-tests/src/test/resources/ieee14/IEEE14.iidm b/dynawo-integration-tests/src/test/resources/ieee14/IEEE14.iidm index a38ece8f0..e72938f44 100644 --- a/dynawo-integration-tests/src/test/resources/ieee14/IEEE14.iidm +++ b/dynawo-integration-tests/src/test/resources/ieee14/IEEE14.iidm @@ -1,5 +1,17 @@ - + + @@ -78,9 +90,7 @@ - - - + @@ -94,12 +104,12 @@ - + - + @@ -111,7 +121,7 @@ - + @@ -145,11 +155,11 @@ - + - + diff --git a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/criteria.crt b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/criteria.crt new file mode 100644 index 000000000..cf3c20a6e --- /dev/null +++ b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/criteria.crt @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/results.json b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/results.json new file mode 100644 index 000000000..90ddb1f93 --- /dev/null +++ b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/convergence/results.json @@ -0,0 +1,94 @@ +{ + "version" : "1.7", + "preContingencyResult" : { + "status" : "CONVERGED", + "limitViolationsResult" : { + "limitViolations" : [ { + "subjectId" : "_BUS____1-BUS____2-1_AC", + "subjectName" : "BUS 1-BUS 2-1", + "limitType" : "CURRENT", + "limitName" : "permanent", + "limit" : 836.74, + "limitReduction" : 1.0, + "value" : 1248.0773003764798, + "side" : "ONE" + } ], + "actionsTaken" : [ ] + }, + "networkResult" : { + "branchResults" : [ ], + "busResults" : [ ], + "threeWindingsTransformerResults" : [ ] + } + }, + "postContingencyResults" : [ { + "contingency" : { + "id" : "_BUS____1-BUS____5-1_AC", + "elements" : [ { + "id" : "_BUS____1-BUS____5-1_AC", + "type" : "LINE" + } ] + }, + "status" : "CONVERGED", + "limitViolationsResult" : { + "limitViolations" : [ { + "subjectId" : "_BUS____1-BUS____2-1_AC", + "subjectName" : "BUS 1-BUS 2-1", + "limitType" : "CURRENT", + "limitName" : "PATL", + "limit" : 836.74, + "limitReduction" : 1.0, + "value" : 1248.100487597837, + "side" : "ONE" + } ], + "actionsTaken" : [ ] + }, + "networkResult" : { + "branchResults" : [ ], + "busResults" : [ ], + "threeWindingsTransformerResults" : [ ] + }, + "connectivityResult" : { + "createdSynchronousComponentCount" : 0, + "createdConnectedComponentCount" : 0, + "disconnectedLoadActivePower" : 0.0, + "disconnectedGenerationActivePower" : 0.0, + "disconnectedElements" : [ ] + } + }, { + "contingency" : { + "id" : "_GEN____2_SM", + "elements" : [ { + "id" : "_GEN____2_SM", + "type" : "GENERATOR" + } ] + }, + "status" : "CONVERGED", + "limitViolationsResult" : { + "limitViolations" : [ { + "subjectId" : "_BUS____1-BUS____2-1_AC", + "subjectName" : "BUS 1-BUS 2-1", + "limitType" : "CURRENT", + "limitName" : "PATL", + "limit" : 836.74, + "limitReduction" : 1.0, + "value" : 1248.100487597837, + "side" : "ONE" + } ], + "actionsTaken" : [ ] + }, + "networkResult" : { + "branchResults" : [ ], + "busResults" : [ ], + "threeWindingsTransformerResults" : [ ] + }, + "connectivityResult" : { + "createdSynchronousComponentCount" : 0, + "createdConnectedComponentCount" : 0, + "disconnectedLoadActivePower" : 0.0, + "disconnectedGenerationActivePower" : 0.0, + "disconnectedElements" : [ ] + } + } ], + "operatorStrategyResults" : [ ] +} \ No newline at end of file diff --git a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/dynamicModels.groovy b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/dynamicModels.groovy new file mode 100644 index 000000000..be5010ca0 --- /dev/null +++ b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/dynamicModels.groovy @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ + +import com.powsybl.iidm.network.Load + +for (Load load : network.loads) { + if (load.id != "_LOAD___2_EC") { + LoadAlphaBeta { + staticId load.id + parameterSetId "LAB" + } + } +} + +for (gen in ["_GEN____1_SM", "_GEN____2_SM", "_GEN____3_SM"]) { + GeneratorSynchronousFourWindingsProportionalRegulations { + staticId gen + parameterSetId "GSFWPR" + gen + } +} + +for (gen in ["_GEN____6_SM", "_GEN____8_SM"]) { + GeneratorSynchronousThreeWindingsProportionalRegulations { + staticId gen + parameterSetId "GSTWPR" + gen + } +} \ No newline at end of file diff --git a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/criteria.crt b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/criteria.crt new file mode 100644 index 000000000..763421ea2 --- /dev/null +++ b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/criteria.crt @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/results.json b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/results.json similarity index 72% rename from dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/results.json rename to dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/results.json index bd63cea33..c591e4cca 100644 --- a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/results.json +++ b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/failed-criteria/results.json @@ -23,15 +23,24 @@ }, "postContingencyResults" : [ { "contingency" : { - "id" : "_LOAD__11_EC", + "id" : "_BUS____1-BUS____5-1_AC", "elements" : [ { - "id" : "_LOAD__11_EC", - "type" : "LOAD" + "id" : "_BUS____1-BUS____5-1_AC", + "type" : "LINE" } ] }, - "status" : "CONVERGED", + "status" : "FAILED", "limitViolationsResult" : { - "limitViolations" : [ ], + "limitViolations" : [ { + "subjectId" : "_BUS____1-BUS____2-1_AC", + "subjectName" : "BUS 1-BUS 2-1", + "limitType" : "CURRENT", + "limitName" : "PATL", + "limit" : 836.74, + "limitReduction" : 1.0, + "value" : 1248.100487597837, + "side" : "ONE" + } ], "actionsTaken" : [ ] }, "networkResult" : { diff --git a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/timeline_report.txt b/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/timeline_report.txt deleted file mode 100644 index d5d5def84..000000000 --- a/dynawo-integration-tests/src/test/resources/ieee14/dynamic-security-analysis/timeline_report.txt +++ /dev/null @@ -1,52 +0,0 @@ -+ Root message - + Dynawo dynamic security analysis on network 'ieee14bus' - + Groovy Dynamic Models Supplier - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD__10_EC will be used instead - Model _LOAD__10_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD__11_EC will be used instead - Model _LOAD__11_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD__12_EC will be used instead - Model _LOAD__12_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD__13_EC will be used instead - Model _LOAD__13_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD__14_EC will be used instead - Model _LOAD__14_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD___2_EC will be used instead - Model _LOAD___2_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD___3_EC will be used instead - Model _LOAD___3_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD___9_EC will be used instead - Model _LOAD___9_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD___4_EC will be used instead - Model _LOAD___4_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD___6_EC will be used instead - Model _LOAD___6_EC instantiation successful - + DSL model builder for LoadAlphaBeta - 'dynamicModelId' field is not set, staticId _LOAD___5_EC will be used instead - Model _LOAD___5_EC instantiation successful - + DSL model builder for GeneratorSynchronousFourWindingsProportionalRegulations - 'dynamicModelId' field is not set, staticId _GEN____1_SM will be used instead - Model _GEN____1_SM instantiation successful - + DSL model builder for GeneratorSynchronousFourWindingsProportionalRegulations - 'dynamicModelId' field is not set, staticId _GEN____2_SM will be used instead - Model _GEN____2_SM instantiation successful - + DSL model builder for GeneratorSynchronousFourWindingsProportionalRegulations - 'dynamicModelId' field is not set, staticId _GEN____3_SM will be used instead - Model _GEN____3_SM instantiation successful - + DSL model builder for GeneratorSynchronousThreeWindingsProportionalRegulations - 'dynamicModelId' field is not set, staticId _GEN____6_SM will be used instead - Model _GEN____6_SM instantiation successful - + DSL model builder for GeneratorSynchronousThreeWindingsProportionalRegulations - 'dynamicModelId' field is not set, staticId _GEN____8_SM will be used instead - Model _GEN____8_SM instantiation successful - Contingency '_LOAD__11_EC' diff --git a/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/models.par b/dynawo-integration-tests/src/test/resources/ieee14/models.par similarity index 100% rename from dynawo-integration-tests/src/test/resources/ieee14/disconnectline/models.par rename to dynawo-integration-tests/src/test/resources/ieee14/models.par diff --git a/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/network.par b/dynawo-integration-tests/src/test/resources/ieee14/network.par similarity index 100% rename from dynawo-integration-tests/src/test/resources/ieee14/disconnectline/network.par rename to dynawo-integration-tests/src/test/resources/ieee14/network.par diff --git a/dynawo-integration-tests/src/test/resources/ieee14/disconnectline/solvers.par b/dynawo-integration-tests/src/test/resources/ieee14/solvers.par similarity index 100% rename from dynawo-integration-tests/src/test/resources/ieee14/disconnectline/solvers.par rename to dynawo-integration-tests/src/test/resources/ieee14/solvers.par diff --git a/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/DynawoSecurityAnalysisHandler.java b/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/DynawoSecurityAnalysisHandler.java index 4a65d8876..7675f2577 100644 --- a/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/DynawoSecurityAnalysisHandler.java +++ b/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/DynawoSecurityAnalysisHandler.java @@ -14,9 +14,7 @@ import com.powsybl.computation.CommandExecution; import com.powsybl.computation.ExecutionReport; import com.powsybl.dynaflow.results.ContingencyResultsUtils; -import com.powsybl.dynawo.xml.DydXml; -import com.powsybl.dynawo.xml.JobsXml; -import com.powsybl.dynawo.xml.ParametersXml; +import com.powsybl.dynawo.DynawoFilesUtils; import com.powsybl.dynawo.commons.DynawoUtil; import com.powsybl.dynawo.commons.NetworkResultsUpdater; import com.powsybl.dynawo.security.xml.ContingenciesDydXml; @@ -37,6 +35,7 @@ import java.util.Collections; import java.util.List; +import static com.powsybl.dynawo.DynawoFilesUtils.deleteExistingFile; import static com.powsybl.dynawo.commons.DynawoConstants.*; import static com.powsybl.dynawo.commons.DynawoUtil.getCommandExecutions; @@ -66,10 +65,7 @@ public DynawoSecurityAnalysisHandler(SecurityAnalysisContext context, Command co @Override public List before(Path workingDir) throws IOException { network.getVariantManager().setWorkingVariant(context.getWorkingVariantId()); - Path outputNetworkFile = workingDir.resolve(OUTPUT_IIDM_FILENAME_PATH); - if (Files.exists(outputNetworkFile)) { - Files.delete(outputNetworkFile); - } + deleteExistingFile(workingDir.resolve(OUTPUTS_FOLDER), FINAL_STATE_FOLDER, OUTPUT_IIDM_FILENAME); writeInputFiles(workingDir); return getCommandExecutions(command); } @@ -95,9 +91,7 @@ public SecurityAnalysisReport after(Path workingDir, ExecutionReport report) thr private void writeInputFiles(Path workingDir) { try { DynawoUtil.writeIidm(network, workingDir.resolve(NETWORK_FILENAME)); - JobsXml.write(workingDir, context); - DydXml.write(workingDir, context); - ParametersXml.write(workingDir, context); + DynawoFilesUtils.writeInputFiles(workingDir, context); MultipleJobsXml.write(workingDir, context); ContingenciesDydXml.write(workingDir, context); ContingenciesParXml.write(workingDir, context); diff --git a/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/SecurityAnalysisContext.java b/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/SecurityAnalysisContext.java index 174b23e22..35ba0a587 100644 --- a/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/SecurityAnalysisContext.java +++ b/dynawo-security-analysis/src/main/java/com/powsybl/dynawo/security/SecurityAnalysisContext.java @@ -96,4 +96,19 @@ public List getContingencies() { public List getContingencyEventModels() { return contingencyEventModels; } + + @Override + public boolean withCurveVariables() { + return false; + } + + @Override + public boolean withFsvVariables() { + return false; + } + + @Override + public boolean withConstraints() { + return true; + } } diff --git a/dynawo-security-analysis/src/test/java/com/powsybl/dynawo/security/xml/SecurityAnalysisJobsXmlTest.java b/dynawo-security-analysis/src/test/java/com/powsybl/dynawo/security/xml/SecurityAnalysisJobsXmlTest.java new file mode 100644 index 000000000..6b3b707df --- /dev/null +++ b/dynawo-security-analysis/src/test/java/com/powsybl/dynawo/security/xml/SecurityAnalysisJobsXmlTest.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.dynawo.security.xml; + +import com.powsybl.dynawo.DynawoSimulationConstants; +import com.powsybl.dynawo.DynawoSimulationContext; +import com.powsybl.dynawo.DynawoSimulationParameters; +import com.powsybl.dynawo.security.SecurityAnalysisContext; +import com.powsybl.dynawo.xml.DynawoTestUtil; +import com.powsybl.dynawo.xml.JobsXml; +import com.powsybl.security.dynamic.DynamicSecurityAnalysisParameters; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.util.Collections; + +/** + * @author Laurent Issertial {@literal } + */ +class SecurityAnalysisJobsXmlTest extends DynawoTestUtil { + + @Test + void testJobXml() throws IOException, SAXException { + DynawoSimulationContext context = new SecurityAnalysisContext(network, network.getVariantManager().getWorkingVariantId(), + dynamicModels, DynamicSecurityAnalysisParameters.load(), DynawoSimulationParameters.load(), Collections.emptyList()); + JobsXml.write(tmpDir, context); + validate("jobs.xsd", "saJobs.xml", tmpDir.resolve(DynawoSimulationConstants.JOBS_FILENAME)); + } +} diff --git a/dynawo-security-analysis/src/test/resources/saJobs.xml b/dynawo-security-analysis/src/test/resources/saJobs.xml new file mode 100644 index 000000000..f0476ffbd --- /dev/null +++ b/dynawo-security-analysis/src/test/resources/saJobs.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoFilesUtils.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoFilesUtils.java new file mode 100644 index 000000000..1d67f3bf8 --- /dev/null +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoFilesUtils.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.dynawo; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.dynawo.xml.DydXml; +import com.powsybl.dynawo.xml.JobsXml; +import com.powsybl.dynawo.xml.OutputVariablesXml; +import com.powsybl.dynawo.xml.ParametersXml; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; + +/** + * @author Laurent Issertial {@literal } + */ +public final class DynawoFilesUtils { + + private DynawoFilesUtils() { + } + + public static void deleteExistingFile(Path basePath, String... elements) throws IOException { + Path finalPath = basePath; + for (String element : elements) { + finalPath = finalPath.resolve(element); + if (!Files.exists(finalPath)) { + return; + } + } + Files.delete(finalPath); + } + + public static void writeInputFiles(Path workingDir, DynawoSimulationContext context) throws IOException { + JobsXml.write(workingDir, context); + DydXml.write(workingDir, context); + ParametersXml.write(workingDir, context); + if (context.withCurveVariables()) { + OutputVariablesXml.writeCurve(workingDir, context); + } + if (context.withFsvVariables()) { + OutputVariablesXml.writeFsv(workingDir, context); + } + writeDumpFiles(workingDir, context.getDynawoSimulationParameters().getDumpFileParameters()); + writeCriteriaFile(workingDir, context.getDynawoSimulationParameters()); + } + + private static void writeDumpFiles(Path workingDir, DumpFileParameters dumpFileParameters) throws IOException { + if (dumpFileParameters.useDumpFile()) { + Path dumpFilePath = dumpFileParameters.getDumpFilePath(); + if (dumpFilePath != null) { + Files.copy(dumpFilePath, workingDir.resolve(dumpFileParameters.dumpFile()), StandardCopyOption.REPLACE_EXISTING); + } + } + } + + private static void writeCriteriaFile(Path workingDir, DynawoSimulationParameters parameters) { + parameters.getCriteriaFilePath().ifPresent(filePath -> { + try { + Files.copy(filePath, workingDir.resolve(filePath.getFileName()), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new PowsyblException("Simulation criteria file error", e); + } + }); + } +} diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java index 3262977a1..4652d2592 100644 --- a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationContext.java @@ -303,6 +303,10 @@ public boolean withFsvVariables() { return outputVariables.containsKey(OutputVariable.OutputType.FINAL_STATE); } + public boolean withConstraints() { + return false; + } + public List getDynamicModelsParameters() { return dynamicModelsParameters; } diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationHandler.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationHandler.java index 0f2f7f6ec..a578dd973 100644 --- a/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationHandler.java +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/DynawoSimulationHandler.java @@ -7,7 +7,6 @@ */ package com.powsybl.dynawo; -import com.powsybl.commons.PowsyblException; import com.powsybl.commons.report.ReportNode; import com.powsybl.computation.AbstractExecutionHandler; import com.powsybl.computation.Command; @@ -18,10 +17,6 @@ import com.powsybl.dynamicsimulation.TimelineEvent; import com.powsybl.dynawo.commons.ExportMode; import com.powsybl.dynawo.outputvariables.CsvFsvParser; -import com.powsybl.dynawo.xml.OutputVariablesXml; -import com.powsybl.dynawo.xml.DydXml; -import com.powsybl.dynawo.xml.JobsXml; -import com.powsybl.dynawo.xml.ParametersXml; import com.powsybl.dynawo.commons.CommonReports; import com.powsybl.dynawo.commons.DynawoUtil; import com.powsybl.dynawo.commons.NetworkResultsUpdater; @@ -47,6 +42,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.powsybl.dynawo.DynawoFilesUtils.*; import static com.powsybl.dynawo.DynawoSimulationConstants.*; import static com.powsybl.dynawo.commons.DynawoConstants.*; import static com.powsybl.dynawo.commons.DynawoUtil.getCommandExecutions; @@ -210,41 +206,7 @@ private void setFinalStateValues(Path workingDir) { } private void writeInputFiles(Path workingDir) throws IOException { - DynawoSimulationParameters parameters = context.getDynawoSimulationParameters(); DynawoUtil.writeIidm(dynawoInput, workingDir.resolve(NETWORK_FILENAME)); - JobsXml.write(workingDir, context); - DydXml.write(workingDir, context); - ParametersXml.write(workingDir, context); - if (context.withCurveVariables()) { - OutputVariablesXml.writeCurve(workingDir, context); - } - if (context.withFsvVariables()) { - OutputVariablesXml.writeFsv(workingDir, context); - } - DumpFileParameters dumpFileParameters = parameters.getDumpFileParameters(); - if (dumpFileParameters.useDumpFile()) { - Path dumpFilePath = dumpFileParameters.getDumpFilePath(); - if (dumpFilePath != null) { - Files.copy(dumpFilePath, workingDir.resolve(dumpFileParameters.dumpFile()), StandardCopyOption.REPLACE_EXISTING); - } - } - parameters.getCriteriaFilePath().ifPresent(filePath -> { - try { - Files.copy(filePath, workingDir.resolve(filePath.getFileName()), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e) { - throw new PowsyblException("Simulation criteria file error", e); - } - }); - } - - private static void deleteExistingFile(Path basePath, String... elements) throws IOException { - Path finalPath = basePath; - for (String element : elements) { - finalPath = finalPath.resolve(element); - if (!Files.exists(finalPath)) { - return; - } - } - Files.delete(finalPath); + DynawoFilesUtils.writeInputFiles(workingDir, context); } } diff --git a/dynawo-simulation/src/main/java/com/powsybl/dynawo/xml/JobsXml.java b/dynawo-simulation/src/main/java/com/powsybl/dynawo/xml/JobsXml.java index 35b3ef86e..0d0fa9f2f 100644 --- a/dynawo-simulation/src/main/java/com/powsybl/dynawo/xml/JobsXml.java +++ b/dynawo-simulation/src/main/java/com/powsybl/dynawo/xml/JobsXml.java @@ -111,6 +111,11 @@ private static void writeOutput(XMLStreamWriter writer, DynawoSimulationContext writer.writeAttribute("local", Boolean.toString(false)); writer.writeAttribute("global", Boolean.toString(false)); + if (context.withConstraints()) { + writer.writeEmptyElement(DYN_URI, "constraints"); + writer.writeAttribute(EXPORT_MODE, ExportMode.XML.toString()); + } + writer.writeEmptyElement(DYN_URI, "timeline"); writer.writeAttribute(EXPORT_MODE, parameters.getTimelineExportMode().toString());