From 9596c0172d8d7708c02ab4b70f74921001a90a58 Mon Sep 17 00:00:00 2001 From: MioRtia Date: Mon, 14 Jun 2021 10:06:53 +0200 Subject: [PATCH] Refactoring of security analysis api (#1766) * Remove deprecated code (#1579) * Use ServiceLoader to create SecurityAnalysis (#1585) * Add SecurityAnalysisProvider * Add FIXME to rename later and fix comments issues * Remove runWithLog method in SecurityAnalysisProvider * Replace SecurityAnalysis factory uses by loaded SecurityAnalysisProvider (#1618) * Refactoring security-analysis-api : SecurityAnalysisImpl (issue 1604) (#1648) * Refactoring security-analysis-api : Remove WithLog suffixed methods (#1667) * Remove SecurityAnalysisResultWithLog class * Replace WithLog methods with bollean usage * Add SecurityAnalysisReport composed by SecurityAnalysisResult & LogBytes Signed-off-by: Thomas ADAM * After rebasing: bump to 4.2.0-SNAPSHOT version + do not use "default" word in automatic module name (forbidden) * Add default impl of API AS in distribution core * Bump to 4.3.0-SNAPSHOT Signed-off-by: RALAMBOTIANA MIORA * Monitor security analysis (#1737) * On demand results for specific equipments Signed-off-by: Etienne Lesot * Corrections following reviewer's comments: - Rename SecurityAnalysisResult.getPreContingencyLimitViolationsResult - Use only pre/post contingency in javadoc - Put methods in StateMonitorJson in StateMonitor - Clear before addAll in setMonitors * Corrections following reviewer's comments: - PreContingencyResult constructor requires Collections, not Maps - Correct SecurityAnalysisResult deserializer and test files - Optimize monitor merging in StateMonitorIndex - Add ID-based getters in PreContingencyResult - Delete redundant methods in SecurityAnalysisResult - If a monitored ID does not exist, ignore it - Add tests * Rebasing from master and resolving conflicts Co-authored-by: RALAMBOTIANA MIORA Co-authored-by: EtienneLt <32468651+EtienneLt@users.noreply.github.com> --- ...AbstractSecurityAnalysisResultBuilder.java | 2 + .../SecurityAnalysisResultBuilderTest.java | 3 +- .../contingency/ContingencyContext.java | 85 ++++++ .../contingency/ContingencyContextType.java | 31 +++ .../contingency/ContingencyContextTest.java | 23 ++ distribution-core/pom.xml | 7 + pom.xml | 2 +- .../AbstractLimitViolationDetector.java | 19 -- .../security/AbstractSecurityAnalysis.java | 59 ----- .../DefaultLimitViolationDetector.java | 18 -- .../security/PostContingencyResult.java | 45 ---- .../powsybl/security/SecurityAnalysis.java | 74 ------ .../security/SecurityAnalysisFactories.java | 34 --- .../security/SecurityAnalysisFactory.java | 65 ----- .../security/SecurityAnalysisFactoryImpl.java | 35 --- .../SecurityAnalysisFactoryPluginInfo.java | 18 -- .../powsybl/security/SecurityAnalyzer.java | 106 -------- .../DistributedSecurityAnalysis.java | 71 ------ .../distributed/ExternalSecurityAnalysis.java | 97 ------- .../SecurityAnalysisInterceptor.java | 119 --------- .../SecurityAnalysisResultWithLogTest.java | 35 --- .../security/SecurityAnalysisTest.java | 156 ------------ .../SecurityAnalysisExecutionImplTest.java | 82 ------ .../SecurityAnalysisInterceptorTest.java | 101 -------- .../tools/SecurityAnalysisMockFactory.java | 77 ------ security-analysis/pom.xml | 31 +++ .../security-analysis-api}/pom.xml | 4 +- .../com/powsybl/security/LimitViolation.java | 0 .../security/LimitViolationBuilder.java | 0 .../security/LimitViolationDetector.java | 0 .../security/LimitViolationFilter.java | 0 .../security/LimitViolationHelper.java | 0 .../powsybl/security/LimitViolationType.java | 0 .../com/powsybl/security/LimitViolations.java | 0 .../security/LimitViolationsResult.java | 0 .../com/powsybl/security/NetworkMetadata.java | 0 .../java/com/powsybl/security/Security.java | 11 +- .../powsybl/security/SecurityAnalysis.java | 211 +++++++++++++++ .../security/SecurityAnalysisConfig.java | 0 .../security/SecurityAnalysisInput.java | 0 .../security/SecurityAnalysisParameters.java | 0 .../security/SecurityAnalysisProvider.java | 133 ++++++++++ .../security/SecurityAnalysisReport.java | 24 +- .../security/SecurityAnalysisResult.java | 33 ++- .../SecurityAnalysisResultBuilder.java | 67 ++++- .../SecurityAnalysisResultMerger.java | 4 +- .../CompareSecurityAnalysisResultsTool.java | 0 .../comparator/LimitViolationComparator.java | 0 .../comparator/LimitViolationEquivalence.java | 0 .../LimitViolationsResultEquivalence.java | 0 .../PostContingencyResultComparator.java | 2 +- ...ecurityAnalysisResultComparisonWriter.java | 0 .../SecurityAnalysisResultEquivalence.java | 4 +- .../JsonSecurityAnalysisResultExporter.java | 0 .../SecurityAnalysisResultExporter.java | 0 .../SecurityAnalysisResultExporters.java | 0 .../AbstractContingencyBlindDetector.java | 0 .../AbstractLimitViolationDetector.java | 0 .../DefaultLimitViolationDetector.java | 0 .../security/detectors/LoadingLimitType.java | 0 .../security/detectors/package-info.java | 0 .../DistributedSecurityAnalysisExecution.java | 17 +- .../ExternalSecurityAnalysisConfig.java | 0 .../ForwardedSecurityAnalysisExecution.java | 16 +- .../SecurityAnalysisCommandOptions.java | 0 .../SecurityAnalysisExecutionHandler.java | 19 +- .../SecurityAnalysisExecutionHandlers.java | 120 +++------ .../distributed/SubContingenciesProvider.java | 0 .../security/distributed/package-info.java | 0 .../security/execution/NetworkVariant.java | 0 .../execution/SecurityAnalysisExecution.java | 9 +- .../SecurityAnalysisExecutionBuilder.java | 16 +- .../SecurityAnalysisExecutionImpl.java | 47 ++-- .../SecurityAnalysisExecutionInput.java | 24 ++ .../SecurityAnalysisInputBuildStrategy.java | 0 .../security/execution/package-info.java | 0 .../extensions/ActivePowerExtension.java | 0 .../security/extensions/CurrentExtension.java | 0 .../security/extensions/VoltageExtension.java | 0 .../CurrentLimitViolationInterceptor.java | 2 +- .../DefaultSecurityAnalysisInterceptor.java | 2 +- .../DefaultSecurityAnalysisResultContext.java | 0 .../security/interceptors/RunningContext.java | 0 .../SecurityAnalysisInterceptor.java | 70 +++++ .../SecurityAnalysisInterceptorExtension.java | 0 .../SecurityAnalysisInterceptors.java | 0 .../SecurityAnalysisResultContext.java | 0 .../json/ActivePowerExtensionSerializer.java | 0 .../json/CurrentExtensionSerializer.java | 0 .../json/JsonSecurityAnalysisParameters.java | 0 .../json/LimitViolationDeserializer.java | 0 .../LimitViolationResultDeserializer.java | 0 .../json/LimitViolationSerializer.java | 0 .../json/LimitViolationsResultSerializer.java | 0 .../json/NetworkMetadataDeserializer.java | 0 .../json/NetworkMetadataSerializer.java | 0 .../PostContingencyResultDeserializer.java | 29 ++- .../json/PostContingencyResultSerializer.java | 5 +- .../PreContingencyResultDeserializer.java | 69 +++++ .../json/PreContingencyResultSerializer.java | 34 +++ .../json/SecurityAnalysisJsonModule.java | 4 + ...ecurityAnalysisParametersDeserializer.java | 0 .../SecurityAnalysisParametersJsonModule.java | 0 .../SecurityAnalysisParametersSerializer.java | 0 .../SecurityAnalysisResultDeserializer.java | 27 +- .../SecurityAnalysisResultSerializer.java | 2 +- .../json/VoltageExtensionSerializer.java | 0 .../security/monitor/StateMonitor.java | 137 ++++++++++ .../security/monitor/StateMonitorIndex.java | 52 ++++ ...tingenciesProviderPreprocessorFactory.java | 0 .../SecurityAnalysisPreprocessor.java | 0 .../SecurityAnalysisPreprocessorFactory.java | 0 .../SecurityAnalysisPreprocessors.java | 0 .../security/preprocessor/package-info.java | 0 .../security/results/BranchResult.java | 113 ++++++++ .../powsybl/security/results/BusResults.java | 85 ++++++ .../results/PostContingencyResult.java | 105 ++++++++ .../results/PreContingencyResult.java | 78 ++++++ .../ThreeWindingsTransformerResult.java | 137 ++++++++++ .../security/tools/SecurityAnalysisTool.java | 184 +++++++------ .../tools/SecurityAnalysisToolConstants.java | 3 + .../security/LimitViolationBuilderTest.java | 0 .../security/LimitViolationFilterTest.java | 0 .../powsybl/security/LimitViolationTest.java | 0 .../powsybl/security/NetworkImporterMock.java | 0 .../security/SecurityAnalysisConfigTest.java | 0 .../security/SecurityAnalysisInputTest.java | 0 .../SecurityAnalysisParametersTest.java | 0 .../SecurityAnalysisResultBuilderTest.java | 22 +- .../SecurityAnalysisResultMergerTest.java | 3 +- .../com/powsybl/security/SecurityTest.java | 1 + .../security/TestingNetworkFactory.java | 0 ...ompareSecurityAnalysisResultsToolTest.java | 0 .../LimitViolationComparatorTest.java | 0 .../LimitViolationEquivalenceTest.java | 0 .../LimitViolationsResultEquivalenceTest.java | 0 .../PostContingencyResultComparatorTest.java | 2 +- ...ityAnalysisResultComparisonWriterTest.java | 0 ...SecurityAnalysisResultEquivalenceTest.java | 2 +- .../security/converter/ExporterTest.java | 41 ++- .../DefaultLimitViolationDetectorTest.java | 0 .../detectors/LimitViolationDetectorTest.java | 0 .../DistributedSecurityAnalysisTest.java | 53 ---- .../SecurityAnalysisCommandOptionsTest.java | 0 ...SecurityAnalysisExecutionHandlersTest.java | 74 +++--- .../SubContingenciesProviderTest.java | 0 .../execution/NetworkVariantTest.java | 0 .../SecurityAnalysisExecutionBuilderTest.java | 69 ++--- .../SecurityAnalysisExecutionImplTest.java | 98 +++++++ .../SecurityAnalysisExecutionInputTest.java | 0 .../security/json/JsonMonitorTest.java | 31 +++ .../JsonSecurityAnalysisParametersTest.java | 0 .../json/PostContingencyResultTest.java | 92 +++++++ .../SecurityAnalysisPreprocessorsTest.java | 0 .../tools/SecurityAnalysisToolTest.java | 103 ++++++-- .../test/resources/MonitoringFileTest.json | 1 + .../resources/PostContingencyResultTest.json | 1 + .../resources/SecurityAnalysisParameters.json | 0 ...rityAnalysisParametersExtensionUpdate.json | 0 .../SecurityAnalysisParametersIncomplete.json | 0 .../SecurityAnalysisParametersInvalid.json | 0 ...curityAnalysisParametersWithExtension.json | 0 .../test/resources/SecurityAnalysisResult.csv | 0 .../resources/SecurityAnalysisResult.json | 135 ++++++++++ .../test/resources/SecurityAnalysisResult.txt | 0 .../resources/SecurityAnalysisResultV1.json | 53 ++-- .../security-analysis-default/pom.xml | 154 +++++++++++ .../impl/DefaultSecurityAnalysis.java | 175 ++++++++----- .../impl/DefaultSecurityAnalysisProvider.java | 52 ++++ .../impl/SecurityAnalysisProviderTest.java | 122 +++++++++ .../security/impl/SecurityAnalysisTest.java | 241 ++++++++++++++++++ .../SecurityAnalysisInterceptorMock.java | 7 +- ...urityAnalysisInterceptorMockExtension.java | 4 +- .../SecurityAnalysisInterceptorTest.java | 45 ++++ .../impl/mocks}/LoadFlowProviderMock.java | 2 +- .../impl/monitors/StateMonitorIndexTest.java | 49 ++++ .../impl/results/BranchResultTest.java | 36 +++ .../security/impl/results/BusResultsTest.java | 33 +++ .../ThreeWindingsTransformerResultTest.java | 41 +++ .../com/powsybl/config/test/config.yml | 2 + .../com/powsybl/config/test/filelist.txt | 1 + 181 files changed, 3281 insertions(+), 1758 deletions(-) create mode 100644 contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContext.java create mode 100644 contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContextType.java create mode 100644 contingency/contingency-api/src/test/java/com/powsybl/contingency/ContingencyContextTest.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/AbstractLimitViolationDetector.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/AbstractSecurityAnalysis.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/DefaultLimitViolationDetector.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/PostContingencyResult.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactories.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactory.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryImpl.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryPluginInfo.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalyzer.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysis.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysis.java delete mode 100644 security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java delete mode 100644 security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultWithLogTest.java delete mode 100644 security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisTest.java delete mode 100644 security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java delete mode 100644 security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorTest.java delete mode 100644 security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisMockFactory.java create mode 100644 security-analysis/pom.xml rename {security-analysis-api => security-analysis/security-analysis-api}/pom.xml (98%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolation.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolationBuilder.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolationDetector.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolationFilter.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolationHelper.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolationType.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolations.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/LimitViolationsResult.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/NetworkMetadata.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/Security.java (97%) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/SecurityAnalysisConfig.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/SecurityAnalysisInput.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/SecurityAnalysisParameters.java (100%) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisProvider.java rename security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultWithLog.java => security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisReport.java (58%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/SecurityAnalysisResult.java (53%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java (77%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java (88%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsTool.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/LimitViolationComparator.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/LimitViolationEquivalence.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/LimitViolationsResultEquivalence.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java (93%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriter.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java (97%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/converter/JsonSecurityAnalysisResultExporter.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporter.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporters.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/detectors/AbstractContingencyBlindDetector.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/detectors/AbstractLimitViolationDetector.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/detectors/DefaultLimitViolationDetector.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/detectors/LoadingLimitType.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/detectors/package-info.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java (71%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysisConfig.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java (72%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptions.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java (92%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java (57%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/SubContingenciesProvider.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/distributed/package-info.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/NetworkVariant.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java (72%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java (79%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java (50%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java (82%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/SecurityAnalysisInputBuildStrategy.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/execution/package-info.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/extensions/ActivePowerExtension.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/extensions/CurrentExtension.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/extensions/VoltageExtension.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java (97%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java (96%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisResultContext.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/RunningContext.java (100%) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorExtension.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptors.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisResultContext.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/ActivePowerExtensionSerializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/CurrentExtensionSerializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/JsonSecurityAnalysisParameters.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/LimitViolationDeserializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/LimitViolationResultDeserializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/LimitViolationSerializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/LimitViolationsResultSerializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/NetworkMetadataDeserializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/NetworkMetadataSerializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java (57%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java (75%) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultDeserializer.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultSerializer.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java (83%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersDeserializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersJsonModule.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersSerializer.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java (74%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java (97%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/json/VoltageExtensionSerializer.java (100%) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitor.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitorIndex.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/preprocessor/ContingenciesProviderPreprocessorFactory.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessor.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorFactory.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessors.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/preprocessor/package-info.java (100%) create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BranchResult.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BusResults.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PostContingencyResult.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PreContingencyResult.java create mode 100644 security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/ThreeWindingsTransformerResult.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java (65%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java (81%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/LimitViolationBuilderTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/LimitViolationFilterTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/LimitViolationTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/NetworkImporterMock.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/SecurityAnalysisConfigTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/SecurityAnalysisInputTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/SecurityAnalysisParametersTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java (85%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java (97%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/SecurityTest.java (99%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/TestingNetworkFactory.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsToolTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/LimitViolationComparatorTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/LimitViolationEquivalenceTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/LimitViolationsResultEquivalenceTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java (96%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriterTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java (99%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/converter/ExporterTest.java (75%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/detectors/DefaultLimitViolationDetectorTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/detectors/LimitViolationDetectorTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java (69%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptionsTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java (85%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/distributed/SubContingenciesProviderTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/execution/NetworkVariantTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java (65%) create mode 100644 security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionInputTest.java (100%) create mode 100644 security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonMonitorTest.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/json/JsonSecurityAnalysisParametersTest.java (100%) create mode 100644 security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/PostContingencyResultTest.java rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorsTest.java (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java (68%) create mode 100644 security-analysis/security-analysis-api/src/test/resources/MonitoringFileTest.json create mode 100644 security-analysis/security-analysis-api/src/test/resources/PostContingencyResultTest.json rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisParameters.json (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisParametersExtensionUpdate.json (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisParametersIncomplete.json (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisParametersInvalid.json (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisParametersWithExtension.json (100%) rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisResult.csv (100%) create mode 100644 security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.json rename {security-analysis-api => security-analysis/security-analysis-api}/src/test/resources/SecurityAnalysisResult.txt (100%) rename security-analysis-api/src/test/resources/SecurityAnalysisResult.json => security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResultV1.json (68%) create mode 100644 security-analysis/security-analysis-default/pom.xml rename security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisImpl.java => security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysis.java (52%) create mode 100644 security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysisProvider.java create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisProviderTest.java create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisTest.java rename {security-analysis-api/src/test/java/com/powsybl/security => security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl}/interceptors/SecurityAnalysisInterceptorMock.java (90%) rename {security-analysis-api/src/test/java/com/powsybl/security => security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl}/interceptors/SecurityAnalysisInterceptorMockExtension.java (79%) create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorTest.java rename {security-analysis-api/src/test/java/com/powsybl/security => security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/mocks}/LoadFlowProviderMock.java (97%) create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/monitors/StateMonitorIndexTest.java create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BranchResultTest.java create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BusResultsTest.java create mode 100644 security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/ThreeWindingsTransformerResultTest.java create mode 100644 security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/config.yml create mode 100644 security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/filelist.txt diff --git a/action/action-simulator/src/main/java/com/powsybl/action/simulator/tools/AbstractSecurityAnalysisResultBuilder.java b/action/action-simulator/src/main/java/com/powsybl/action/simulator/tools/AbstractSecurityAnalysisResultBuilder.java index e6691f49d8d..80001110bc6 100644 --- a/action/action-simulator/src/main/java/com/powsybl/action/simulator/tools/AbstractSecurityAnalysisResultBuilder.java +++ b/action/action-simulator/src/main/java/com/powsybl/action/simulator/tools/AbstractSecurityAnalysisResultBuilder.java @@ -10,6 +10,8 @@ import com.powsybl.action.simulator.loadflow.RunningContext; import com.powsybl.contingency.Contingency; import com.powsybl.security.*; +import com.powsybl.security.results.PostContingencyResult; + import java.util.*; import java.util.stream.Collectors; diff --git a/action/action-simulator/src/test/java/com/powsybl/action/simulator/tools/SecurityAnalysisResultBuilderTest.java b/action/action-simulator/src/test/java/com/powsybl/action/simulator/tools/SecurityAnalysisResultBuilderTest.java index 20fbdf2e082..05280c11787 100644 --- a/action/action-simulator/src/test/java/com/powsybl/action/simulator/tools/SecurityAnalysisResultBuilderTest.java +++ b/action/action-simulator/src/test/java/com/powsybl/action/simulator/tools/SecurityAnalysisResultBuilderTest.java @@ -10,6 +10,7 @@ import com.powsybl.contingency.Contingency; import com.powsybl.iidm.network.Branch; import com.powsybl.security.*; +import com.powsybl.security.results.PostContingencyResult; import org.junit.Test; import java.util.Arrays; @@ -50,7 +51,7 @@ private void testSARBuilder(final boolean convergent) { @Override public void onFinalStateResult(SecurityAnalysisResult result) { - testLimitViolation(result.getPreContingencyResult(), convergent, Collections.singletonList("line1"), Collections.singletonList("pre-action")); + testLimitViolation(result.getPreContingencyLimitViolationsResult(), convergent, Collections.singletonList("line1"), Collections.singletonList("pre-action")); List postContingencyResults = result.getPostContingencyResults(); assertEquals(1, postContingencyResults.size()); diff --git a/contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContext.java b/contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContext.java new file mode 100644 index 00000000000..da1e9e0d137 --- /dev/null +++ b/contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContext.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2021, 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/. + */ + +package com.powsybl.contingency; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * @author Geoffroy Jamgotchian + * @author Etienne Lesot + *

+ * provide the context to get information of the network after a security analysis + * it contains a contingency's id and a context type. Context type defines + * if we want the information in a pre-contingency state, a post-contingency state or both. + * contingency's id is defined if informations are needed after + * a specific contingency computation + */ +public class ContingencyContext { + + private final String contingencyId; + + /** + * Define if informations needed are in N_Situation, N-k Situation or both + * if it is N_situation contingencyid is null + */ + private final ContingencyContextType contextType; + + public ContingencyContext(@JsonProperty("contingencyId") String contingencyId, + @JsonProperty("contextType") ContingencyContextType contingencyContextType) { + this.contextType = Objects.requireNonNull(contingencyContextType); + this.contingencyId = contingencyId; + } + + public String getContingencyId() { + return contingencyId; + } + + public ContingencyContextType getContextType() { + return contextType; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ContingencyContext that = (ContingencyContext) o; + return Objects.equals(contingencyId, that.contingencyId) && + contextType == that.contextType; + } + + @Override + public int hashCode() { + return Objects.hash(contingencyId, contextType); + } + + @Override + public String toString() { + return "ContingencyContext(" + + "contingencyId='" + Objects.toString(contingencyId, "") + '\'' + + ", contextType=" + contextType + + ')'; + } + + public static ContingencyContext all() { + return new ContingencyContext(null, ContingencyContextType.ALL); + } + + public static ContingencyContext none() { + return new ContingencyContext(null, ContingencyContextType.NONE); + } + + public static ContingencyContext specificContingency(String contingencyId) { + return new ContingencyContext(contingencyId, ContingencyContextType.SPECIFIC); + } +} diff --git a/contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContextType.java b/contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContextType.java new file mode 100644 index 00000000000..94765b6d12b --- /dev/null +++ b/contingency/contingency-api/src/main/java/com/powsybl/contingency/ContingencyContextType.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021, 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/. + */ + +package com.powsybl.contingency; + +/** + * @author Geoffroy Jamgotchian + * @author Etienne Lesot + * + * Define for a contingencyContext the type of information asked. + * It can be a pre-contingency state, a post-contingency state on a specific contingency (SPECIFIC) or both (ALL) + */ + +public enum ContingencyContextType { + /** + * Corresponds to all contingencies and pre-contingency situation + */ + ALL, + /** + * Corresponds to pre-contingency situation + */ + NONE, + /** + * Corresponds to one contingency his id is specified in the contingencyContext + */ + SPECIFIC, +} diff --git a/contingency/contingency-api/src/test/java/com/powsybl/contingency/ContingencyContextTest.java b/contingency/contingency-api/src/test/java/com/powsybl/contingency/ContingencyContextTest.java new file mode 100644 index 00000000000..0c1622a40f9 --- /dev/null +++ b/contingency/contingency-api/src/test/java/com/powsybl/contingency/ContingencyContextTest.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.contingency; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Geoffroy Jamgotchian + */ +public class ContingencyContextTest { + + @Test + public void test() { + ContingencyContext context = new ContingencyContext("c1", ContingencyContextType.SPECIFIC); + assertEquals("ContingencyContext(contingencyId='c1', contextType=SPECIFIC)", context.toString()); + } +} diff --git a/distribution-core/pom.xml b/distribution-core/pom.xml index e9c34cdcdc7..08bcbc090ec 100644 --- a/distribution-core/pom.xml +++ b/distribution-core/pom.xml @@ -326,6 +326,13 @@ ${project.version} + + ${project.groupId} + powsybl-security-analysis-default + ${project.version} + runtime + + ${project.groupId} powsybl-sensitivity-analysis-api diff --git a/pom.xml b/pom.xml index ed4d4f4ed14..346ddd4c5aa 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ matpower psse scripting - security-analysis-api + security-analysis sensitivity-analysis-api time-series tools diff --git a/security-analysis-api/src/main/java/com/powsybl/security/AbstractLimitViolationDetector.java b/security-analysis-api/src/main/java/com/powsybl/security/AbstractLimitViolationDetector.java deleted file mode 100644 index b39eee4409f..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/AbstractLimitViolationDetector.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security; - -/** - * Provides implementations for aggregation methods of {@link LimitViolationDetector}. - * Actual implementations will only have to focus on detecting violations element-wise. - * - * @deprecated Moved to package {@link com.powsybl.security.detectors}. - * @author Sylvain Leclerc - */ -@Deprecated -public abstract class AbstractLimitViolationDetector extends com.powsybl.security.detectors.AbstractLimitViolationDetector { - -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/AbstractSecurityAnalysis.java b/security-analysis-api/src/main/java/com/powsybl/security/AbstractSecurityAnalysis.java deleted file mode 100644 index e43510949de..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/AbstractSecurityAnalysis.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security; - -import com.powsybl.iidm.network.Network; -import com.powsybl.security.detectors.DefaultLimitViolationDetector; -import com.powsybl.security.detectors.LoadingLimitType; -import com.powsybl.security.interceptors.RunningContext; -import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Objects; - -/** - * - * Implements some common methods of interface {@link SecurityAnalysis}, - * and provides a {@link SecurityAnalysisResultBuilder} to ease creation of results. - * - * @author Teofil Calin BANC - */ -public abstract class AbstractSecurityAnalysis implements SecurityAnalysis { - - protected final Network network; - protected final LimitViolationDetector violationDetector; - protected final LimitViolationFilter violationFilter; - - protected final List interceptors; - - protected AbstractSecurityAnalysis(Network network, LimitViolationFilter violationFilter) { - this(network, new DefaultLimitViolationDetector(EnumSet.allOf(LoadingLimitType.class)), violationFilter); - } - - protected AbstractSecurityAnalysis(Network network, LimitViolationDetector detector, LimitViolationFilter filter) { - this.network = Objects.requireNonNull(network); - this.violationDetector = Objects.requireNonNull(detector); - this.violationFilter = Objects.requireNonNull(filter); - this.interceptors = new ArrayList<>(); - } - - @Override - public void addInterceptor(SecurityAnalysisInterceptor interceptor) { - interceptors.add(Objects.requireNonNull(interceptor)); - } - - @Override - public boolean removeInterceptor(SecurityAnalysisInterceptor interceptor) { - return interceptors.remove(interceptor); - } - - protected SecurityAnalysisResultBuilder createResultBuilder(String initialWorkingStateId) { - return new SecurityAnalysisResultBuilder(violationFilter, new RunningContext(network, initialWorkingStateId), interceptors); - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/DefaultLimitViolationDetector.java b/security-analysis-api/src/main/java/com/powsybl/security/DefaultLimitViolationDetector.java deleted file mode 100644 index 24570d2d5e0..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/DefaultLimitViolationDetector.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security; - -/** - * Implements the default behaviour for limit violation detection. - * - * @deprecated moved to package {@link com.powsybl.security.detectors}. - * @author Sylvain Leclerc - */ -@Deprecated -public class DefaultLimitViolationDetector extends com.powsybl.security.detectors.DefaultLimitViolationDetector { - -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/PostContingencyResult.java b/security-analysis-api/src/main/java/com/powsybl/security/PostContingencyResult.java deleted file mode 100644 index 5419abe4f2e..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/PostContingencyResult.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2016-2017, 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/. - */ -package com.powsybl.security; - -import com.powsybl.contingency.Contingency; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * @author Geoffroy Jamgotchian - * @author Mathieu Bague - */ -public class PostContingencyResult { - - private final Contingency contingency; - - private final LimitViolationsResult limitViolationsResult; - - public PostContingencyResult(Contingency contingency, LimitViolationsResult limitViolationsResult) { - this.contingency = Objects.requireNonNull(contingency); - this.limitViolationsResult = Objects.requireNonNull(limitViolationsResult); - } - - public PostContingencyResult(Contingency contingency, boolean computationOk, List limitViolations) { - this(contingency, new LimitViolationsResult(computationOk, limitViolations, Collections.emptyList())); - } - - public PostContingencyResult(Contingency contingency, boolean computationOk, List limitViolations, List actionsTaken) { - this(contingency, new LimitViolationsResult(computationOk, limitViolations, actionsTaken)); - } - - public Contingency getContingency() { - return contingency; - } - - public LimitViolationsResult getLimitViolationsResult() { - return limitViolationsResult; - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java b/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java deleted file mode 100644 index 51337fe2b1c..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) 2016-2018, 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/. - */ -package com.powsybl.security; - -import com.powsybl.contingency.ContingenciesProvider; -import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; - -import java.util.concurrent.CompletableFuture; - -/** - * - * A {@link SecurityAnalysis} is a power system computation which computes, for a {@link com.powsybl.iidm.network.Network Network}, - * the {@link LimitViolation LimitViolations} on N-situation - * and the ones caused by a specified list of {@link com.powsybl.contingency.Contingency Contingencies}. - * - *

Computation results are provided asynchronously as a {@link SecurityAnalysisResult}. - * - *

Implementations of that interface may typically rely on an external tool. - * - *

{@link SecurityAnalysisInterceptor Interceptors} might be used to execute client user-specific code - * on events such as the availability of N-situation results, for example to further customize the results content - * through {@link com.powsybl.commons.extensions.Extension Extensions}. - * - * @author Geoffroy Jamgotchian - * @author Teofil Calin BANC - */ -public interface SecurityAnalysis { - - void addInterceptor(SecurityAnalysisInterceptor interceptor); - - boolean removeInterceptor(SecurityAnalysisInterceptor interceptor); - - CompletableFuture run(String workingVariantId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider); - - /** - * To be consistent with {@link #run(String, SecurityAnalysisParameters, ContingenciesProvider)}, this method would also complete exceptionally - * if there are exceptions thrown. But the original exception would be wrapped in {@link com.powsybl.computation.ComputationException}, and those .out/.err log file's contents - * are be collected in the {@link com.powsybl.computation.ComputationException} too. - * - * - *

 {@code
-     * try {
-     *       SecurityAnalysisResultWithLog resultWithLog = securityAnalysis.runWithLog(currentState, parameters, contingenciesProvider).join();
-     *       result = resultWithLog.getResult();
-     *   } catch (CompletionException e) {
-     *       if (e.getCause() instanceof ComputationException) {
-     *           ComputationException computationException = (ComputationException) e.getCause();
-     *           System.out.println("Consume exception...");
-     *           computationException.getOutLogs().forEach((name, content) -> {
-     *               System.out.println("-----" + name + "----");
-     *               System.out.println(content);
-     *           });
-     *           computationException.getErrLogs().forEach((name, content) -> {
-     *               System.out.println("-----" + name + "----");
-     *               System.out.println(content);
-     *           });
-     *       }
-     *       throw e;
-     *   }
-     * }
- * @param workingVariantId - * @param parameters - * @param contingenciesProvider - * @return - */ - default CompletableFuture runWithLog(String workingVariantId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider) { - return run(workingVariantId, parameters, contingenciesProvider).thenApply(r -> new SecurityAnalysisResultWithLog(r, null)); - } - -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactories.java b/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactories.java deleted file mode 100644 index ca30751ca8c..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactories.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security; - -import com.powsybl.commons.config.ComponentDefaultConfig; -import com.powsybl.commons.config.PlatformConfig; - -/** - * @author Sylvain Leclerc - */ -public final class SecurityAnalysisFactories { - - private SecurityAnalysisFactories() { - } - - /** - * Returns a factory as defined in the {@link ComponentDefaultConfig}. - */ - public static SecurityAnalysisFactory newDefaultFactory() { - return newDefaultFactory(PlatformConfig.defaultConfig()); - } - - /** - * Returns a factory as defined in the {@link ComponentDefaultConfig}. - */ - public static SecurityAnalysisFactory newDefaultFactory(PlatformConfig platformConfig) { - return ComponentDefaultConfig.load(platformConfig).newFactoryImpl(SecurityAnalysisFactory.class); - } - -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactory.java b/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactory.java deleted file mode 100644 index fda76393142..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactory.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2016, 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/. - */ -package com.powsybl.security; - -import com.powsybl.computation.ComputationManager; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.detectors.DefaultLimitViolationDetector; - -/** - * - * TODO: deprecate priority parameter - * - * @author Geoffroy Jamgotchian - */ -public interface SecurityAnalysisFactory { - - /** - * Creates a {@link SecurityAnalysis} for specified {@link Network}, - * using specified {@link ComputationManager} to handle computations. - * Limit violations should be detected using {@link DefaultLimitViolationDetector}, - * and then filtered using a default {@link LimitViolationFilter}. - * - * @param network The network for which computation will be performed. - * @param computationManager The computation manager to use to handle computations - * @return The created security analysis. - */ - SecurityAnalysis create(Network network, ComputationManager computationManager, int priority); - - /** - * Creates a {@link SecurityAnalysis} for specified {@link Network}, - * using specified {@link ComputationManager} to handle computations. - * Limit violations should be detected using {@link DefaultLimitViolationDetector}, - * and then filtered using the specified {@link LimitViolationFilter}. - * - * @param network The network for which computation will be performed. - * @param computationManager The computation manager to use to handle computations - * @param filter A filter to filter out unwanted limit violations. - * @return The created security analysis. - */ - default SecurityAnalysis create(Network network, LimitViolationFilter filter, ComputationManager computationManager, int priority) { - return create(network, computationManager, priority); - } - - /** - * Creates a {@link SecurityAnalysis} for specified {@link Network}, - * using specified {@link ComputationManager} to handle computations. - * Limit violations will be detected using the specified {@link LimitViolationDetector}, - * and then filtered using the specified {@link LimitViolationFilter}. - * - * @param network The network for which computation will be performed. - * @param detector The detector used to evaluate the occurence of limit violations. - * @param filter A filter to filter out unwanted limit violations. - * @param computationManager The computation manager to use to handle computations - * @return The created security analysis. - */ - default SecurityAnalysis create(Network network, LimitViolationDetector detector, LimitViolationFilter filter, - ComputationManager computationManager, int priority) { - return create(network, filter, computationManager, priority); - } - -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryImpl.java b/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryImpl.java deleted file mode 100644 index b91e6b8e985..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2016, 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/. - */ -package com.powsybl.security; - -import com.google.auto.service.AutoService; -import com.powsybl.computation.ComputationManager; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.detectors.DefaultLimitViolationDetector; - -/** - * @author Geoffroy Jamgotchian - */ -@AutoService(SecurityAnalysisFactory.class) -public class SecurityAnalysisFactoryImpl implements SecurityAnalysisFactory { - - @Override - public SecurityAnalysis create(Network network, ComputationManager computationManager, int priority) { - return create(network, new LimitViolationFilter(), computationManager, priority); - } - - @Override - public SecurityAnalysis create(Network network, LimitViolationFilter filter, ComputationManager computationManager, int priority) { - return create(network, new DefaultLimitViolationDetector(), filter, computationManager, priority); - } - - @Override - public SecurityAnalysis create(Network network, LimitViolationDetector detector, LimitViolationFilter filter, - ComputationManager computationManager, int priority) { - return new SecurityAnalysisImpl(network, detector, filter, computationManager); - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryPluginInfo.java b/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryPluginInfo.java deleted file mode 100644 index 09c3e30c398..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisFactoryPluginInfo.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security; - -import com.google.auto.service.AutoService; -import com.powsybl.commons.plugins.PluginInfo; - -@AutoService(PluginInfo.class) -public class SecurityAnalysisFactoryPluginInfo extends PluginInfo { - - public SecurityAnalysisFactoryPluginInfo() { - super(SecurityAnalysisFactory.class); - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalyzer.java b/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalyzer.java deleted file mode 100644 index 439fe2aeaf8..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalyzer.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright (c) 2016-2018, 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/. - */ -package com.powsybl.security; - -import com.powsybl.commons.PowsyblException; -import com.powsybl.commons.config.ComponentDefaultConfig; -import com.powsybl.computation.ComputationManager; -import com.powsybl.contingency.ContingenciesProvider; -import com.powsybl.contingency.ContingenciesProviderFactory; -import com.powsybl.contingency.EmptyContingencyListProvider; -import com.powsybl.iidm.import_.Importers; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; - -import java.io.InputStream; -import java.nio.file.Path; -import java.util.Collections; -import java.util.Objects; -import java.util.Set; - -/** - * @author Giovanni Ferrari - * @author Teofil Calin BANC - */ -public class SecurityAnalyzer { - - private final LimitViolationFilter filter; - - private final ComputationManager computationManager; - - private final int priority; - - private final SecurityAnalysisFactory securityAnalysisFactory; - - private final ContingenciesProviderFactory contingenciesProviderFactory; - - private final Set interceptors; - - public SecurityAnalyzer(LimitViolationFilter filter, ComputationManager computationManager, int priority) { - this(filter, computationManager, priority, Collections.emptySet()); - } - - public SecurityAnalyzer(LimitViolationFilter filter, ComputationManager computationManager, int priority, Set interceptors) { - this.filter = Objects.requireNonNull(filter); - this.computationManager = Objects.requireNonNull(computationManager); - this.priority = priority; - this.interceptors = Objects.requireNonNull(interceptors); - - ComponentDefaultConfig defaultConfig = ComponentDefaultConfig.load(); - securityAnalysisFactory = defaultConfig.newFactoryImpl(SecurityAnalysisFactory.class); - contingenciesProviderFactory = defaultConfig.newFactoryImpl(ContingenciesProviderFactory.class); - } - - public SecurityAnalysisResult analyze(Network network, Path contingenciesFile) { - return analyze(network, contingenciesFile, SecurityAnalysisParameters.load()); - } - - public SecurityAnalysisResult analyze(Network network, Path contingenciesFile, SecurityAnalysisParameters parameters) { - Objects.requireNonNull(network); - - ContingenciesProvider contingenciesProvider = contingenciesFile != null - ? contingenciesProviderFactory.create(contingenciesFile) : new EmptyContingencyListProvider(); - - return analyze(network, contingenciesProvider, parameters); - } - - public SecurityAnalysisResult analyze(String filename, InputStream networkData, InputStream contingencies) { - return analyze(filename, networkData, contingencies, SecurityAnalysisParameters.load()); - } - - public SecurityAnalysisResult analyze(String filename, InputStream networkData, InputStream contingencies, SecurityAnalysisParameters parameters) { - Objects.requireNonNull(networkData); - Objects.requireNonNull(filename); - - Network network = Importers.loadNetwork(filename, networkData); - if (network == null) { - throw new PowsyblException("Error loading network"); - } - - ContingenciesProvider contingenciesProvider = contingencies != null - ? contingenciesProviderFactory.create(contingencies) : new EmptyContingencyListProvider(); - - return analyze(network, contingenciesProvider, parameters); - } - - public SecurityAnalysisResult analyze(Network network, ContingenciesProvider contingenciesProvider) { - return analyze(network, contingenciesProvider, SecurityAnalysisParameters.load()); - } - - public SecurityAnalysisResult analyze(Network network, ContingenciesProvider contingenciesProvider, SecurityAnalysisParameters parameters) { - Objects.requireNonNull(network); - Objects.requireNonNull(contingenciesProvider); - Objects.requireNonNull(parameters); - - network.getVariantManager().allowVariantMultiThreadAccess(true); - - SecurityAnalysis securityAnalysis = securityAnalysisFactory.create(network, filter, computationManager, priority); - interceptors.forEach(securityAnalysis::addInterceptor); - - return securityAnalysis.run(network.getVariantManager().getWorkingVariantId(), parameters, contingenciesProvider).join(); - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysis.java b/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysis.java deleted file mode 100644 index 4d208a80ff1..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysis.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security.distributed; - -import com.powsybl.computation.*; -import com.powsybl.contingency.ContingenciesProvider; -import com.powsybl.contingency.Contingency; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.SecurityAnalysisParameters; -import com.powsybl.security.SecurityAnalysisResult; -import com.powsybl.security.SecurityAnalysisResultWithLog; -import com.powsybl.security.execution.SecurityAnalysisExecutionInput; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -/** - * Security analysis implementation which distributes the work through X - * executions of the "itools security-analysis" command. - * - * @deprecated Use instead {@link DistributedSecurityAnalysisExecution}, which clarifies the input data for that kind - * of execution, and tries to differentiate more between a {@link com.powsybl.security.SecurityAnalysis} - * and its mode of execution. - * - * @author Sylvain Leclerc - */ -@Deprecated -public class DistributedSecurityAnalysis extends ExternalSecurityAnalysis { - - private static final Logger LOGGER = LoggerFactory.getLogger(DistributedSecurityAnalysis.class); - - public DistributedSecurityAnalysis(ExternalSecurityAnalysisConfig config, Network network, - ComputationManager computationManager, List extensions, int taskCount) { - super(config, network, computationManager, extensions, taskCount); - } - - @Override - public CompletableFuture run(String workingVariantId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider) { - LOGGER.debug("Starting distributed security analysis."); - - ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_task_", config.isDebug()); - - SecurityAnalysisExecutionInput input = buildInput(workingVariantId, parameters, contingenciesProvider); - - List contingencies = contingenciesProvider.getContingencies(network); - int actualTaskCount = Math.min(taskCount, Math.max(1, contingencies.size())); - return computationManager.execute(itoolsEnv, - SecurityAnalysisExecutionHandlers.distributed(input, actualTaskCount)); - } - - @Override - public CompletableFuture runWithLog(String workingVariantId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider) { - LOGGER.debug("Starting distributed security analysis(with log)."); - - ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_task_", config.isDebug()); - - SecurityAnalysisExecutionInput input = buildInput(workingVariantId, parameters, contingenciesProvider); - - List contingencies = contingenciesProvider.getContingencies(network); - int actualTaskCount = Math.min(taskCount, Math.max(1, contingencies.size())); - return computationManager.execute(itoolsEnv, - SecurityAnalysisExecutionHandlers.distributedWithLog(input, actualTaskCount)); - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysis.java b/security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysis.java deleted file mode 100644 index ee63ba09e84..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysis.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security.distributed; - -import com.google.common.io.ByteSource; -import com.powsybl.computation.ComputationManager; -import com.powsybl.computation.ExecutionEnvironment; -import com.powsybl.contingency.ContingenciesProvider; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.SecurityAnalysis; -import com.powsybl.security.SecurityAnalysisParameters; -import com.powsybl.security.SecurityAnalysisResult; -import com.powsybl.security.execution.SecurityAnalysisExecutionInput; -import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import static java.util.Objects.requireNonNull; - -/** - * Submits execution of an "itools security-analysis" command to the ComputationManager, - * for example to remotely execute the security-analysis. - * - * @deprecated Use instead {@link ForwardedSecurityAnalysisExecution}, which clarifies the input data for that kind - * of execution, and tries to differentiate more between a {@link com.powsybl.security.SecurityAnalysis} - * and its mode of execution. - * - * @author Sylvain Leclerc - * @author Teofil Calin BANC - */ -@Deprecated -public class ExternalSecurityAnalysis implements SecurityAnalysis { - - private static final Logger LOGGER = LoggerFactory.getLogger(ExternalSecurityAnalysis.class); - - protected final ExternalSecurityAnalysisConfig config; - protected final Network network; - protected final ComputationManager computationManager; - protected final List extensions; - protected final Integer taskCount; - - public ExternalSecurityAnalysis(ExternalSecurityAnalysisConfig config, Network network, - ComputationManager computationManager, List extensions) { - this(config, network, computationManager, extensions, null); - } - - private ExternalSecurityAnalysis(ExternalSecurityAnalysisConfig config, Network network, - ComputationManager computationManager, List extensions, Integer taskCount) { - this.config = requireNonNull(config); - this.network = requireNonNull(network); - this.computationManager = requireNonNull(computationManager); - this.extensions = new ArrayList<>(requireNonNull(extensions)); - this.taskCount = taskCount; - } - - public ExternalSecurityAnalysis(ExternalSecurityAnalysisConfig config, Network network, - ComputationManager computationManager, List extensions, int taskCount) { - this(config, network, computationManager, extensions, Integer.valueOf(taskCount)); - } - - @Override - public void addInterceptor(SecurityAnalysisInterceptor interceptor) { - throw new UnsupportedOperationException("External security analysis does not support interceptors. Use extension names instead."); - } - - @Override - public boolean removeInterceptor(SecurityAnalysisInterceptor interceptor) { - throw new UnsupportedOperationException("External security analysis does not support interceptors."); - } - - @Override - public CompletableFuture run(String workingStateId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider) { - LOGGER.debug("Starting external security analysis."); - - ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_", config.isDebug()); - SecurityAnalysisExecutionInput input = buildInput(workingStateId, parameters, contingenciesProvider); - return computationManager.execute(itoolsEnv, SecurityAnalysisExecutionHandlers.forwarded(input, taskCount)); - } - - protected SecurityAnalysisExecutionInput buildInput(String workingStateId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider) { - return new SecurityAnalysisExecutionInput() - .setNetworkVariant(network, workingStateId) - .setParameters(parameters) - .setContingenciesSource(ByteSource.wrap(contingenciesProvider.asScript().getBytes(StandardCharsets.UTF_8))) - .addResultExtensions(extensions); - } -} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java b/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java deleted file mode 100644 index a8ead30100c..00000000000 --- a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (c) 2017, 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/. - */ -package com.powsybl.security.interceptors; - -import com.powsybl.contingency.Contingency; -import com.powsybl.security.LimitViolation; -import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.PostContingencyResult; -import com.powsybl.security.SecurityAnalysisResult; - -/** - * - * Security analysis interceptors are notified at various steps of the construction of - * the {@link SecurityAnalysisResult}, for instance when adding new {@link LimitViolation limit violations}. - * This mechanism allows for example users of the {@link com.powsybl.security.SecurityAnalysis} to add - * additional information in the result, as {@link com.powsybl.commons.extensions.Extension extensions}. - * - *

Some of this information can be retrieved from the provided {@link SecurityAnalysisResultContext}. - * Implementations of the security analysis can provide implementation-specific information by providing - * their own implementation of this context. - * - *

Note that the contexts provided to the various methods can be different objects, in order - * to provide more specific information, for example for violations or contingencies. - * This can also be helpful to guarantee thread safety, if the result builder is used concurrently. - * - * - * @author Mathieu Bague - */ -public interface SecurityAnalysisInterceptor { - - /** - * @deprecated Use {@link #onPreContingencyResult(LimitViolationsResult, SecurityAnalysisResultContext)} - * Callback after the pre-contingency analysis result is created - * @param context The running context - * @param preContingencyResult - */ - @Deprecated - default void onPreContingencyResult(RunningContext context, LimitViolationsResult preContingencyResult) { - onPreContingencyResult(preContingencyResult, context); - } - - /** - * @deprecated Use {@link #onPostContingencyResult(PostContingencyResult, SecurityAnalysisResultContext)} - * @param context - * @param postContingencyResult - */ - @Deprecated - default void onPostContingencyResult(RunningContext context, PostContingencyResult postContingencyResult) { - onPostContingencyResult(postContingencyResult, context); - } - - /** - * @deprecated Use {@link #onSecurityAnalysisResult(SecurityAnalysisResult, SecurityAnalysisResultContext)} - * Callback after the result is created - * @param context - * @param result - */ - @Deprecated - default void onSecurityAnalysisResult(RunningContext context, SecurityAnalysisResult result) { - onSecurityAnalysisResult(result, context); - } - - /** - * Callback after the pre-contingency result is built. - * @param preContingencyResult - * @param context - */ - default void onPreContingencyResult(LimitViolationsResult preContingencyResult, SecurityAnalysisResultContext context) { - if (context instanceof RunningContext) { - onPreContingencyResult((RunningContext) context, preContingencyResult); - } - } - - /** - * Callback after the post-contingency result is built. - * @param context - * @param postContingencyResult - */ - default void onPostContingencyResult(PostContingencyResult postContingencyResult, SecurityAnalysisResultContext context) { - if (context instanceof RunningContext) { - onPostContingencyResult((RunningContext) context, postContingencyResult); - } - } - - /** - * Callback after the security-analysis result is built. - * @param result - * @param context - */ - default void onSecurityAnalysisResult(SecurityAnalysisResult result, SecurityAnalysisResultContext context) { - if (context instanceof RunningContext) { - onSecurityAnalysisResult((RunningContext) context, result); - } - } - - /** - * Callback when a violation is detected on N situation. - * @param limitViolation - * @param context - */ - default void onLimitViolation(LimitViolation limitViolation, SecurityAnalysisResultContext context) { - - } - - /** - * Callback when a violation is detected on N-1 situation. - * @param contingency - * @param limitViolation - * @param context - */ - default void onLimitViolation(Contingency contingency, LimitViolation limitViolation, SecurityAnalysisResultContext context) { - - } - -} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultWithLogTest.java b/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultWithLogTest.java deleted file mode 100644 index af7c8cdc58a..00000000000 --- a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultWithLogTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2019, 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/. - */ -package com.powsybl.security; - -import org.junit.Test; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; - -/** - * @author Yichen TANG - */ -public class SecurityAnalysisResultWithLogTest { - - @Test - public void baseTest() { - SecurityAnalysisResult sar = mock(SecurityAnalysisResult.class); - SecurityAnalysisResultWithLog sut = new SecurityAnalysisResultWithLog(sar); - assertSame(sar, sut.getResult()); - assertFalse(sut.getLogBytes().isPresent()); - byte[] logs = new byte[10]; - SecurityAnalysisResultWithLog sut1 = new SecurityAnalysisResultWithLog(sar, logs); - assertSame(logs, sut1.getLogBytes().orElse(new byte[1])); - try { - new SecurityAnalysisResultWithLog(null); - fail(); - } catch (NullPointerException e) { - // ignored - } - } -} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisTest.java b/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisTest.java deleted file mode 100644 index d0659b1a9ce..00000000000 --- a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright (c) 2017-2018, 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/. - */ -package com.powsybl.security; - -import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Jimfs; -import com.powsybl.commons.config.InMemoryPlatformConfig; -import com.powsybl.commons.config.PlatformConfig; -import com.powsybl.computation.ComputationManager; -import com.powsybl.computation.ComputationResourcesStatus; -import com.powsybl.contingency.ContingenciesProvider; -import com.powsybl.contingency.Contingency; -import com.powsybl.iidm.network.Bus; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.VariantManagerConstants; -import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; -import com.powsybl.security.extensions.ActivePowerExtension; -import com.powsybl.security.extensions.CurrentExtension; -import com.powsybl.security.interceptors.CurrentLimitViolationInterceptor; -import com.powsybl.security.interceptors.SecurityAnalysisInterceptorMock; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.io.IOException; -import java.nio.file.FileSystem; -import java.util.Collections; -import java.util.concurrent.Executor; - -import static org.junit.Assert.*; - -/** - * - * @author Massimo Ferraro - * @author Teofil Calin BANC - */ -public class SecurityAnalysisTest { - - private FileSystem fileSystem; - - private PlatformConfig platformConfig; - - @Before - public void setUp() { - fileSystem = Jimfs.newFileSystem(Configuration.unix()); - platformConfig = new InMemoryPlatformConfig(fileSystem); - } - - @After - public void tearDown() throws IOException { - fileSystem.close(); - } - - @Test - public void run() { - Network network = EurostagTutorialExample1Factory.create(); - ((Bus) network.getIdentifiable("NHV1")).setV(380.0); - ((Bus) network.getIdentifiable("NHV2")).setV(380.0); - network.getLine("NHV1_NHV2_1").getTerminal1().setP(560.0).setQ(550.0); - network.getLine("NHV1_NHV2_1").getTerminal2().setP(560.0).setQ(550.0); - network.getLine("NHV1_NHV2_1").newCurrentLimits1().setPermanentLimit(1500.0).add(); - network.getLine("NHV1_NHV2_1").newCurrentLimits2() - .setPermanentLimit(1200.0) - .beginTemporaryLimit() - .setName("10'") - .setAcceptableDuration(10 * 60) - .setValue(1300.0) - .endTemporaryLimit() - .add(); - - ComputationManager computationManager = createMockComputationManager(); - - Contingency contingency = Contingency.builder("NHV1_NHV2_2_contingency") - .addBranch("NHV1_NHV2_2") - .build(); - contingency = Mockito.spy(contingency); - Mockito.when(contingency.toTask()).thenReturn((network1, computationManager1) -> { - network1.getLine("NHV1_NHV2_2").getTerminal1().disconnect(); - network1.getLine("NHV1_NHV2_2").getTerminal2().disconnect(); - network1.getLine("NHV1_NHV2_1").getTerminal2().setP(600.0); - }); - ContingenciesProvider contingenciesProvider = Mockito.mock(ContingenciesProvider.class); - Mockito.when(contingenciesProvider.getContingencies(network)).thenReturn(Collections.singletonList(contingency)); - - LimitViolationFilter filter = new LimitViolationFilter(); - - SecurityAnalysis securityAnalysis = new SecurityAnalysisImpl(network, filter, computationManager); - SecurityAnalysisInterceptorMock interceptorMock = new SecurityAnalysisInterceptorMock(); - securityAnalysis.addInterceptor(interceptorMock); - securityAnalysis.addInterceptor(new CurrentLimitViolationInterceptor()); - - SecurityAnalysisResult result = securityAnalysis.run(VariantManagerConstants.INITIAL_VARIANT_ID, SecurityAnalysisParameters.load(platformConfig), contingenciesProvider).join(); - - assertTrue(result.getPreContingencyResult().isComputationOk()); - assertEquals(0, result.getPreContingencyResult().getLimitViolations().size()); - PostContingencyResult postcontingencyResult = result.getPostContingencyResults().get(0); - assertTrue(postcontingencyResult.getLimitViolationsResult().isComputationOk()); - assertEquals(1, postcontingencyResult.getLimitViolationsResult().getLimitViolations().size()); - LimitViolation violation = postcontingencyResult.getLimitViolationsResult().getLimitViolations().get(0); - assertEquals(LimitViolationType.CURRENT, violation.getLimitType()); - assertEquals("NHV1_NHV2_1", violation.getSubjectId()); - - ActivePowerExtension extension1 = violation.getExtension(ActivePowerExtension.class); - assertNotNull(extension1); - assertEquals(560.0, extension1.getPreContingencyValue(), 0.0); - assertEquals(600.0, extension1.getPostContingencyValue(), 0.0); - - CurrentExtension extension2 = violation.getExtension(CurrentExtension.class); - assertNotNull(extension2); - assertEquals(1192.5631358010583, extension2.getPreContingencyValue(), 0.0); - - assertEquals(1, interceptorMock.getOnPostContingencyResultCount()); - assertEquals(1, interceptorMock.getOnPreContingencyResultCount()); - assertEquals(1, interceptorMock.getOnSecurityAnalysisResultCount()); - } - - @Test - public void runWithoutContingency() { - Network network = EurostagTutorialExample1Factory.create(); - ComputationManager computationManager = createMockComputationManager(); - - ContingenciesProvider contingenciesProvider = Mockito.mock(ContingenciesProvider.class); - Mockito.when(contingenciesProvider.getContingencies(network)).thenReturn(Collections.emptyList()); - LimitViolationFilter filter = new LimitViolationFilter(); - - SecurityAnalysis securityAnalysis = new SecurityAnalysisImpl(network, filter, computationManager); - SecurityAnalysisInterceptorMock interceptorMock = new SecurityAnalysisInterceptorMock(); - securityAnalysis.addInterceptor(interceptorMock); - securityAnalysis.addInterceptor(new CurrentLimitViolationInterceptor()); - - SecurityAnalysisResult result = securityAnalysis.run(VariantManagerConstants.INITIAL_VARIANT_ID, SecurityAnalysisParameters.load(platformConfig), contingenciesProvider).join(); - - assertTrue(result.getPreContingencyResult().isComputationOk()); - assertEquals(0, result.getPreContingencyResult().getLimitViolations().size()); - assertEquals(0, result.getPostContingencyResults().size()); - - assertEquals(0, interceptorMock.getOnPostContingencyResultCount()); - assertEquals(1, interceptorMock.getOnPreContingencyResultCount()); - assertEquals(1, interceptorMock.getOnSecurityAnalysisResultCount()); - } - - private static ComputationManager createMockComputationManager() { - ComputationManager computationManager = Mockito.mock(ComputationManager.class); - Executor executor = Runnable::run; - Mockito.when(computationManager.getExecutor()).thenReturn(executor); - ComputationResourcesStatus computationResourcesStatus = Mockito.mock(ComputationResourcesStatus.class); - Mockito.when(computationResourcesStatus.getAvailableCores()).thenReturn(4); - Mockito.when(computationManager.getResourcesStatus()).thenReturn(computationResourcesStatus); - return computationManager; - } -} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java b/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java deleted file mode 100644 index 4a2f85b6227..00000000000 --- a/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security.execution; - -import com.powsybl.computation.ComputationManager; -import com.powsybl.contingency.ContingenciesProvider; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.*; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import static org.mockito.Mockito.*; - -/** - * @author Sylvain Leclerc - */ -public class SecurityAnalysisExecutionImplTest { - - private SecurityAnalysis analysis; - private SecurityAnalysisFactory factory; - - private LimitViolationFilter filter; - private LimitViolationDetector detector; - private ContingenciesProvider contingencies; - private SecurityAnalysisParameters parameters; - private SecurityAnalysisExecution execution; - private Network network; - private ComputationManager computationManager; - private SecurityAnalysisExecutionInput input; - - @Before - public void setUp() { - analysis = mock(SecurityAnalysis.class); - factory = mock(SecurityAnalysisFactory.class); - when(factory.create(any(), any(), any(), any(), anyInt())) - .thenReturn(analysis); - - filter = Mockito.mock(LimitViolationFilter.class); - detector = Mockito.mock(LimitViolationDetector.class); - contingencies = Mockito.mock(ContingenciesProvider.class); - parameters = Mockito.mock(SecurityAnalysisParameters.class); - - execution = new SecurityAnalysisExecutionImpl(factory, - execInput -> new SecurityAnalysisInput(execInput.getNetworkVariant()) - .setFilter(filter) - .setDetector(detector) - .setContingencies(contingencies) - .setParameters(parameters) - ); - - network = mock(Network.class); - computationManager = mock(ComputationManager.class); - input = new SecurityAnalysisExecutionInput(); - input.setNetworkVariant(network, "variantId"); - } - - @Test - public void checkExecutionCallAndArguments() { - - execution.execute(computationManager, input); - - Mockito.verify(factory, Mockito.times(1)) - .create(same(network), same(detector), same(filter), same(computationManager), anyInt()); - Mockito.verify(analysis, Mockito.times(1)) - .run(eq("variantId"), same(parameters), same(contingencies)); - } - - @Test - public void checkExecutionWithLogCallAndArguments() { - - execution.executeWithLog(computationManager, input); - Mockito.verify(factory, Mockito.times(1)) - .create(same(network), same(detector), same(filter), same(computationManager), anyInt()); - Mockito.verify(analysis, Mockito.times(1)) - .runWithLog(eq("variantId"), same(parameters), same(contingencies)); - } -} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorTest.java b/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorTest.java deleted file mode 100644 index 601478c97dd..00000000000 --- a/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2018, 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/. - */ -package com.powsybl.security.interceptors; - -import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.PostContingencyResult; -import com.powsybl.security.SecurityAnalysisResult; -import org.junit.Test; - -import java.util.Collections; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; - -/** - * @author Mathieu Bague - */ -public class SecurityAnalysisInterceptorTest { - - @Test - public void test() { - assertEquals(Collections.singleton("SecurityAnalysisInterceptorMock"), SecurityAnalysisInterceptors.getExtensionNames()); - - SecurityAnalysisInterceptor interceptor = SecurityAnalysisInterceptors.createInterceptor("SecurityAnalysisInterceptorMock"); - assertNotNull(interceptor); - assertEquals(SecurityAnalysisInterceptorMock.class, interceptor.getClass()); - - try { - interceptor = SecurityAnalysisInterceptors.createInterceptor(null); - fail(); - } catch (NullPointerException e) { - // Nothing to do - } - - try { - interceptor = SecurityAnalysisInterceptors.createInterceptor("unknown-security-analysis-interceptor"); - fail(); - } catch (IllegalArgumentException e) { - // Nothing to do - } - } - - @Test - public void testDefaultNewApi() { - RunningContext runningContext = mock(RunningContext.class); - LimitViolationsResult preRes = mock(LimitViolationsResult.class); - PostContingencyResult postRes = mock(PostContingencyResult.class); - SecurityAnalysisResult allRes = mock(SecurityAnalysisResult.class); - OldInterceptor oldInterceptor = new OldInterceptor(runningContext, preRes, postRes, allRes); - oldInterceptor.onPreContingencyResult(preRes, runningContext); - oldInterceptor.onPostContingencyResult(postRes, runningContext); - oldInterceptor.onSecurityAnalysisResult(allRes, runningContext); - - for (int i = 0; i < 3; i++) { - assertTrue(oldInterceptor.allMethodsCalled[i]); - } - } - - static class OldInterceptor implements SecurityAnalysisInterceptor { - - private final RunningContext runningContext; - private final LimitViolationsResult preRes; - private final PostContingencyResult postRes; - private final SecurityAnalysisResult allRes; - - private boolean[] allMethodsCalled = new boolean[3]; - - public OldInterceptor(RunningContext runningContext, LimitViolationsResult preRes, PostContingencyResult postRes, SecurityAnalysisResult allRes) { - this.runningContext = runningContext; - this.preRes = preRes; - this.postRes = postRes; - this.allRes = allRes; - } - - @Override - public void onPreContingencyResult(RunningContext context, LimitViolationsResult preContingencyResult) { - assertSame(runningContext, context); - assertSame(preRes, preContingencyResult); - allMethodsCalled[0] = true; - } - - @Override - public void onPostContingencyResult(RunningContext context, PostContingencyResult postContingencyResult) { - assertSame(runningContext, context); - assertSame(postRes, postContingencyResult); - allMethodsCalled[1] = true; - } - - @Override - public void onSecurityAnalysisResult(RunningContext context, SecurityAnalysisResult result) { - assertSame(runningContext, context); - assertSame(allRes, result); - allMethodsCalled[2] = true; - } - } - -} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisMockFactory.java b/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisMockFactory.java deleted file mode 100644 index 227e04ae041..00000000000 --- a/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisMockFactory.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2019, 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/. - */ -package com.powsybl.security.tools; - -import com.powsybl.computation.ComputationException; -import com.powsybl.computation.ComputationExceptionBuilder; -import com.powsybl.computation.ComputationManager; -import com.powsybl.iidm.network.Network; -import com.powsybl.security.*; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author Yichen TANG - */ -public class SecurityAnalysisMockFactory implements SecurityAnalysisFactory { - - private SecurityAnalysis mock; - - private final boolean failed; - - SecurityAnalysisMockFactory() { - this(false); - } - - SecurityAnalysisMockFactory(boolean failed) { - this.failed = failed; - } - - @Override - public SecurityAnalysis create(Network network, ComputationManager computationManager, int priority) { - return mock == null ? mockSa() : mock; - } - - @Override - public SecurityAnalysis create(Network network, LimitViolationFilter filter, ComputationManager computationManager, int priority) { - return mock == null ? mockSa() : mock; - } - - @Override - public SecurityAnalysis create(Network network, LimitViolationDetector detector, LimitViolationFilter filter, ComputationManager computationManager, int priority) { - return mock == null ? mockSa() : mock; - } - - private SecurityAnalysis mockSa() { - mock = mock(SecurityAnalysis.class); - CompletableFuture cfSarl = mock(CompletableFuture.class); - CompletableFuture cfSar = mock(CompletableFuture.class); - SecurityAnalysisResult sar = mock(SecurityAnalysisResult.class); - LimitViolationsResult preResult = mock(LimitViolationsResult.class); - when(sar.getPreContingencyResult()).thenReturn(preResult); - SecurityAnalysisResultWithLog sarl = new SecurityAnalysisResultWithLog(sar, "hi".getBytes()); - when(cfSarl.join()).thenReturn(sarl); - when(cfSar.join()).thenReturn(sar); - if (!failed) { - when(mock.runWithLog(any(), any(), any())).thenReturn(cfSarl); - when(mock.run(any(), any(), any())).thenReturn(cfSar); - } else { - ComputationExceptionBuilder ceb = new ComputationExceptionBuilder(new RuntimeException("test")); - ceb.addOutLog("out", "outLog") - .addErrLog("err", "errLog"); - ComputationException computationException = ceb.build(); - when(mock.runWithLog(any(), any(), any())).thenThrow(new CompletionException(computationException)); - when(mock.run(any(), any(), any())).thenThrow(new CompletionException(computationException)); - } - return mock; - } -} diff --git a/security-analysis/pom.xml b/security-analysis/pom.xml new file mode 100644 index 00000000000..a3a6a44d366 --- /dev/null +++ b/security-analysis/pom.xml @@ -0,0 +1,31 @@ + + + + 4.0.0 + + + com.powsybl + powsybl-core + 4.3.0-SNAPSHOT + + + pom + powsybl-security-analysis + Security Analysis + Security Analysis aggregator module + + + security-analysis-api + security-analysis-default + + + diff --git a/security-analysis-api/pom.xml b/security-analysis/security-analysis-api/pom.xml similarity index 98% rename from security-analysis-api/pom.xml rename to security-analysis/security-analysis-api/pom.xml index 4c0bc851bfd..f281bd336e7 100644 --- a/security-analysis-api/pom.xml +++ b/security-analysis/security-analysis-api/pom.xml @@ -14,7 +14,7 @@ com.powsybl - powsybl-core + powsybl-security-analysis 4.3.0-SNAPSHOT @@ -30,7 +30,7 @@ - com.powsybl.security + com.powsybl.security.analysis.api diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolation.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolation.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolation.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolation.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationBuilder.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationBuilder.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolationBuilder.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationBuilder.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationDetector.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationDetector.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolationDetector.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationDetector.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationFilter.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationFilter.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolationFilter.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationFilter.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationHelper.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationHelper.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolationHelper.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationHelper.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationType.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationType.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolationType.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationType.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolations.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolations.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolations.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolations.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationsResult.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationsResult.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/LimitViolationsResult.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/LimitViolationsResult.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/NetworkMetadata.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/NetworkMetadata.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/NetworkMetadata.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/NetworkMetadata.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/Security.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/Security.java similarity index 97% rename from security-analysis-api/src/main/java/com/powsybl/security/Security.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/Security.java index d5b7742d537..b705f268633 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/Security.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/Security.java @@ -12,6 +12,7 @@ import com.powsybl.iidm.network.Network; import com.powsybl.security.detectors.DefaultLimitViolationDetector; import com.powsybl.security.detectors.LoadingLimitType; +import com.powsybl.security.results.PostContingencyResult; import java.io.IOException; import java.io.StringWriter; @@ -228,8 +229,8 @@ public static void printPreContingencyViolations(SecurityAnalysisResult result, NumberFormat percentageFormat = getFormatter(printConfig.getFormatterConfig().getLocale(), 2, 2); List filteredLimitViolations = printConfig.getFilter() != null - ? printConfig.getFilter().apply(result.getPreContingencyResult().getLimitViolations(), network) - : result.getPreContingencyResult().getLimitViolations(); + ? printConfig.getFilter().apply(result.getPreContingencyLimitViolationsResult().getLimitViolations(), network) + : result.getPreContingencyLimitViolationsResult().getLimitViolations(); try (TableFormatter formatter = formatterFactory.create(writer, "Pre-contingency violations", @@ -254,7 +255,7 @@ public static void printPreContingencyViolations(SecurityAnalysisResult result, new Column(LOADING_RATE) .setHorizontalAlignment(HorizontalAlignment.RIGHT) .setNumberFormat(percentageFormat))) { - for (String action : result.getPreContingencyResult().getActionsTaken()) { + for (String action : result.getPreContingencyLimitViolationsResult().getActionsTaken()) { formatter.writeCell(action) .writeEmptyCell() .writeEmptyCell() @@ -384,7 +385,7 @@ public static void printPostContingencyViolations(SecurityAnalysisResult result, Objects.requireNonNull(writeConfig); if (!result.getPostContingencyResults().isEmpty()) { Set preContingencyViolations = writeConfig.isFilterPreContingencyViolations() - ? result.getPreContingencyResult().getLimitViolations() + ? result.getPreContingencyLimitViolationsResult().getLimitViolations() .stream() .map(Security::toKey) .collect(Collectors.toSet()) @@ -447,7 +448,7 @@ public static void printPostContingencyViolations(SecurityAnalysisResult result, } private static Consumer writePostContingencyResult(LimitViolationFilter limitViolationFilter, Network network, - Set preContingencyViolations, TableFormatter formatter, boolean writeName) { + Set preContingencyViolations, TableFormatter formatter, boolean writeName) { return postContingencyResult -> { try { // configured filtering diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java new file mode 100644 index 00000000000..1ad68c6d424 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysis.java @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.commons.Versionable; +import com.powsybl.commons.config.PlatformConfig; +import com.powsybl.commons.config.PlatformConfigNamedProvider; +import com.powsybl.computation.ComputationManager; +import com.powsybl.computation.local.LocalComputationManager; +import com.powsybl.contingency.ContingenciesProvider; +import com.powsybl.contingency.EmptyContingencyListProvider; +import com.powsybl.iidm.network.Network; +import com.powsybl.security.detectors.DefaultLimitViolationDetector; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.monitor.StateMonitor; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +/** + * Security analysis main API. It is a utility class (so with only static methods) used as an entry point for running + * a security analysis allowing to choose either a specific implementation or just to rely on the default one. + * + * @author Thomas Adam + */ +public final class SecurityAnalysis { + + private SecurityAnalysis() { + throw new AssertionError("Utility class should not been instantiated"); + } + + /** + * A security analysis runner is responsible for providing convenient methods on top of {@link SecurityAnalysisProvider}: + * several variants of synchronous and asynchronous run with default parameters. + */ + public static final class Runner implements Versionable { + + private final SecurityAnalysisProvider provider; + + private Runner(SecurityAnalysisProvider provider) { + this.provider = Objects.requireNonNull(provider); + } + + public CompletableFuture runAsync(Network network, + String workingStateId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors, + List monitors) { + Objects.requireNonNull(network, "Network should not be null"); + Objects.requireNonNull(workingStateId, "WorkingVariantId should not be null"); + Objects.requireNonNull(detector, "LimitViolation detector should not be null"); + Objects.requireNonNull(filter, "LimitViolation filter should not be null"); + Objects.requireNonNull(computationManager, "ComputationManager should not be null"); + Objects.requireNonNull(contingenciesProvider, "Contingencies provider should not be null"); + Objects.requireNonNull(parameters, "Security analysis parameters should not be null"); + Objects.requireNonNull(interceptors, "Interceptor list should not be null"); + return provider.run(network, workingStateId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors, monitors); + } + + public CompletableFuture runAsync(Network network, LimitViolationFilter filter, + ComputationManager computationManager) { + return runAsync(network, network.getVariantManager().getWorkingVariantId(), new DefaultLimitViolationDetector(), filter, computationManager, SecurityAnalysisParameters.load(), new EmptyContingencyListProvider(), Collections.emptyList(), Collections.emptyList()); + } + + public CompletableFuture runAsync(Network network, ComputationManager computationManager) { + return runAsync(network, LimitViolationFilter.load(), computationManager); + } + + public CompletableFuture runAsync(Network network) { + return runAsync(network, LocalComputationManager.getDefault()); + } + + public SecurityAnalysisReport run(Network network, + String workingStateId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors) { + return runAsync(network, workingStateId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors, Collections.emptyList()).join(); + } + + public SecurityAnalysisReport run(Network network, + String workingStateId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors, List monitors) { + return runAsync(network, workingStateId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors, monitors).join(); + } + + public SecurityAnalysisReport run(Network network, LimitViolationFilter filter, + ComputationManager computationManager) { + return run(network, network.getVariantManager().getWorkingVariantId(), new DefaultLimitViolationDetector(), filter, computationManager, SecurityAnalysisParameters.load(), new EmptyContingencyListProvider(), Collections.emptyList()); + } + + public SecurityAnalysisReport run(Network network, ComputationManager computationManager) { + return run(network, LimitViolationFilter.load(), computationManager); + } + + public SecurityAnalysisReport run(Network network) { + return run(network, LocalComputationManager.getDefault()); + } + + @Override + public String getName() { + return provider.getName(); + } + + @Override + public String getVersion() { + return provider.getVersion(); + } + } + + /** + * Get a runner for security analysis implementation named {@code name}. In the case of a null {@code name}, default + * implementation is used. + * + * @param name name of the security analysis implementation, null if we want to use default one + * @return a runner for security analysis implementation named {@code name} + */ + public static Runner find(String name) { + return new Runner(PlatformConfigNamedProvider.Finder + .find(name, "security-analysis", SecurityAnalysisProvider.class, + PlatformConfig.defaultConfig())); + } + + /** + * Get a runner for default security analysis implementation. + * + * @return a runner for default security analysis implementation + * @throws PowsyblException in case we cannot find a default implementation + */ + public static Runner find() { + return find(null); + } + + public static CompletableFuture runAsync(Network network, + String workingStateId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors) { + return find().runAsync(network, workingStateId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors, Collections.emptyList()); + } + + public static CompletableFuture runAsync(Network network, LimitViolationFilter filter, + ComputationManager computationManager) { + return find().runAsync(network, filter, computationManager); + } + + public static CompletableFuture runAsync(Network network, ComputationManager computationManager) { + return find().runAsync(network, computationManager); + } + + public static CompletableFuture runAsync(Network network) { + return find().runAsync(network); + } + + public static SecurityAnalysisReport run(Network network, + String workingStateId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors) { + return find().run(network, workingStateId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors); + } + + public static SecurityAnalysisReport run(Network network, + String workingStateId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors, List monitors) { + return find().run(network, workingStateId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors, monitors); + } + + public static SecurityAnalysisReport run(Network network, LimitViolationFilter filter, + ComputationManager computationManager) { + return find().run(network, filter, computationManager); + } + + public static SecurityAnalysisReport run(Network network, ComputationManager computationManager) { + return find().run(network, computationManager); + } + + public static SecurityAnalysisReport run(Network network) { + return find().run(network); + } +} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisConfig.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisConfig.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisConfig.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisConfig.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisInput.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisInput.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisInput.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisInput.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisParameters.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisParameters.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisParameters.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisParameters.java diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisProvider.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisProvider.java new file mode 100644 index 00000000000..575c1e24d2f --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisProvider.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2020, 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/. + */ +package com.powsybl.security; + +import com.powsybl.commons.Versionable; +import com.powsybl.commons.config.PlatformConfigNamedProvider; +import com.powsybl.computation.ComputationManager; +import com.powsybl.contingency.ContingenciesProvider; +import com.powsybl.iidm.network.Network; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.monitor.StateMonitor; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * A {@link SecurityAnalysisProvider} is a power system computation which computes, for a {@link com.powsybl.iidm.network.Network Network}, + * the {@link LimitViolation LimitViolations} on N-situation + * and the ones caused by a specified list of {@link com.powsybl.contingency.Contingency Contingencies}. + * + *

Computation results are provided asynchronously as a {@link SecurityAnalysisResult}. + * + *

Implementations of that interface may typically rely on an external tool. + * + *

{@link SecurityAnalysisInterceptor Interceptors} might be used to execute client user-specific code + * on events such as the availability of N-situation results, for example to further customize the results content + * through {@link com.powsybl.commons.extensions.Extension Extensions}. + * + * @author Thomas Adam + */ +public interface SecurityAnalysisProvider extends Versionable, PlatformConfigNamedProvider { + + /** + * Run an asynchronous single security analysis job. + *

+ * if there are exceptions thrown. But the original exception would be wrapped in {@link com.powsybl.computation.ComputationException}, and those .out/.err log file's contents + * are be collected in the {@link com.powsybl.computation.ComputationException} too. + * + *

 {@code
+     * try {
+     *       SecurityAnalysisResult result = securityAnalysis.run(network, variantId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors).join();
+     *   } catch (CompletionException e) {
+     *       if (e.getCause() instanceof ComputationException) {
+     *           ComputationException computationException = (ComputationException) e.getCause();
+     *           System.out.println("Consume exception...");
+     *           computationException.getOutLogs().forEach((name, content) -> {
+     *               System.out.println("-----" + name + "----");
+     *               System.out.println(content);
+     *           });
+     *           computationException.getErrLogs().forEach((name, content) -> {
+     *               System.out.println("-----" + name + "----");
+     *               System.out.println(content);
+     *           });
+     *       }
+     *       throw e;
+     *   }
+     * }
+ * + * @param network IIDM network on which the security analysis will be performed + * @param workingVariantId network variant ID on which the analysis will be performed + * @param detector + * @param filter + * @param computationManager + * @param parameters specific security analysis parameters + * @param contingenciesProvider provides list of contingencies + * @param interceptors + * @return a {@link CompletableFuture} on {@link SecurityAnalysisResult} that gathers security factor values + */ + default CompletableFuture run(Network network, + String workingVariantId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors) { + return run(network, workingVariantId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors, Collections.emptyList()); + } + + /** + * Run an asynchronous single security analysis job. + *

+ * if there are exceptions thrown. But the original exception would be wrapped in {@link com.powsybl.computation.ComputationException}, and those .out/.err log file's contents + * are be collected in the {@link com.powsybl.computation.ComputationException} too. + * + *

 {@code
+     * try {
+     *       SecurityAnalysisResult result = securityAnalysis.run(network, variantId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors).join();
+     *   } catch (CompletionException e) {
+     *       if (e.getCause() instanceof ComputationException) {
+     *           ComputationException computationException = (ComputationException) e.getCause();
+     *           System.out.println("Consume exception...");
+     *           computationException.getOutLogs().forEach((name, content) -> {
+     *               System.out.println("-----" + name + "----");
+     *               System.out.println(content);
+     *           });
+     *           computationException.getErrLogs().forEach((name, content) -> {
+     *               System.out.println("-----" + name + "----");
+     *               System.out.println(content);
+     *           });
+     *       }
+     *       throw e;
+     *   }
+     * }
+ * + * @param network IIDM network on which the security analysis will be performed + * @param workingVariantId network variant ID on which the analysis will be performed + * @param detector + * @param filter + * @param computationManager + * @param parameters specific security analysis parameters + * @param contingenciesProvider provides list of contingencies + * @param interceptors + * @param monitors stateMonitor that defines the branch bus and threeWindingsTransformer about which informations will be written after security analysis + * @return a {@link CompletableFuture} on {@link SecurityAnalysisResult} that gathers security factor values + */ + default CompletableFuture run(Network network, + String workingVariantId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors, + List monitors) { + return run(network, workingVariantId, detector, filter, computationManager, parameters, contingenciesProvider, interceptors); + } +} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultWithLog.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisReport.java similarity index 58% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultWithLog.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisReport.java index bcd3ed219fb..8d366e43e49 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultWithLog.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisReport.java @@ -1,30 +1,35 @@ /** - * Copyright (c) 2019, RTE (http://www.rte-france.com) + * Copyright (c) 2021, 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/. */ package com.powsybl.security; +import com.powsybl.commons.extensions.AbstractExtendable; + import java.util.Objects; import java.util.Optional; /** - * @author Yichen TANG + * @author Thomas Adam */ -public class SecurityAnalysisResultWithLog { +public class SecurityAnalysisReport extends AbstractExtendable { private final SecurityAnalysisResult result; private byte[] logBytes; - public SecurityAnalysisResultWithLog(SecurityAnalysisResult result) { - this.result = Objects.requireNonNull(result); + public static SecurityAnalysisReport empty() { + return new SecurityAnalysisReport(SecurityAnalysisResult.empty()); } - public SecurityAnalysisResultWithLog(SecurityAnalysisResult result, byte[] logBytes) { + public SecurityAnalysisReport(SecurityAnalysisResult result) { this.result = Objects.requireNonNull(result); - this.logBytes = logBytes; + } + + public SecurityAnalysisResult getResult() { + return result; } /** @@ -35,7 +40,8 @@ public Optional getLogBytes() { return Optional.ofNullable(logBytes); } - public SecurityAnalysisResult getResult() { - return result; + public SecurityAnalysisReport setLogBytes(byte[] logBytes) { + this.logBytes = logBytes; + return this; } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResult.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResult.java similarity index 53% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResult.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResult.java index 458dd5469ff..6b2fa3c7929 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResult.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResult.java @@ -7,10 +7,9 @@ package com.powsybl.security; import com.powsybl.commons.extensions.AbstractExtendable; +import com.powsybl.security.results.*; -import java.util.Collections; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * @author Geoffroy Jamgotchian @@ -19,16 +18,32 @@ public class SecurityAnalysisResult extends AbstractExtendable postContingencyResults; + private final PreContingencyResult preContingencyResult; + public static SecurityAnalysisResult empty() { return new SecurityAnalysisResult(LimitViolationsResult.empty(), Collections.emptyList()); } public SecurityAnalysisResult(LimitViolationsResult preContingencyResult, List postContingencyResults) { + this(new PreContingencyResult(preContingencyResult, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()), postContingencyResults); + } + + public SecurityAnalysisResult(LimitViolationsResult preContingencyResult, + List postContingencyResults, + List preContingencyBranchResults, + List preContingencyBusResults, + List preContingencyThreeWindingsTransformerResults) { + this(new PreContingencyResult(preContingencyResult, preContingencyBranchResults, + preContingencyBusResults, + preContingencyThreeWindingsTransformerResults), + postContingencyResults); + } + + public SecurityAnalysisResult(PreContingencyResult preContingencyResult, + List postContingencyResults) { this.preContingencyResult = Objects.requireNonNull(preContingencyResult); this.postContingencyResults = Objects.requireNonNull(postContingencyResults); } @@ -42,11 +57,15 @@ public SecurityAnalysisResult setNetworkMetadata(NetworkMetadata networkMetadata return this; } - public LimitViolationsResult getPreContingencyResult() { - return preContingencyResult; + public LimitViolationsResult getPreContingencyLimitViolationsResult() { + return preContingencyResult.getLimitViolationsResult(); } public List getPostContingencyResults() { return postContingencyResults; } + + public PreContingencyResult getPreContingencyResult() { + return preContingencyResult; + } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java similarity index 77% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java index a2f94d43144..00910f7c9c5 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultBuilder.java @@ -10,14 +10,13 @@ import com.powsybl.contingency.Contingency; import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; import com.powsybl.security.interceptors.SecurityAnalysisResultContext; +import com.powsybl.security.results.*; import java.util.*; /** - * - * Facilitates the creation of security analysis results, in particular - * for subclasses of {@link AbstractSecurityAnalysis}. - * + * Facilitates the creation of security analysis results. + *

* Encapsulates filtering of limit violations with a provided {@link LimitViolationFilter}, * as well as notifications to {@link SecurityAnalysisInterceptor}s. * @@ -30,7 +29,7 @@ public class SecurityAnalysisResultBuilder { private final List interceptors; // Below are volatile objects used for building the actual complete result - private LimitViolationsResult preContingencyResult; + private final PreContingencyResult preContingencyResult; private final List postContingencyResults = Collections.synchronizedList(new ArrayList<>()); public SecurityAnalysisResultBuilder(LimitViolationFilter filter, SecurityAnalysisResultContext context, @@ -38,6 +37,7 @@ public SecurityAnalysisResultBuilder(LimitViolationFilter filter, SecurityAnalys this.filter = Objects.requireNonNull(filter); this.context = Objects.requireNonNull(context); this.interceptors = ImmutableList.copyOf(interceptors); + this.preContingencyResult = new PreContingencyResult(); } public SecurityAnalysisResultBuilder(LimitViolationFilter filter, SecurityAnalysisResultContext context) { @@ -45,15 +45,28 @@ public SecurityAnalysisResultBuilder(LimitViolationFilter filter, SecurityAnalys } private void setPreContingencyResult(LimitViolationsResult preContingencyResult) { - this.preContingencyResult = Objects.requireNonNull(preContingencyResult); + this.preContingencyResult.setLimitViolationsResult(preContingencyResult); } private void addPostContingencyResult(PostContingencyResult result) { postContingencyResults.add(Objects.requireNonNull(result)); } + private void addPreContingencyBranchResults(Map preContingencyBranchResults) { + this.preContingencyResult.addPreContingencyBranchResults(Objects.requireNonNull(preContingencyBranchResults.values())); + } + + private void addPreContingencyBusResults(Map preContingencyBusResults) { + this.preContingencyResult.addPreContingencyBusResults(Objects.requireNonNull(preContingencyBusResults.values())); + } + + private void addPreContingencyThreeWindingsTransformerResults(Map threeWindingsTransformerResults) { + this.preContingencyResult.addPreContingencyThreeWindingsTransformerResults(Objects.requireNonNull(threeWindingsTransformerResults.values())); + } + /** * Initiates the creation of the result for N situation. + * * @return a {@link PreContingencyResultBuilder} instance. */ public PreContingencyResultBuilder preContingency() { @@ -62,6 +75,7 @@ public PreContingencyResultBuilder preContingency() { /** * Initiates the creation of the result for N situation + * * @param preContingencyResultContext the context used when create the result * @return a {@link PreContingencyResultBuilder} instance. */ @@ -71,6 +85,7 @@ public PreContingencyResultBuilder preContingency(SecurityAnalysisResultContext /** * Initiates the creation of the result for one {@link Contingency}. + * * @param contingency the contingency for which a result should be created * @return a {@link PostContingencyResultBuilder} instance. */ @@ -80,7 +95,8 @@ public PostContingencyResultBuilder contingency(Contingency contingency) { /** * Initiates the creation of the result for one {@link Contingency} - * @param contingency the contingency for which a result should be created + * + * @param contingency the contingency for which a result should be created * @param postContingencyResultContext the context used when create the result * @return a {@link PostContingencyResultBuilder} instance. */ @@ -90,6 +106,7 @@ public PostContingencyResultBuilder contingency(Contingency contingency, Securit /** * Finalizes the result. + * * @return the N situation result builder */ public SecurityAnalysisResult build() { @@ -111,6 +128,12 @@ public abstract class AbstractLimitViolationsResultBuilder branchResults = new HashMap<>(); + + protected final Map busResults = new HashMap<>(); + + protected final Map threeWindingsTransformerResults = new HashMap<>(); + protected final List violations = new ArrayList<>(); protected final SecurityAnalysisResultContext resultContext; @@ -122,6 +145,7 @@ public B setComputationOk(boolean computationOk) { /** * Initiates a result builder with a {@link SecurityAnalysisResultContext}. + * * @param resultContext The context would be used when creation result or as default context when a limit violation added. */ private AbstractLimitViolationsResultBuilder(SecurityAnalysisResultContext resultContext) { @@ -131,6 +155,7 @@ private AbstractLimitViolationsResultBuilder(SecurityAnalysisResultContext resul /** * Adds a {@link LimitViolation} to the builder. * The default result context would be supplied to interceptors. + * * @param violation * @return */ @@ -141,6 +166,7 @@ public B addViolation(LimitViolation violation) { /** * Adds a {@link LimitViolation} to the builder with a context. + * * @param violation the context would be supplied to interceptors. * @return */ @@ -160,6 +186,21 @@ public B addViolations(List violations) { return addViolations(violations, resultContext); } + public B addBranchResult(BranchResult branchResult) { + this.branchResults.put(branchResult.getBranchId(), branchResult); + return (B) this; + } + + public B addBusResult(BusResults busResults) { + this.busResults.put(busResults.getBusId(), busResults); + return (B) this; + } + + public B addThreeWindingsTransformerResult(ThreeWindingsTransformerResult threeWindingsTransformerResult) { + this.threeWindingsTransformerResults.put(threeWindingsTransformerResult.getThreeWindingsTransformerId(), threeWindingsTransformerResult); + return (B) this; + } + } /** @@ -173,6 +214,7 @@ public class PreContingencyResultBuilder extends AbstractLimitViolationsResultBu /** * Finalize the creation of the PreContingencyResult instance + * * @return the parent {@link SecurityAnalysisResultBuilder} instance. */ public SecurityAnalysisResultBuilder endPreContingency() { @@ -180,7 +222,9 @@ public SecurityAnalysisResultBuilder endPreContingency() { LimitViolationsResult res = new LimitViolationsResult(computationOk, filteredViolations); interceptors.forEach(i -> i.onPreContingencyResult(res, resultContext)); setPreContingencyResult(res); - + addPreContingencyBranchResults(branchResults); + addPreContingencyBusResults(busResults); + addPreContingencyThreeWindingsTransformerResults(threeWindingsTransformerResults); return SecurityAnalysisResultBuilder.this; } } @@ -204,15 +248,20 @@ public PostContingencyResultBuilder addViolation(LimitViolation violation, Secur /** * Finalize the creation of the PostContingencyResult instance + * * @return the parent {@link SecurityAnalysisResultBuilder} instance. */ public SecurityAnalysisResultBuilder endContingency() { List filteredViolations = filter.apply(violations, context.getNetwork()); - PostContingencyResult res = new PostContingencyResult(contingency, computationOk, filteredViolations); + PostContingencyResult res = new PostContingencyResult(contingency, computationOk, filteredViolations, branchResults, busResults, threeWindingsTransformerResults); interceptors.forEach(i -> i.onPostContingencyResult(res, resultContext)); addPostContingencyResult(res); return SecurityAnalysisResultBuilder.this; } + + public void addPostContingency(PostContingencyResult res) { + addPostContingencyResult(res); + } } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java similarity index 88% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java index ae99766982f..bb818a984c3 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisResultMerger.java @@ -20,14 +20,14 @@ public static SecurityAnalysisResult merge(SecurityAnalysisResult[] results) { //If one of the subtasks has failed, return a failed result Objects.requireNonNull(results); for (SecurityAnalysisResult subResult : results) { - if (!subResult.getPreContingencyResult().isComputationOk()) { + if (!subResult.getPreContingencyLimitViolationsResult().isComputationOk()) { return FAILED_SECURITY_ANALYSIS_RESULT; } } //Else, actually merge results final SecurityAnalysisResult res = new SecurityAnalysisResult( - results[0].getPreContingencyResult(), new ArrayList<>(results[0].getPostContingencyResults())) + results[0].getPreContingencyLimitViolationsResult(), new ArrayList<>(results[0].getPostContingencyResults())) .setNetworkMetadata(results[0].getNetworkMetadata()); if (results.length > 1) { Arrays.stream(results, 1, results.length).forEach(r -> res.getPostContingencyResults().addAll(r.getPostContingencyResults())); diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsTool.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsTool.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsTool.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsTool.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationComparator.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationComparator.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationComparator.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationComparator.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationEquivalence.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationEquivalence.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationEquivalence.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationEquivalence.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationsResultEquivalence.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationsResultEquivalence.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationsResultEquivalence.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/LimitViolationsResultEquivalence.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java similarity index 93% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java index 6f8b9fb0b58..eaabe9e3680 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/PostContingencyResultComparator.java @@ -9,7 +9,7 @@ import java.util.Comparator; import java.util.Objects; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; /** * diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriter.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriter.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriter.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriter.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java similarity index 97% rename from security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java index 5f62316a41e..6f10d71390b 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalence.java @@ -13,7 +13,7 @@ import com.google.common.base.Equivalence; import com.powsybl.security.LimitViolation; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; import com.powsybl.security.SecurityAnalysisResult; /** @@ -36,7 +36,7 @@ protected boolean doEquivalent(SecurityAnalysisResult result1, SecurityAnalysisR PostContingencyResultComparator postContingencyResultComparator = new PostContingencyResultComparator(); // compare precontingency results - boolean equivalent = violationsResultEquivalence.equivalent(result1.getPreContingencyResult(), result2.getPreContingencyResult()); + boolean equivalent = violationsResultEquivalence.equivalent(result1.getPreContingencyLimitViolationsResult(), result2.getPreContingencyLimitViolationsResult()); // I still carry on the comparison even if equivalent is already false because I need to print the violations of the post contingency results // compare postcontingency results diff --git a/security-analysis-api/src/main/java/com/powsybl/security/converter/JsonSecurityAnalysisResultExporter.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/converter/JsonSecurityAnalysisResultExporter.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/converter/JsonSecurityAnalysisResultExporter.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/converter/JsonSecurityAnalysisResultExporter.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporter.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporter.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporter.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporter.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporters.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporters.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporters.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/converter/SecurityAnalysisResultExporters.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractContingencyBlindDetector.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractContingencyBlindDetector.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractContingencyBlindDetector.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractContingencyBlindDetector.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractLimitViolationDetector.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractLimitViolationDetector.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractLimitViolationDetector.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/AbstractLimitViolationDetector.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/detectors/DefaultLimitViolationDetector.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/DefaultLimitViolationDetector.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/detectors/DefaultLimitViolationDetector.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/DefaultLimitViolationDetector.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/detectors/LoadingLimitType.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/LoadingLimitType.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/detectors/LoadingLimitType.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/LoadingLimitType.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/detectors/package-info.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/package-info.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/detectors/package-info.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/detectors/package-info.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java similarity index 71% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java index cb89da6ec2f..9ff66edd93a 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/DistributedSecurityAnalysisExecution.java @@ -9,8 +9,7 @@ import com.powsybl.computation.ComputationManager; import com.powsybl.computation.ExecutionEnvironment; import com.powsybl.computation.ExecutionHandler; -import com.powsybl.security.SecurityAnalysisResult; -import com.powsybl.security.SecurityAnalysisResultWithLog; +import com.powsybl.security.SecurityAnalysisReport; import com.powsybl.security.execution.SecurityAnalysisExecution; import com.powsybl.security.execution.SecurityAnalysisExecutionInput; @@ -39,20 +38,10 @@ public DistributedSecurityAnalysisExecution(ExternalSecurityAnalysisConfig confi } @Override - public CompletableFuture execute(ComputationManager computationManager, + public CompletableFuture execute(ComputationManager computationManager, SecurityAnalysisExecutionInput data) { - - ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_task_", config.isDebug()); - ExecutionHandler executionHandler = SecurityAnalysisExecutionHandlers.distributed(data, subtaskCount); - return computationManager.execute(itoolsEnv, executionHandler); - } - - @Override - public CompletableFuture executeWithLog(ComputationManager computationManager, - SecurityAnalysisExecutionInput data) { - ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_task_", config.isDebug()); - ExecutionHandler executionHandler = SecurityAnalysisExecutionHandlers.distributedWithLog(data, subtaskCount); + ExecutionHandler executionHandler = SecurityAnalysisExecutionHandlers.distributed(data, subtaskCount); return computationManager.execute(itoolsEnv, executionHandler); } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysisConfig.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysisConfig.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysisConfig.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/ExternalSecurityAnalysisConfig.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java similarity index 72% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java index ce4248c7061..1bbf36b536f 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/ForwardedSecurityAnalysisExecution.java @@ -9,8 +9,7 @@ import com.powsybl.computation.ComputationManager; import com.powsybl.computation.ExecutionEnvironment; import com.powsybl.computation.ExecutionHandler; -import com.powsybl.security.SecurityAnalysisResult; -import com.powsybl.security.SecurityAnalysisResultWithLog; +import com.powsybl.security.SecurityAnalysisReport; import com.powsybl.security.execution.SecurityAnalysisExecution; import com.powsybl.security.execution.SecurityAnalysisExecutionInput; @@ -44,20 +43,11 @@ public ForwardedSecurityAnalysisExecution(ExternalSecurityAnalysisConfig config, } @Override - public CompletableFuture execute(ComputationManager computationManager, + public CompletableFuture execute(ComputationManager computationManager, SecurityAnalysisExecutionInput data) { ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_", config.isDebug()); - ExecutionHandler executionHandler = SecurityAnalysisExecutionHandlers.forwarded(data, forwardedTaskCount); - return computationManager.execute(itoolsEnv, executionHandler); - } - - @Override - public CompletableFuture executeWithLog(ComputationManager computationManager, - SecurityAnalysisExecutionInput data) { - - ExecutionEnvironment itoolsEnv = new ExecutionEnvironment(Collections.emptyMap(), "security_analysis_", config.isDebug()); - ExecutionHandler executionHandler = SecurityAnalysisExecutionHandlers.forwardedWithLogs(data, forwardedTaskCount); + ExecutionHandler executionHandler = SecurityAnalysisExecutionHandlers.forwarded(data, forwardedTaskCount); return computationManager.execute(itoolsEnv, executionHandler); } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptions.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptions.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptions.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptions.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java similarity index 92% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java index f1d45fba003..ebf61c8414f 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandler.java @@ -14,6 +14,7 @@ import com.powsybl.security.execution.NetworkVariant; import com.powsybl.security.execution.SecurityAnalysisExecutionInput; import com.powsybl.security.json.JsonSecurityAnalysisParameters; +import com.powsybl.security.monitor.StateMonitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,7 +31,6 @@ import static java.util.Objects.requireNonNull; /** - * * Base implementation for {@link ExecutionHandler}s which may execute one or multiple {@literal itools security-analysis} command(s). * The exact behaviour is provided through the constructor argument. * Instances are provided by factory methods of {@link SecurityAnalysisExecutionHandlers}. @@ -85,11 +85,11 @@ interface ExceptionHandler { /** * Creates a new security analysis execution handler. * - * @param reader Defines how results should be read from working directory. + * @param reader Defines how results should be read from working directory. * @param optionsCustomizer If not {@code null}, defines additional command options. - * @param exceptionHandler Used to translate exceptions to a {@link ComputationException}. - * @param executionCount The number of executions of the command. - * @param input The execution input data. + * @param exceptionHandler Used to translate exceptions to a {@link ComputationException}. + * @param executionCount The number of executions of the command. + * @param input The execution input data. */ public SecurityAnalysisExecutionHandler(ResultReader reader, OptionsCustomizer optionsCustomizer, @@ -112,6 +112,9 @@ public SecurityAnalysisExecutionHandler(ResultReader reader, @Override public List before(Path workingDir) throws IOException { CommandExecution execution = createSecurityAnalysisCommandExecution(workingDir); + if (!this.input.getMonitors().isEmpty()) { + StateMonitor.write(this.input.getMonitors(), workingDir.resolve("montoring_file.json")); + } return Collections.singletonList(execution); } @@ -136,9 +139,9 @@ public R after(Path workingDir, ExecutionReport report) throws IOException { */ private CommandExecution createSecurityAnalysisCommandExecution(Path workingDir) { SecurityAnalysisCommandOptions options = new SecurityAnalysisCommandOptions() - .id("security-analysis") - .resultExtensions(input.getResultExtensions()) - .violationTypes(input.getViolationTypes()); + .id("security-analysis") + .resultExtensions(input.getResultExtensions()) + .violationTypes(input.getViolationTypes()); addCaseFile(options, workingDir, input.getNetworkVariant()); addParametersFile(options, workingDir, input.getParameters()); diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java similarity index 57% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java index 6ac4113d5cd..bbdabfb5051 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlers.java @@ -12,9 +12,9 @@ import com.powsybl.computation.ComputationExceptionBuilder; import com.powsybl.computation.ExecutionHandler; import com.powsybl.computation.Partition; +import com.powsybl.security.SecurityAnalysisReport; import com.powsybl.security.SecurityAnalysisResult; import com.powsybl.security.SecurityAnalysisResultMerger; -import com.powsybl.security.SecurityAnalysisResultWithLog; import com.powsybl.security.execution.SecurityAnalysisExecutionInput; import com.powsybl.security.json.SecurityAnalysisResultDeserializer; @@ -46,7 +46,7 @@ private SecurityAnalysisExecutionHandlers() { * Create an {@link ExecutionHandler} which forwards the security analysis execution through a call * to {@literal itools security-analysis}. */ - public static ExecutionHandler forwarded(SecurityAnalysisExecutionInput input) { + public static ExecutionHandler forwarded(SecurityAnalysisExecutionInput input) { return forwarded(input, null); } @@ -54,31 +54,10 @@ public static ExecutionHandler forwarded(SecurityAnalysi * Create an {@link ExecutionHandler} which forwards the security analysis execution through a call * to {@literal itools security-analysis}, with the option {@literal --task-count}. */ - public static ExecutionHandler forwarded(SecurityAnalysisExecutionInput input, Integer forwardedTaskCount) { + public static ExecutionHandler forwarded(SecurityAnalysisExecutionInput input, Integer forwardedTaskCount) { Preconditions.checkArgument(forwardedTaskCount == null || forwardedTaskCount >= 1, TASK_COUNT_ERROR_MESSAGE, forwardedTaskCount); - return new SecurityAnalysisExecutionHandler<>(SecurityAnalysisExecutionHandlers::readSingleResult, - (workingDir, options) -> forwardedOptions(workingDir, options, forwardedTaskCount), - SecurityAnalysisExecutionHandlers::generateExceptionWithLogs, - 1, - input); - } - - /** - * Create an {@link ExecutionHandler} which forwards the security analysis execution through a call - * to {@literal itools security-analysis}. It also retrieves execution logs. - */ - public static ExecutionHandler forwardedWithLogs(SecurityAnalysisExecutionInput input) { - return forwardedWithLogs(input, null); - } - - /** - * Create an {@link ExecutionHandler} which forwards the security analysis execution through a call - * to {@literal itools security-analysis}, with the option {@literal --task-count}. It also retrieves execution logs. - */ - public static ExecutionHandler forwardedWithLogs(SecurityAnalysisExecutionInput input, Integer forwardedTaskCount) { - Preconditions.checkArgument(forwardedTaskCount == null || forwardedTaskCount >= 1, TASK_COUNT_ERROR_MESSAGE, forwardedTaskCount); - return new SecurityAnalysisExecutionHandler<>(SecurityAnalysisExecutionHandlers::readSingleResultWithLogs, - (workingDir, options) -> forwardedWithLogsOptions(workingDir, options, forwardedTaskCount), + return new SecurityAnalysisExecutionHandler<>(workingDir -> readSingleResult(workingDir, input.isWithLogs()), + (workingDir, options) -> forwardedOptions(workingDir, options, forwardedTaskCount, input.isWithLogs()), SecurityAnalysisExecutionHandlers::generateExceptionWithLogs, 1, input); @@ -88,41 +67,28 @@ public static ExecutionHandler forwardedWithLogs( * Create an {@link ExecutionHandler} which distributes the security analysis execution through multiple calls * to {@literal itools security-analysis}, as specified in argument. */ - public static ExecutionHandler distributed(SecurityAnalysisExecutionInput input, int subtaskCount) { - Preconditions.checkArgument(subtaskCount >= 1, TASK_COUNT_ERROR_MESSAGE, subtaskCount); - return new SecurityAnalysisExecutionHandler<>(workingDir -> readResults(workingDir, subtaskCount), - (workingDir, options) -> distributedOptions(workingDir, options, subtaskCount), - (workingDir, cause) -> generateExceptionWithLogs(workingDir, cause, subtaskCount), - subtaskCount, - input); - } - - /** - * Create an {@link ExecutionHandler} which distributes the security analysis execution through multiple calls - * to {@literal itools security-analysis}, as specified in argument. It also retrieves execution logs. - */ - public static ExecutionHandler distributedWithLog(SecurityAnalysisExecutionInput input, int subtaskCount) { + public static ExecutionHandler distributed(SecurityAnalysisExecutionInput input, int subtaskCount) { Preconditions.checkArgument(subtaskCount >= 1, TASK_COUNT_ERROR_MESSAGE, subtaskCount); - return new SecurityAnalysisExecutionHandler<>(workingDir -> readResultsWithLogs(workingDir, subtaskCount), - (workingDir, options) -> distributedWithLogsOptions(workingDir, options, subtaskCount), + return new SecurityAnalysisExecutionHandler<>(workingDir -> readResults(workingDir, subtaskCount, input.isWithLogs()), + (workingDir, options) -> distributedOptions(workingDir, options, subtaskCount, input.isWithLogs()), (workingDir, cause) -> generateExceptionWithLogs(workingDir, cause, subtaskCount), subtaskCount, input); } - public static SecurityAnalysisResult readSingleResult(Path workingDir) { + public static SecurityAnalysisReport readSingleResult(Path workingDir, boolean withLogs) { Path taskResultFile = workingDir.resolve(OUTPUT_FILE); - return SecurityAnalysisResultDeserializer.read(taskResultFile); - } - - public static SecurityAnalysisResultWithLog readSingleResultWithLogs(Path workingDir) { - SecurityAnalysisResult re = readSingleResult(workingDir); // throws UncheckedIOException - List collectedLogsFilename = new ArrayList<>(); - collectedLogsFilename.add(workingDir.relativize(getLogPath(workingDir)).toString()); // logs_IDX.zip - collectedLogsFilename.add(saCmdOutLogName()); - collectedLogsFilename.add(saCmdErrLogName()); - byte[] logBytes = ZipPackager.archiveFilesToZipBytes(workingDir, collectedLogsFilename); - return new SecurityAnalysisResultWithLog(re, logBytes); + SecurityAnalysisResult re = SecurityAnalysisResultDeserializer.read(taskResultFile); + SecurityAnalysisReport report = new SecurityAnalysisReport(re); + if (withLogs) { + List collectedLogsFilename = new ArrayList<>(); + collectedLogsFilename.add(workingDir.relativize(getLogPath(workingDir)).toString()); // logs_IDX.zip + collectedLogsFilename.add(saCmdOutLogName()); + collectedLogsFilename.add(saCmdErrLogName()); + byte[] logBytes = ZipPackager.archiveFilesToZipBytes(workingDir, collectedLogsFilename); + report.setLogBytes(logBytes); + } + return report; } private static String saCmdOutLogName() { @@ -133,51 +99,47 @@ private static String saCmdErrLogName() { return SA_CMD_ID + ".err"; } - public static void forwardedOptions(Path workingDir, SecurityAnalysisCommandOptions options, Integer taskCount) { + public static void forwardedOptions(Path workingDir, SecurityAnalysisCommandOptions options, Integer taskCount, boolean withLogs) { options.outputFile(workingDir.resolve(OUTPUT_FILE), "JSON"); if (taskCount != null) { options.taskCount(taskCount); } + if (withLogs) { + options.logFile(getLogPath(workingDir)); + } } - public static void forwardedWithLogsOptions(Path workingDir, SecurityAnalysisCommandOptions options, Integer taskCount) { - forwardedOptions(workingDir, options, taskCount); - options.logFile(getLogPath(workingDir)); - } - - public static void distributedOptions(Path workingDir, SecurityAnalysisCommandOptions options, int taskCount) { + public static void distributedOptions(Path workingDir, SecurityAnalysisCommandOptions options, int taskCount, boolean withLogs) { options.id(SA_TASK_CMD_ID); options.outputFile(i -> getOutputPathForTask(workingDir, i), "JSON"); options.task(i -> new Partition(i + 1, taskCount)); - } - - public static void distributedWithLogsOptions(Path workingDir, SecurityAnalysisCommandOptions options, int taskCount) { - distributedOptions(workingDir, options, taskCount); - options.logFile(i -> getLogPathForTask(workingDir, i)); + if (withLogs) { + options.logFile(i -> getLogPathForTask(workingDir, i)); + } } public static Path getOutputPathForTask(Path workingDir, int taskIndex) { return workingDir.resolve(String.format(OUTPUT_FILE_FMT, taskIndex)); } - public static SecurityAnalysisResult readResults(Path workingDir, int subtaskCount) { + public static SecurityAnalysisReport readResults(Path workingDir, int subtaskCount, boolean withLogs) { List results = IntStream.range(0, subtaskCount) .mapToObj(taskIndex -> getOutputPathForTask(workingDir, taskIndex)) .map(SecurityAnalysisResultDeserializer::read) .collect(Collectors.toList()); - return SecurityAnalysisResultMerger.merge(results); - } - - public static SecurityAnalysisResultWithLog readResultsWithLogs(Path workingDir, int subtaskCount) { - SecurityAnalysisResult re = readResults(workingDir, subtaskCount); - List collectedLogsFilename = new ArrayList<>(); - for (int i = 0; i < subtaskCount; i++) { - collectedLogsFilename.add(workingDir.relativize(getLogPathForTask(workingDir, i)).toString()); // logs_IDX.zip - collectedLogsFilename.add(satOutName(i)); - collectedLogsFilename.add(satErrName(i)); + SecurityAnalysisResult re = SecurityAnalysisResultMerger.merge(results); + SecurityAnalysisReport report = new SecurityAnalysisReport(re); + if (withLogs) { + List collectedLogsFilename = new ArrayList<>(); + for (int i = 0; i < subtaskCount; i++) { + collectedLogsFilename.add(workingDir.relativize(getLogPathForTask(workingDir, i)).toString()); // logs_IDX.zip + collectedLogsFilename.add(satOutName(i)); + collectedLogsFilename.add(satErrName(i)); + } + byte[] logBytes = ZipPackager.archiveFilesToZipBytes(workingDir, collectedLogsFilename); + report.setLogBytes(logBytes); } - byte[] logBytes = ZipPackager.archiveFilesToZipBytes(workingDir, collectedLogsFilename); - return new SecurityAnalysisResultWithLog(re, logBytes); + return report; } private static ComputationException generateExceptionWithLogs(Path workingDir, Exception cause, int count) { diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/SubContingenciesProvider.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SubContingenciesProvider.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/SubContingenciesProvider.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/SubContingenciesProvider.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/distributed/package-info.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/package-info.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/distributed/package-info.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/distributed/package-info.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/NetworkVariant.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/NetworkVariant.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/NetworkVariant.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/NetworkVariant.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java similarity index 72% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java index d2ab15baaec..1f67ac306fd 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecution.java @@ -7,8 +7,7 @@ package com.powsybl.security.execution; import com.powsybl.computation.ComputationManager; -import com.powsybl.security.SecurityAnalysisResult; -import com.powsybl.security.SecurityAnalysisResultWithLog; +import com.powsybl.security.SecurityAnalysisReport; import java.util.concurrent.CompletableFuture; @@ -23,10 +22,6 @@ */ public interface SecurityAnalysisExecution { - CompletableFuture execute(ComputationManager computationManager, + CompletableFuture execute(ComputationManager computationManager, SecurityAnalysisExecutionInput data); - - CompletableFuture executeWithLog(ComputationManager computationManager, - SecurityAnalysisExecutionInput data); - } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java similarity index 79% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java index d914bfd7812..772d9e11369 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilder.java @@ -8,7 +8,7 @@ import com.powsybl.computation.Partition; import com.powsybl.contingency.ContingenciesProviders; -import com.powsybl.security.SecurityAnalysisFactory; +import com.powsybl.security.SecurityAnalysis; import com.powsybl.security.SecurityAnalysisInput; import com.powsybl.security.distributed.DistributedSecurityAnalysisExecution; import com.powsybl.security.distributed.ExternalSecurityAnalysisConfig; @@ -26,7 +26,7 @@ public class SecurityAnalysisExecutionBuilder { private final Supplier externalConfig; - private final Supplier factory; + private final String providerName; private final SecurityAnalysisInputBuildStrategy inputBuildStrategy; private boolean forward = false; @@ -36,15 +36,15 @@ public class SecurityAnalysisExecutionBuilder { /** * Create a new builder. * - * @param externalConfig The method to load an external security analysis config, only used for forwarded and distributed executions. - * @param factory The method to load a security analysis factory, only used for local executions. - * @param inputBuildStrategy The method to translates execution inputs into actual security analysis inputs. Only used for local executions. + * @param externalConfig The method to load an external security analysis config, only used for forwarded and distributed executions. + * @param providerName The named security-analysis implementation to use. If {@literal null}, the default would be used. + * @param inputBuildStrategy The method to translates execution inputs into actual security analysis inputs. Only used for local executions. */ public SecurityAnalysisExecutionBuilder(Supplier externalConfig, - Supplier factory, + String providerName, SecurityAnalysisInputBuildStrategy inputBuildStrategy) { this.externalConfig = Objects.requireNonNull(externalConfig); - this.factory = Objects.requireNonNull(factory); + this.providerName = Objects.requireNonNull(providerName); this.inputBuildStrategy = Objects.requireNonNull(inputBuildStrategy); } @@ -69,7 +69,7 @@ public SecurityAnalysisExecution build() { } else if (taskCount != null) { return new DistributedSecurityAnalysisExecution(externalConfig.get(), taskCount); } else { - return new SecurityAnalysisExecutionImpl(factory.get(), inputBuildStrategy()); + return new SecurityAnalysisExecutionImpl(SecurityAnalysis.find(providerName), inputBuildStrategy()); } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java similarity index 50% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java index b6d2bdfe1f2..11c557e6a41 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionImpl.java @@ -9,6 +9,7 @@ import com.powsybl.computation.ComputationManager; import com.powsybl.security.*; +import java.util.ArrayList; import java.util.concurrent.CompletableFuture; import static java.util.Objects.requireNonNull; @@ -22,15 +23,25 @@ */ public class SecurityAnalysisExecutionImpl implements SecurityAnalysisExecution { - private final SecurityAnalysisFactory factory; + private final SecurityAnalysis.Runner runner; private final SecurityAnalysisInputBuildStrategy inputBuildStrategy; - public SecurityAnalysisExecutionImpl(SecurityAnalysisFactory factory) { - this(factory, SecurityAnalysisExecutionImpl::buildDefault); + /** + * The execution will use the default security-analysis implementation defined in the platform. + */ + public SecurityAnalysisExecutionImpl() { + this(null, SecurityAnalysisExecutionImpl::buildDefault); } - public SecurityAnalysisExecutionImpl(SecurityAnalysisFactory factory, SecurityAnalysisInputBuildStrategy inputBuildStrategy) { - this.factory = requireNonNull(factory); + /** + * The execution will use the {@literal providerName} implementation. + */ + public SecurityAnalysisExecutionImpl(SecurityAnalysis.Runner runner) { + this(runner, SecurityAnalysisExecutionImpl::buildDefault); + } + + public SecurityAnalysisExecutionImpl(SecurityAnalysis.Runner runner, SecurityAnalysisInputBuildStrategy inputBuildStrategy) { + this.runner = requireNonNull(runner); this.inputBuildStrategy = requireNonNull(inputBuildStrategy); } @@ -42,24 +53,16 @@ private SecurityAnalysisInput buildInput(SecurityAnalysisExecutionInput executio return inputBuildStrategy.buildFrom(executionInput); } - private SecurityAnalysis buildSecurityAnalysis(SecurityAnalysisInput input, ComputationManager computationManager) { - SecurityAnalysis securityAnalysis = factory.create(input.getNetworkVariant().getNetwork(), input.getLimitViolationDetector(), - input.getFilter(), computationManager, 0); - input.getInterceptors().forEach(securityAnalysis::addInterceptor); - return securityAnalysis; - } - - @Override - public CompletableFuture execute(ComputationManager computationManager, SecurityAnalysisExecutionInput data) { - SecurityAnalysisInput input = buildInput(data); - SecurityAnalysis securityAnalysis = buildSecurityAnalysis(input, computationManager); - return securityAnalysis.run(input.getNetworkVariant().getVariantId(), input.getParameters(), input.getContingenciesProvider()); - } - @Override - public CompletableFuture executeWithLog(ComputationManager computationManager, SecurityAnalysisExecutionInput data) { + public CompletableFuture execute(ComputationManager computationManager, SecurityAnalysisExecutionInput data) { SecurityAnalysisInput input = buildInput(data); - SecurityAnalysis securityAnalysis = buildSecurityAnalysis(input, computationManager); - return securityAnalysis.runWithLog(input.getNetworkVariant().getVariantId(), input.getParameters(), input.getContingenciesProvider()); + return runner.runAsync(input.getNetworkVariant().getNetwork(), + input.getNetworkVariant().getVariantId(), + input.getLimitViolationDetector(), + input.getFilter(), + computationManager, + input.getParameters(), + input.getContingenciesProvider(), + new ArrayList<>(input.getInterceptors()), data.getMonitors()); } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java similarity index 82% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java index ac8ffc2a462..8345a9ad4a2 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisExecutionInput.java @@ -6,10 +6,12 @@ */ package com.powsybl.security.execution; +import com.google.common.collect.ImmutableList; import com.google.common.io.ByteSource; import com.powsybl.iidm.network.Network; import com.powsybl.security.LimitViolationType; import com.powsybl.security.SecurityAnalysisParameters; +import com.powsybl.security.monitor.StateMonitor; import java.util.*; @@ -36,6 +38,8 @@ public class SecurityAnalysisExecutionInput { private SecurityAnalysisParameters parameters; private final List resultExtensions = new ArrayList<>(); private final Set violationTypes = EnumSet.noneOf(LimitViolationType.class); + private boolean withLogs = false; + private final List monitors = new ArrayList<>(); public Optional getContingenciesSource() { return Optional.ofNullable(contingenciesSource); @@ -57,6 +61,14 @@ public NetworkVariant getNetworkVariant() { return networkVariant; } + public List getMonitors() { + return ImmutableList.copyOf(monitors); + } + + public boolean isWithLogs() { + return withLogs; + } + public SecurityAnalysisExecutionInput setContingenciesSource(ByteSource contingenciesSource) { this.contingenciesSource = contingenciesSource; return this; @@ -91,4 +103,16 @@ public SecurityAnalysisExecutionInput setNetworkVariant(Network network, String networkVariant = new NetworkVariant(network, variantId); return this; } + + public SecurityAnalysisExecutionInput setMonitors(List monitors) { + Objects.requireNonNull(monitors); + this.monitors.clear(); + this.monitors.addAll(monitors); + return this; + } + + public SecurityAnalysisExecutionInput setWithLogs(boolean withLogs) { + this.withLogs = withLogs; + return this; + } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisInputBuildStrategy.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisInputBuildStrategy.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisInputBuildStrategy.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/SecurityAnalysisInputBuildStrategy.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/execution/package-info.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/package-info.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/execution/package-info.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/execution/package-info.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/extensions/ActivePowerExtension.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/extensions/ActivePowerExtension.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/extensions/ActivePowerExtension.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/extensions/ActivePowerExtension.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/extensions/CurrentExtension.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/extensions/CurrentExtension.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/extensions/CurrentExtension.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/extensions/CurrentExtension.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/extensions/VoltageExtension.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/extensions/VoltageExtension.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/extensions/VoltageExtension.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/extensions/VoltageExtension.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java similarity index 97% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java index c28695259ee..d4afcc2177a 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/CurrentLimitViolationInterceptor.java @@ -10,7 +10,7 @@ import com.powsybl.security.LimitViolation; import com.powsybl.security.LimitViolationType; import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; import com.powsybl.security.extensions.ActivePowerExtension; import com.powsybl.security.extensions.CurrentExtension; diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java similarity index 96% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java index 3b9bc4f9194..7aca9fb0f11 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisInterceptor.java @@ -9,7 +9,7 @@ import com.powsybl.contingency.Contingency; import com.powsybl.security.LimitViolation; import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; import com.powsybl.security.SecurityAnalysisResult; /** diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisResultContext.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisResultContext.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisResultContext.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/DefaultSecurityAnalysisResultContext.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/RunningContext.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/RunningContext.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/RunningContext.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/RunningContext.java diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java new file mode 100644 index 00000000000..d7c5105b671 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptor.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2017, 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/. + */ +package com.powsybl.security.interceptors; + +import com.powsybl.contingency.Contingency; +import com.powsybl.security.LimitViolation; +import com.powsybl.security.LimitViolationsResult; +import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.SecurityAnalysisResult; + +/** + * + * Security analysis interceptors are notified at various steps of the construction of + * the {@link SecurityAnalysisResult}, for instance when adding new {@link LimitViolation limit violations}. + * This mechanism allows for example users of the {@link com.powsybl.security.SecurityAnalysis} to add + * additional information in the result, as {@link com.powsybl.commons.extensions.Extension extensions}. + * + *

Some of this information can be retrieved from the provided {@link SecurityAnalysisResultContext}. + * Implementations of the security analysis can provide implementation-specific information by providing + * their own implementation of this context. + * + *

Note that the contexts provided to the various methods can be different objects, in order + * to provide more specific information, for example for violations or contingencies. + * This can also be helpful to guarantee thread safety, if the result builder is used concurrently. + * + * + * @author Mathieu Bague + */ +public interface SecurityAnalysisInterceptor { + + /** + * Callback after the pre-contingency result is built. + * @param preContingencyResult + * @param context + */ + void onPreContingencyResult(LimitViolationsResult preContingencyResult, SecurityAnalysisResultContext context); + + /** + * Callback after the post-contingency result is built. + * @param context + * @param postContingencyResult + */ + void onPostContingencyResult(PostContingencyResult postContingencyResult, SecurityAnalysisResultContext context); + + /** + * Callback after the security-analysis result is built. + * @param result + * @param context + */ + void onSecurityAnalysisResult(SecurityAnalysisResult result, SecurityAnalysisResultContext context); + + /** + * Callback when a violation is detected on N situation. + * @param limitViolation + * @param context + */ + void onLimitViolation(LimitViolation limitViolation, SecurityAnalysisResultContext context); + + /** + * Callback when a violation is detected on N-1 situation. + * @param contingency + * @param limitViolation + * @param context + */ + void onLimitViolation(Contingency contingency, LimitViolation limitViolation, SecurityAnalysisResultContext context); +} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorExtension.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorExtension.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorExtension.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorExtension.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptors.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptors.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptors.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptors.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisResultContext.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisResultContext.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisResultContext.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/interceptors/SecurityAnalysisResultContext.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/ActivePowerExtensionSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/ActivePowerExtensionSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/ActivePowerExtensionSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/ActivePowerExtensionSerializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/CurrentExtensionSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/CurrentExtensionSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/CurrentExtensionSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/CurrentExtensionSerializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/JsonSecurityAnalysisParameters.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/JsonSecurityAnalysisParameters.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/JsonSecurityAnalysisParameters.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/JsonSecurityAnalysisParameters.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationDeserializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationDeserializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationDeserializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationResultDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationResultDeserializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationResultDeserializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationResultDeserializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationSerializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationsResultSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationsResultSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationsResultSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/LimitViolationsResultSerializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataDeserializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataDeserializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataDeserializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/NetworkMetadataSerializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java similarity index 57% rename from security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java index 055ff7ee5c9..aa93d5d1ac7 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultDeserializer.java @@ -8,13 +8,19 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.powsybl.contingency.Contingency; import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.results.BranchResult; +import com.powsybl.security.results.BusResults; +import com.powsybl.security.results.ThreeWindingsTransformerResult; import java.io.IOException; +import java.util.Collections; +import java.util.List; /** * @author Mathieu Bague @@ -29,6 +35,9 @@ class PostContingencyResultDeserializer extends StdDeserializer branchResults = Collections.emptyList(); + List busResults = Collections.emptyList(); + List threeWindingsTransformerResults = Collections.emptyList(); while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { @@ -41,12 +50,26 @@ public PostContingencyResult deserialize(JsonParser parser, DeserializationConte parser.nextToken(); limitViolationsResult = parser.readValueAs(LimitViolationsResult.class); break; - + case "branchResults": + parser.nextToken(); + branchResults = parser.readValueAs(new TypeReference>() { + }); + break; + case "busResults": + parser.nextToken(); + busResults = parser.readValueAs(new TypeReference>() { + }); + break; + case "threeWindingsTransformerResults": + parser.nextToken(); + threeWindingsTransformerResults = parser.readValueAs(new TypeReference>() { + }); + break; default: throw new AssertionError("Unexpected field: " + parser.getCurrentName()); } } - return new PostContingencyResult(contingency, limitViolationsResult); + return new PostContingencyResult(contingency, limitViolationsResult, branchResults, busResults, threeWindingsTransformerResults); } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java similarity index 75% rename from security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java index ddadb8c0514..117a98eede4 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PostContingencyResultSerializer.java @@ -9,7 +9,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; import java.io.IOException; @@ -27,6 +27,9 @@ public void serialize(PostContingencyResult postContingencyResult, JsonGenerator jsonGenerator.writeStartObject(); jsonGenerator.writeObjectField("contingency", postContingencyResult.getContingency()); jsonGenerator.writeObjectField("limitViolationsResult", postContingencyResult.getLimitViolationsResult()); + jsonGenerator.writeObjectField("branchResults", postContingencyResult.getBranchResults()); + jsonGenerator.writeObjectField("busResults", postContingencyResult.getBusResults()); + jsonGenerator.writeObjectField("threeWindingsTransformerResults", postContingencyResult.getThreeWindingsTransformerResult()); jsonGenerator.writeEndObject(); } } diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultDeserializer.java new file mode 100644 index 00000000000..643c6a1e67f --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultDeserializer.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.powsybl.security.LimitViolationsResult; +import com.powsybl.security.results.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +/** + * @author Etienne Lesot + */ +class PreContingencyResultDeserializer extends StdDeserializer { + + PreContingencyResultDeserializer() { + super(PreContingencyResult.class); + } + + @Override + public PreContingencyResult deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException { + LimitViolationsResult preContingencyResult = null; + List branchResults = Collections.emptyList(); + List busResults = Collections.emptyList(); + List threeWindingsTransformerResults = Collections.emptyList(); + + while (parser.nextToken() != JsonToken.END_OBJECT) { + switch (parser.getCurrentName()) { + + case "limitViolationsResult": + parser.nextToken(); + preContingencyResult = parser.readValueAs(LimitViolationsResult.class); + break; + case "branchResults": + parser.nextToken(); + branchResults = parser.readValueAs(new TypeReference>() { + }); + break; + case "busResults": + parser.nextToken(); + busResults = parser.readValueAs(new TypeReference>() { + }); + break; + case "threeWindingsTransformerResults": + parser.nextToken(); + threeWindingsTransformerResults = parser.readValueAs(new TypeReference>() { + }); + break; + default: + throw new AssertionError("Unexpected field: " + parser.getCurrentName()); + } + } + + return new PreContingencyResult(preContingencyResult, + branchResults, + busResults, + threeWindingsTransformerResults); + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultSerializer.java new file mode 100644 index 00000000000..24d474456ee --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/PreContingencyResultSerializer.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.json; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.powsybl.security.results.PreContingencyResult; + +import java.io.IOException; + +/** + * @author Etienne Lesot + */ +class PreContingencyResultSerializer extends StdSerializer { + + PreContingencyResultSerializer() { + super(PreContingencyResult.class); + } + + @Override + public void serialize(PreContingencyResult preContingencyResult, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeStartObject(); + jsonGenerator.writeObjectField("limitViolationsResult", preContingencyResult.getLimitViolationsResult()); + jsonGenerator.writeObjectField("branchResults", preContingencyResult.getPreContingencyBranchResults()); + jsonGenerator.writeObjectField("busResults", preContingencyResult.getPreContingencyBusResults()); + jsonGenerator.writeObjectField("threeWindingsTransformerResults", preContingencyResult.getPreContingencyThreeWindingsTransformerResults()); + jsonGenerator.writeEndObject(); + } +} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java similarity index 83% rename from security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java index 0bf8ba7210a..dff7072be6f 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisJsonModule.java @@ -8,6 +8,8 @@ import com.powsybl.contingency.json.ContingencyJsonModule; import com.powsybl.security.*; +import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.results.PreContingencyResult; /** * @author Geoffroy Jamgotchian @@ -20,11 +22,13 @@ public SecurityAnalysisJsonModule() { addSerializer(PostContingencyResult.class, new PostContingencyResultSerializer()); addSerializer(LimitViolationsResult.class, new LimitViolationsResultSerializer()); addSerializer(LimitViolation.class, new LimitViolationSerializer()); + addSerializer(PreContingencyResult.class, new PreContingencyResultSerializer()); addDeserializer(SecurityAnalysisResult.class, new SecurityAnalysisResultDeserializer()); addDeserializer(NetworkMetadata.class, new NetworkMetadataDeserializer()); addDeserializer(PostContingencyResult.class, new PostContingencyResultDeserializer()); addDeserializer(LimitViolationsResult.class, new LimitViolationResultDeserializer()); addDeserializer(LimitViolation.class, new LimitViolationDeserializer()); + addDeserializer(PreContingencyResult.class, new PreContingencyResultDeserializer()); } } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersDeserializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersDeserializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersDeserializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersJsonModule.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersJsonModule.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersJsonModule.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersJsonModule.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisParametersSerializer.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java similarity index 74% rename from security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java index 876c35526da..062de819441 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultDeserializer.java @@ -18,7 +18,7 @@ import com.powsybl.commons.json.JsonUtil; import com.powsybl.security.LimitViolationsResult; import com.powsybl.security.NetworkMetadata; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.*; import com.powsybl.security.SecurityAnalysisResult; import java.io.IOException; @@ -32,13 +32,12 @@ import java.util.Objects; /** - * * @author Massimo Ferraro */ public class SecurityAnalysisResultDeserializer extends StdDeserializer { private static final Supplier> SUPPLIER = - Suppliers.memoize(() -> ExtensionProviders.createProvider(ExtensionJsonSerializer.class, "security-analysis")); + Suppliers.memoize(() -> ExtensionProviders.createProvider(ExtensionJsonSerializer.class, "security-analysis")); SecurityAnalysisResultDeserializer() { super(SecurityAnalysisResult.class); @@ -46,15 +45,21 @@ public class SecurityAnalysisResultDeserializer extends StdDeserializer postContingencyResults = Collections.emptyList(); List> extensions = Collections.emptyList(); + PreContingencyResult preContingencyResult = null; + List branchResults = Collections.emptyList(); + List busResults = Collections.emptyList(); + List threeWindingsTransformerResults = Collections.emptyList(); while (parser.nextToken() != JsonToken.END_OBJECT) { switch (parser.getCurrentName()) { case "version": parser.nextToken(); // skip + version = parser.getValueAsString(); break; case "network": @@ -64,7 +69,11 @@ public SecurityAnalysisResult deserialize(JsonParser parser, DeserializationCont case "preContingencyResult": parser.nextToken(); - preContingencyResult = parser.readValueAs(LimitViolationsResult.class); + if (version != null && version.equals("1.0")) { + limitViolationsResult = parser.readValueAs(LimitViolationsResult.class); + } else { + preContingencyResult = parser.readValueAs(PreContingencyResult.class); + } break; case "postContingencyResults": @@ -82,8 +91,12 @@ public SecurityAnalysisResult deserialize(JsonParser parser, DeserializationCont throw new AssertionError("Unexpected field: " + parser.getCurrentName()); } } - - SecurityAnalysisResult result = new SecurityAnalysisResult(preContingencyResult, postContingencyResults); + SecurityAnalysisResult result = null; + if (preContingencyResult == null) { + result = new SecurityAnalysisResult(limitViolationsResult, postContingencyResults, branchResults, busResults, threeWindingsTransformerResults); + } else { + result = new SecurityAnalysisResult(preContingencyResult, postContingencyResults); + } result.setNetworkMetadata(networkMetadata); SUPPLIER.get().addExtensions(result, extensions); diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java similarity index 97% rename from security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java index d7750f505b7..ca2eb0d6077 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/SecurityAnalysisResultSerializer.java @@ -23,7 +23,7 @@ */ public class SecurityAnalysisResultSerializer extends StdSerializer { - private static final String VERSION = "1.0"; + private static final String VERSION = "1.1"; SecurityAnalysisResultSerializer() { super(SecurityAnalysisResult.class); diff --git a/security-analysis-api/src/main/java/com/powsybl/security/json/VoltageExtensionSerializer.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/VoltageExtensionSerializer.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/json/VoltageExtensionSerializer.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/json/VoltageExtensionSerializer.java diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitor.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitor.java new file mode 100644 index 00000000000..7af5b99b227 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitor.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.monitor; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.type.TypeReference; +import com.powsybl.commons.json.JsonUtil; +import com.powsybl.contingency.ContingencyContext; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +/** + * @author Etienne Lesot + *

+ *

+ * A stateMonitor allows to get information about branch, bus and three windings transformers on the network after a security analysis computation. + * Contingency context allows to specify if the information asked are about N situation N-k situation with a contingency id + * or both. + *

+ * for example if we want information about a branch after security analysis on contingency c1 + * contingencyContext will contained the contingencyId c1, contextType SPECIFIC and StateMonitor will contained the id of the branch + * if we want information about a branch in N situation + * contingencyContext will contained a null contingencyId, contextType NONE and StateMonitor will contained the id of the branch + * if we want information about a branch in N situation and after security analysis on contingency c1 + * contingencyContext will contained contingencyId c1, contextType ALL and StateMonitor will contained the id of the branch + */ +public class StateMonitor { + + /** + * define on which situation information are needed + */ + private final ContingencyContext contingencyContext; + + /** + * branchs ids on which information will be collected + */ + private final Set branchIds = new LinkedHashSet<>(); + + /** + * voltageLevels ids on which information will be collected + */ + private final Set voltageLevelIds = new LinkedHashSet<>(); + + /** + * voltageLevels ids on which information will be collected + */ + private final Set threeWindingsTransformerIds = new LinkedHashSet<>(); + + public ContingencyContext getContingencyContext() { + return contingencyContext; + } + + public Set getBranchIds() { + return branchIds; + } + + public Set getVoltageLevelIds() { + return voltageLevelIds; + } + + public Set getThreeWindingsTransformerIds() { + return threeWindingsTransformerIds; + } + + public StateMonitor(@JsonProperty("contingencyContext") ContingencyContext contingencyContext, + @JsonProperty("branchIds") Set branchIds, @JsonProperty("voltageLevelIds") Set voltageLevelIds, + @JsonProperty("threeWindingsTransformerIds") Set threeWindingsTransformerIds) { + this.contingencyContext = Objects.requireNonNull(contingencyContext); + this.branchIds.addAll(Objects.requireNonNull(branchIds)); + this.voltageLevelIds.addAll(Objects.requireNonNull(voltageLevelIds)); + this.threeWindingsTransformerIds.addAll(Objects.requireNonNull(threeWindingsTransformerIds)); + } + + public StateMonitor merge(StateMonitor monitorTobeMerged) { + this.branchIds.addAll(monitorTobeMerged.getBranchIds()); + this.voltageLevelIds.addAll(monitorTobeMerged.getVoltageLevelIds()); + this.threeWindingsTransformerIds.addAll(monitorTobeMerged.getThreeWindingsTransformerIds()); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + StateMonitor that = (StateMonitor) o; + return Objects.equals(contingencyContext, that.contingencyContext) && + Objects.equals(branchIds, that.branchIds) && + Objects.equals(voltageLevelIds, that.voltageLevelIds) && + Objects.equals(threeWindingsTransformerIds, that.threeWindingsTransformerIds); + } + + @Override + public int hashCode() { + return Objects.hash(contingencyContext, branchIds, voltageLevelIds, threeWindingsTransformerIds); + } + + @Override + public String toString() { + return "StateMonitor{" + + "contingencyContext=" + contingencyContext + + ", branchIds=" + branchIds + + ", voltageLevelIds=" + voltageLevelIds + + ", threeWindingsTransformerIds=" + threeWindingsTransformerIds + + '}'; + } + + public static void write(List monitors, Path jsonFile) { + try { + OutputStream out = Files.newOutputStream(jsonFile); + JsonUtil.createObjectMapper().writer().writeValue(out, monitors); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static List read(Path jsonFile) { + try { + return JsonUtil.createObjectMapper().readerFor(new TypeReference>() { + }).readValue(Files.newInputStream(jsonFile)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitorIndex.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitorIndex.java new file mode 100644 index 00000000000..4991add5464 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/monitor/StateMonitorIndex.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.monitor; + +import com.powsybl.contingency.ContingencyContext; +import com.powsybl.contingency.ContingencyContextType; + +import java.util.*; + +/** + * @author Etienne Lesot + * index all state monitors according to their ContingencyContextType + * + */ +public class StateMonitorIndex { + private final StateMonitor allStateMonitor; + private final StateMonitor noneStateMonitor; + private final Map specificStateMonitors = new HashMap<>(); + + public StateMonitorIndex(List stateMonitors) { + allStateMonitor = new StateMonitor(new ContingencyContext(null, ContingencyContextType.ALL), + new HashSet<>(), new HashSet<>(), new HashSet<>()); + noneStateMonitor = new StateMonitor(new ContingencyContext(null, ContingencyContextType.NONE), + new HashSet<>(), new HashSet<>(), new HashSet<>()); + stateMonitors.forEach(monitor -> { + String id = monitor.getContingencyContext().getContingencyId(); + if (id != null) { + this.specificStateMonitors.merge(id, monitor, StateMonitor::merge); + } else if (monitor.getContingencyContext().getContextType() == ContingencyContextType.ALL) { + allStateMonitor.merge(monitor); + } else if (monitor.getContingencyContext().getContextType() == ContingencyContextType.NONE) { + noneStateMonitor.merge(monitor); + } + }); + } + + public StateMonitor getAllStateMonitor() { + return allStateMonitor; + } + + public StateMonitor getNoneStateMonitor() { + return noneStateMonitor; + } + + public Map getSpecificStateMonitors() { + return specificStateMonitors; + } +} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/ContingenciesProviderPreprocessorFactory.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/ContingenciesProviderPreprocessorFactory.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/preprocessor/ContingenciesProviderPreprocessorFactory.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/ContingenciesProviderPreprocessorFactory.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessor.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessor.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessor.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessor.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorFactory.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorFactory.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorFactory.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorFactory.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessors.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessors.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessors.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessors.java diff --git a/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/package-info.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/package-info.java similarity index 100% rename from security-analysis-api/src/main/java/com/powsybl/security/preprocessor/package-info.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/preprocessor/package-info.java diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BranchResult.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BranchResult.java new file mode 100644 index 00000000000..8c7ad24afd7 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BranchResult.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.results; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * provide electrical information on a branch after a security analysis. + * it belongs to pre and post Contingency results. + * it is the result of the branch id specified in StateMonitor. + * + * @author Etienne Lesot + */ +public class BranchResult { + + private final String branchId; + + private final double p1; + + private final double q1; + + private final double i1; + + private final double p2; + + private final double q2; + + private final double i2; + + @JsonCreator + public BranchResult(@JsonProperty("branchId") String branchId, @JsonProperty("p1") double p1, @JsonProperty("q1") double q1, + @JsonProperty("i1") double i1, @JsonProperty("p2") double p2, + @JsonProperty("q2") double q2, @JsonProperty("i2") double i2) { + this.branchId = Objects.requireNonNull(branchId); + this.p1 = Objects.requireNonNull(p1); + this.q1 = Objects.requireNonNull(q1); + this.i1 = Objects.requireNonNull(i1); + this.p2 = Objects.requireNonNull(p2); + this.q2 = Objects.requireNonNull(q2); + this.i2 = Objects.requireNonNull(i2); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + BranchResult that = (BranchResult) o; + return Double.compare(that.p1, p1) == 0 && + Double.compare(that.q1, q1) == 0 && + Double.compare(that.i1, i1) == 0 && + Double.compare(that.p2, p2) == 0 && + Double.compare(that.q2, q2) == 0 && + Double.compare(that.i2, i2) == 0 && + Objects.equals(branchId, that.branchId); + } + + @Override + public int hashCode() { + return Objects.hash(branchId, p1, q1, i1, p2, q2, i2); + } + + public String getBranchId() { + return branchId; + } + + public double getI1() { + return i1; + } + + public double getI2() { + return i2; + } + + public double getP1() { + return p1; + } + + public double getP2() { + return p2; + } + + public double getQ1() { + return q1; + } + + public double getQ2() { + return q2; + } + + @Override + public String toString() { + return "BranchResult{" + + "branchId='" + branchId + '\'' + + ", p1=" + p1 + + ", q1=" + q1 + + ", i1=" + i1 + + ", p2=" + p2 + + ", q2=" + q2 + + ", i2=" + i2 + + '}'; + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BusResults.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BusResults.java new file mode 100644 index 00000000000..0c2aeedba21 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/BusResults.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2016-2017, 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/. + */ +package com.powsybl.security.results; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * + * provide electrical information on a bus after a security analysis. + * it belongs to pre and post Contingency results. + * it is the result of the bus id specified in StateMonitor. + * @author Etienne Lesot + */ +public class BusResults { + + private final String voltageLevelId; + + private final String busId; + + private final double v; + + private final double angle; + + @JsonCreator + public BusResults(@JsonProperty("voltageLevelId") String voltageLevelId, @JsonProperty("busId") String busId, + @JsonProperty("v") double v, @JsonProperty("angle") double angle) { + this.voltageLevelId = Objects.requireNonNull(voltageLevelId); + this.busId = Objects.requireNonNull(busId); + this.v = Objects.requireNonNull(v); + this.angle = Objects.requireNonNull(angle); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + BusResults that = (BusResults) o; + return Double.compare(that.v, v) == 0 && + Double.compare(that.angle, angle) == 0 && + Objects.equals(voltageLevelId, that.voltageLevelId) && + Objects.equals(busId, that.busId); + } + + @Override + public int hashCode() { + return Objects.hash(voltageLevelId, busId, v, angle); + } + + public String getBusId() { + return busId; + } + + public double getAngle() { + return angle; + } + + public double getV() { + return v; + } + + public String getVoltageLevelId() { + return voltageLevelId; + } + + @Override + public String toString() { + return "BusResults{" + + "voltageLevelId='" + voltageLevelId + '\'' + + ", busId='" + busId + '\'' + + ", v=" + v + + ", angle=" + angle + + '}'; + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PostContingencyResult.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PostContingencyResult.java new file mode 100644 index 00000000000..6783c02bc66 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PostContingencyResult.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2016-2017, 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/. + */ +package com.powsybl.security.results; + +import com.google.common.collect.ImmutableMap; +import com.powsybl.contingency.Contingency; +import com.powsybl.security.LimitViolation; +import com.powsybl.security.LimitViolationsResult; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author Geoffroy Jamgotchian + * @author Mathieu Bague + */ +public class PostContingencyResult { + + private final Contingency contingency; + + private final LimitViolationsResult limitViolationsResult; + + private final Map branchResults; + + private final Map busResults; + + private final Map threeWindingsTransformerResults; + + public PostContingencyResult(Contingency contingency, LimitViolationsResult limitViolationsResult) { + this(contingency, limitViolationsResult, Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()); + } + + public PostContingencyResult(Contingency contingency, LimitViolationsResult limitViolationsResult, List branchResults, List busResults, List threeWindingsTransformerResults) { + this(contingency, limitViolationsResult, + branchResults.stream().collect(Collectors.toMap(BranchResult::getBranchId, Function.identity())), + busResults.stream().collect(Collectors.toMap(BusResults::getBusId, Function.identity())), + threeWindingsTransformerResults.stream().collect(Collectors.toMap(ThreeWindingsTransformerResult::getThreeWindingsTransformerId, Function.identity()))); + } + + public PostContingencyResult(Contingency contingency, LimitViolationsResult limitViolationsResult, Map branchResults, Map busResults, Map threeWindingsTransformerResults) { + this.contingency = Objects.requireNonNull(contingency); + this.limitViolationsResult = Objects.requireNonNull(limitViolationsResult); + this.branchResults = ImmutableMap.copyOf(Objects.requireNonNull(branchResults)); + this.busResults = ImmutableMap.copyOf(Objects.requireNonNull(busResults)); + this.threeWindingsTransformerResults = ImmutableMap.copyOf(Objects.requireNonNull(threeWindingsTransformerResults)); + } + + public PostContingencyResult(Contingency contingency, boolean computationOk, List limitViolations, + Map branchResults, Map busResults, Map threeWindingsTransformerResults) { + this(contingency, new LimitViolationsResult(computationOk, limitViolations, Collections.emptyList()), branchResults, busResults, threeWindingsTransformerResults); + } + + public PostContingencyResult(Contingency contingency, boolean computationOk, List limitViolations) { + this(contingency, new LimitViolationsResult(computationOk, limitViolations, Collections.emptyList())); + } + + public PostContingencyResult(Contingency contingency, boolean computationOk, List limitViolations, List actionsTaken) { + this(contingency, new LimitViolationsResult(computationOk, limitViolations, actionsTaken)); + } + + public PostContingencyResult(Contingency contingency, boolean computationOk, List limitViolations, + List actionsTaken, Map branchResults, Map busResults, Map threeWindingsTransformerResults) { + this(contingency, new LimitViolationsResult(computationOk, limitViolations, actionsTaken), branchResults, busResults, threeWindingsTransformerResults); + } + + public Contingency getContingency() { + return contingency; + } + + public LimitViolationsResult getLimitViolationsResult() { + return limitViolationsResult; + } + + public BranchResult getBranchResult(String id) { + Objects.requireNonNull(id); + return branchResults.get(id); + } + + public List getBranchResults() { + return List.copyOf(branchResults.values()); + } + + public BusResults getBusResult(String id) { + Objects.requireNonNull(id); + return busResults.get(id); + } + + public List getBusResults() { + return List.copyOf(busResults.values()); + } + + public ThreeWindingsTransformerResult getThreeWindingsTransformerResult(String id) { + Objects.requireNonNull(id); + return threeWindingsTransformerResults.get(id); + } + + public List getThreeWindingsTransformerResult() { + return List.copyOf(threeWindingsTransformerResults.values()); + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PreContingencyResult.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PreContingencyResult.java new file mode 100644 index 00000000000..b3a7cb26ee0 --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/PreContingencyResult.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.results; + +import com.powsybl.security.LimitViolationsResult; + +import java.util.*; + +/** + * @author Etienne Lesot + */ +public class PreContingencyResult { + private LimitViolationsResult limitViolationsResult; + private final Map preContingencyBranchResults = new HashMap<>(); + private final Map preContingencyBusResults = new HashMap<>(); + private final Map preContingencyThreeWindingsTransformerResults = new HashMap<>(); + + public PreContingencyResult() { + this(null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + } + + public PreContingencyResult(LimitViolationsResult preContingencyResult, Collection preContingencyBranchResults, + Collection preContingencyBusResults, + Collection preContingencyThreeWindingsTransformerResults) { + this.limitViolationsResult = preContingencyResult; + Objects.requireNonNull(preContingencyBranchResults).forEach(r -> this.preContingencyBranchResults.put(r.getBranchId(), r)); + Objects.requireNonNull(preContingencyBusResults).forEach(r -> this.preContingencyBusResults.put(r.getBusId(), r)); + Objects.requireNonNull(preContingencyThreeWindingsTransformerResults).forEach(r -> this.preContingencyThreeWindingsTransformerResults.put(r.getThreeWindingsTransformerId(), r)); + } + + public void setLimitViolationsResult(LimitViolationsResult limitViolationsResult) { + this.limitViolationsResult = limitViolationsResult; + } + + public void addPreContingencyBranchResults(Collection branchResults) { + Objects.requireNonNull(branchResults).forEach(r -> this.preContingencyBranchResults.put(r.getBranchId(), r)); + } + + public void addPreContingencyBusResults(Collection busResults) { + Objects.requireNonNull(busResults).forEach(r -> this.preContingencyBusResults.put(r.getBusId(), r)); + } + + public void addPreContingencyThreeWindingsTransformerResults(Collection threeWindingsTransformerResults) { + Objects.requireNonNull(threeWindingsTransformerResults).forEach(r -> this.preContingencyThreeWindingsTransformerResults.put(r.getThreeWindingsTransformerId(), r)); + } + + public LimitViolationsResult getLimitViolationsResult() { + return limitViolationsResult; + } + + public List getPreContingencyBusResults() { + return List.copyOf(preContingencyBusResults.values()); + } + + public BusResults getPreContingencyBusResult(String id) { + return preContingencyBusResults.get(Objects.requireNonNull(id)); + } + + public List getPreContingencyBranchResults() { + return List.copyOf(preContingencyBranchResults.values()); + } + + public BranchResult getPreContingencyBranchResult(String id) { + return preContingencyBranchResults.get(Objects.requireNonNull(id)); + } + + public List getPreContingencyThreeWindingsTransformerResults() { + return List.copyOf(preContingencyThreeWindingsTransformerResults.values()); + } + + public ThreeWindingsTransformerResult getPreContingencyThreeWindingsTransformerResult(String id) { + return preContingencyThreeWindingsTransformerResults.get(Objects.requireNonNull(id)); + } +} diff --git a/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/ThreeWindingsTransformerResult.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/ThreeWindingsTransformerResult.java new file mode 100644 index 00000000000..68e20a12fdd --- /dev/null +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/results/ThreeWindingsTransformerResult.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.results; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + +/** + * + * provide electrical information on a three windings transformer + * after a security analysis. it belongs to pre and post Contingency results. + * it is the result of the three windings transformer id specified in StateMonitor. + * @author Etienne Lesot + */ +public class ThreeWindingsTransformerResult { + + private final String threeWindingsTransformerId; + + private final double p1; + + private final double q1; + + private final double i1; + + private final double p2; + + private final double q2; + + private final double i2; + + private final double p3; + + private final double q3; + + private final double i3; + + public ThreeWindingsTransformerResult(@JsonProperty("threeWindingsTransformerId") String threeWindingsTransformerId, @JsonProperty("p1") double p1, @JsonProperty("q1") double q1, + @JsonProperty("i1") double i1, @JsonProperty("p2") double p2, @JsonProperty("q2") double q2, + @JsonProperty("i2") double i2, @JsonProperty("p3") double p3, @JsonProperty("q3") double q3, @JsonProperty("i3") double i3) { + this.threeWindingsTransformerId = Objects.requireNonNull(threeWindingsTransformerId); + this.p1 = Objects.requireNonNull(p1); + this.q1 = Objects.requireNonNull(q1); + this.i1 = Objects.requireNonNull(i1); + this.p2 = Objects.requireNonNull(p2); + this.q2 = Objects.requireNonNull(q2); + this.i2 = Objects.requireNonNull(i2); + this.p3 = Objects.requireNonNull(p3); + this.q3 = Objects.requireNonNull(q3); + this.i3 = Objects.requireNonNull(i3); + } + + public String getThreeWindingsTransformerId() { + return threeWindingsTransformerId; + } + + public double getI1() { + return i1; + } + + public double getP1() { + return p1; + } + + public double getQ1() { + return q1; + } + + public double getI2() { + return i2; + } + + public double getP2() { + return p2; + } + + public double getQ2() { + return q2; + } + + public double getI3() { + return i3; + } + + public double getP3() { + return p3; + } + + public double getQ3() { + return q3; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ThreeWindingsTransformerResult that = (ThreeWindingsTransformerResult) o; + return Double.compare(that.p1, p1) == 0 && + Double.compare(that.q1, q1) == 0 && + Double.compare(that.i1, i1) == 0 && + Double.compare(that.p2, p2) == 0 && + Double.compare(that.q2, q2) == 0 && + Double.compare(that.i2, i2) == 0 && + Double.compare(that.p3, p3) == 0 && + Double.compare(that.q3, q3) == 0 && + Double.compare(that.i3, i3) == 0 && + Objects.equals(threeWindingsTransformerId, that.threeWindingsTransformerId); + } + + @Override + public int hashCode() { + return Objects.hash(threeWindingsTransformerId, p1, q1, i1, p2, q2, i2, p3, q3, i3); + } + + @Override + public String toString() { + return "ThreeWindingsTransformerResult{" + + "threeWindingsTransformerId='" + threeWindingsTransformerId + '\'' + + ", p1=" + p1 + + ", q1=" + q1 + + ", i1=" + i1 + + ", p2=" + p2 + + ", q2=" + q2 + + ", i2=" + i2 + + ", p3=" + p3 + + ", q3=" + q3 + + ", i3=" + i3 + + '}'; + } +} diff --git a/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java similarity index 65% rename from security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java index 07135507a51..8870f806b60 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisTool.java @@ -32,6 +32,7 @@ import com.powsybl.security.execution.SecurityAnalysisInputBuildStrategy; import com.powsybl.security.interceptors.SecurityAnalysisInterceptors; import com.powsybl.security.json.JsonSecurityAnalysisParameters; +import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.preprocessor.SecurityAnalysisPreprocessorFactory; import com.powsybl.security.preprocessor.SecurityAnalysisPreprocessors; import com.powsybl.tools.Command; @@ -89,69 +90,74 @@ public String getDescription() { public Options getOptions() { Options options = new Options(); options.addOption(Option.builder().longOpt(CASE_FILE_OPTION) - .desc("the case path") - .hasArg() - .argName("FILE") - .required() - .build()); + .desc("the case path") + .hasArg() + .argName("FILE") + .required() + .build()); options.addOption(Option.builder().longOpt(PARAMETERS_FILE_OPTION) - .desc("loadflow parameters as JSON file") - .hasArg() - .argName("FILE") - .build()); + .desc("loadflow parameters as JSON file") + .hasArg() + .argName("FILE") + .build()); options.addOption(Option.builder().longOpt(LIMIT_TYPES_OPTION) - .desc("limit type filter (all if not set)") - .hasArg() - .argName("LIMIT-TYPES") - .build()); + .desc("limit type filter (all if not set)") + .hasArg() + .argName("LIMIT-TYPES") + .build()); options.addOption(Option.builder().longOpt(OUTPUT_FILE_OPTION) - .desc("the output path") - .hasArg() - .argName("FILE") - .build()); + .desc("the output path") + .hasArg() + .argName("FILE") + .build()); options.addOption(Option.builder().longOpt(OUTPUT_FORMAT_OPTION) - .desc("the output format " + SecurityAnalysisResultExporters.getFormats()) - .hasArg() - .argName("FORMAT") - .build()); + .desc("the output format " + SecurityAnalysisResultExporters.getFormats()) + .hasArg() + .argName("FORMAT") + .build()); options.addOption(Option.builder().longOpt(CONTINGENCIES_FILE_OPTION) - .desc("the contingencies path") - .hasArg() - .argName("FILE") - .build()); + .desc("the contingencies path") + .hasArg() + .argName("FILE") + .build()); options.addOption(Option.builder().longOpt(WITH_EXTENSIONS_OPTION) - .desc("the extension list to enable") - .hasArg() - .argName("EXTENSIONS") - .build()); + .desc("the extension list to enable") + .hasArg() + .argName("EXTENSIONS") + .build()); options.addOption(Option.builder().longOpt(TASK_COUNT) - .desc("number of tasks used for parallelization") - .hasArg() - .argName("NTASKS") - .build()); + .desc("number of tasks used for parallelization") + .hasArg() + .argName("NTASKS") + .build()); options.addOption(Option.builder().longOpt(TASK) - .desc("task identifier (task-index/task-count)") - .hasArg() - .argName("TASKID") - .build()); + .desc("task identifier (task-index/task-count)") + .hasArg() + .argName("TASKID") + .build()); options.addOption(Option.builder().longOpt(EXTERNAL) - .desc("external execution") - .build()); + .desc("external execution") + .build()); options.addOption(createImportParametersFileOption()); options.addOption(createImportParameterOption()); options.addOption(Option.builder().longOpt(OUTPUT_LOG_OPTION) - .desc("log output path (.zip)") - .hasArg() - .argName("FILE") - .build()); + .desc("log output path (.zip)") + .hasArg() + .argName("FILE") + .build()); + options.addOption(Option.builder().longOpt(MONITORING_FILE) + .desc("monitoring file (.json) to get network's infos after computation") + .hasArg() + .argName("FILE") + .build()); return options; } @Override public String getUsageFooter() { return String.join(System.lineSeparator(), - "Allowed LIMIT-TYPES values are " + Arrays.toString(LimitViolationType.values()), - "Allowed EXTENSIONS values are " + SecurityAnalysisInterceptors.getExtensionNames() + "Allowed LIMIT-TYPES values are " + Arrays.toString(LimitViolationType.values()), + "Allowed EXTENSIONS values are " + SecurityAnalysisInterceptors.getExtensionNames() ); } }; @@ -159,28 +165,31 @@ public String getUsageFooter() { static void updateInput(ToolOptions options, SecurityAnalysisExecutionInput inputs) { options.getPath(PARAMETERS_FILE_OPTION) - .ifPresent(f -> JsonSecurityAnalysisParameters.update(inputs.getParameters(), f)); + .ifPresent(f -> JsonSecurityAnalysisParameters.update(inputs.getParameters(), f)); options.getPath(CONTINGENCIES_FILE_OPTION) - .map(p -> FileUtil.asByteSource(p)) - .ifPresent(inputs::setContingenciesSource); + .map(FileUtil::asByteSource) + .ifPresent(inputs::setContingenciesSource); options.getValues(LIMIT_TYPES_OPTION) - .map(types -> types.stream().map(LimitViolationType::valueOf).collect(Collectors.toList())) - .ifPresent(inputs::addViolationTypes); + .map(types -> types.stream().map(LimitViolationType::valueOf).collect(Collectors.toList())) + .ifPresent(inputs::addViolationTypes); options.getValues(WITH_EXTENSIONS_OPTION) - .ifPresent(inputs::addResultExtensions); + .ifPresent(inputs::addResultExtensions); + + options.getValues(OUTPUT_LOG_OPTION) + .ifPresent(f -> inputs.setWithLogs(true)); } private static SecurityAnalysisInputBuildStrategy configBasedInputBuildStrategy(PlatformConfig config) { return preprocessedInputBuildStrategy(() -> LimitViolationFilter.load(config), - SecurityAnalysisPreprocessors.configuredFactory(config) - .orElseGet(() -> SecurityAnalysisPreprocessors.wrap(ContingenciesProviders.newDefaultFactory(config)))); + SecurityAnalysisPreprocessors.configuredFactory(config) + .orElseGet(() -> SecurityAnalysisPreprocessors.wrap(ContingenciesProviders.newDefaultFactory(config)))); } private static SecurityAnalysisInputBuildStrategy preprocessedInputBuildStrategy(Supplier filterInitializer, - SecurityAnalysisPreprocessorFactory preprocessorFactory) { + SecurityAnalysisPreprocessorFactory preprocessorFactory) { return executionInput -> buildPreprocessedInput(executionInput, filterInitializer, preprocessorFactory); } @@ -189,27 +198,27 @@ static SecurityAnalysisInput buildPreprocessedInput(SecurityAnalysisExecutionInp SecurityAnalysisPreprocessorFactory preprocessorFactory) { SecurityAnalysisInput input = new SecurityAnalysisInput(executionInput.getNetworkVariant()) - .setParameters(executionInput.getParameters()) - .setFilter(filterInitializer.get()); + .setParameters(executionInput.getParameters()) + .setFilter(filterInitializer.get()); executionInput.getResultExtensions().stream() - .map(SecurityAnalysisInterceptors::createInterceptor) - .forEach(input::addInterceptor); + .map(SecurityAnalysisInterceptors::createInterceptor) + .forEach(input::addInterceptor); if (!executionInput.getViolationTypes().isEmpty()) { input.getFilter().setViolationTypes(ImmutableSet.copyOf(executionInput.getViolationTypes())); } executionInput.getContingenciesSource() - .map(preprocessorFactory::newPreprocessor) - .ifPresent(p -> p.preprocess(input)); + .map(preprocessorFactory::newPreprocessor) + .ifPresent(p -> p.preprocess(input)); return input; } private static SecurityAnalysisExecutionBuilder createBuilder(PlatformConfig platformConfig) { return new SecurityAnalysisExecutionBuilder(() -> ExternalSecurityAnalysisConfig.load(platformConfig), - () -> SecurityAnalysisFactories.newDefaultFactory(platformConfig), + platformConfig.getModuleConfig(MODULE_CONFIG_NAME_PROPERTY).getStringProperty(DEFAULT_SERVICE_IMPL_NAME_PROPERTY), configBasedInputBuildStrategy(platformConfig)); } @@ -220,16 +229,16 @@ private static SecurityAnalysisExecution buildExecution(ToolOptions options, Sec return builder.build(); } - private static SecurityAnalysisResult runSecurityAnalysisWithLog(ComputationManager computationManager, - SecurityAnalysisExecution execution, - SecurityAnalysisExecutionInput input, - Path logPath) { + private static SecurityAnalysisReport runSecurityAnalysisWithLog(ComputationManager computationManager, + SecurityAnalysisExecution execution, + SecurityAnalysisExecutionInput input, + Path logPath) { try { - SecurityAnalysisResultWithLog resultWithLog = execution.executeWithLog(computationManager, input).join(); + SecurityAnalysisReport report = execution.execute(computationManager, input).join(); // copy log bytes to file - resultWithLog.getLogBytes() - .ifPresent(logBytes -> uncheckedWriteBytes(logBytes, logPath)); - return resultWithLog.getResult(); + report.getLogBytes() + .ifPresent(logBytes -> uncheckedWriteBytes(logBytes, logPath)); + return report; } catch (CompletionException e) { if (e.getCause() instanceof ComputationException) { ComputationException computationException = (ComputationException) e.getCause(); @@ -243,9 +252,8 @@ private static SecurityAnalysisResult runSecurityAnalysisWithLog(ComputationMana static Network readNetwork(CommandLine line, ToolRunningContext context, ImportersLoader importersLoader) throws IOException { ToolOptions options = new ToolOptions(line, context); Path caseFile = options.getPath(CASE_FILE_OPTION) - .orElseThrow(AssertionError::new); + .orElseThrow(AssertionError::new); Properties inputParams = readProperties(line, ConversionToolUtils.OptionType.IMPORT, context); - context.getOutputStream().println("Loading network '" + caseFile + "'"); Network network = Importers.loadNetwork(caseFile, context.getShortTimeExecutionComputationManager(), ImportConfig.load(), inputParams, importersLoader); network.getVariantManager().allowVariantMultiThreadAccess(true); @@ -263,10 +271,10 @@ private static void uncheckedWriteBytes(byte[] bytes, Path path) { @Override public void run(CommandLine line, ToolRunningContext context) throws Exception { run(line, context, - createBuilder(PlatformConfig.defaultConfig()), - SecurityAnalysisParameters::load, - new ImportersServiceLoader(), - TableFormatterConfig::load); + createBuilder(PlatformConfig.defaultConfig()), + SecurityAnalysisParameters::load, + new ImportersServiceLoader(), + TableFormatterConfig::load); } void run(CommandLine line, ToolRunningContext context, @@ -274,36 +282,42 @@ void run(CommandLine line, ToolRunningContext context, Supplier parametersLoader, ImportersLoader importersLoader, Supplier tableFormatterConfigLoader) throws Exception { - ToolOptions options = new ToolOptions(line, context); // Output file and output format Path outputFile = options.getPath(OUTPUT_FILE_OPTION) - .orElse(null); + .orElse(null); String format = null; if (outputFile != null) { format = options.getValue(OUTPUT_FORMAT_OPTION) - .orElseThrow(() -> new ParseException("Missing required option: " + OUTPUT_FORMAT_OPTION)); + .orElseThrow(() -> new ParseException("Missing required option: " + OUTPUT_FORMAT_OPTION)); } Network network = readNetwork(line, context, importersLoader); SecurityAnalysisExecutionInput executionInput = new SecurityAnalysisExecutionInput() - .setNetworkVariant(network, VariantManagerConstants.INITIAL_VARIANT_ID) - .setParameters(parametersLoader.get()); + .setNetworkVariant(network, VariantManagerConstants.INITIAL_VARIANT_ID) + .setParameters(parametersLoader.get()); + + Path monitorFilePath = options.getPath(MONITORING_FILE).orElse(null); + if (monitorFilePath != null) { + executionInput.setMonitors(StateMonitor.read(monitorFilePath)); + } updateInput(options, executionInput); SecurityAnalysisExecution execution = buildExecution(options, executionBuilder); ComputationManager computationManager = options.hasOption(TASK) ? context.getShortTimeExecutionComputationManager() : - context.getLongTimeExecutionComputationManager(); + context.getLongTimeExecutionComputationManager(); + + SecurityAnalysisReport report = options.getPath(OUTPUT_LOG_OPTION) + .map(logPath -> runSecurityAnalysisWithLog(computationManager, execution, executionInput, logPath)) + .orElseGet(() -> execution.execute(computationManager, executionInput).join()); - SecurityAnalysisResult result = options.getPath(OUTPUT_LOG_OPTION) - .map(logPath -> runSecurityAnalysisWithLog(computationManager, execution, executionInput, logPath)) - .orElseGet(() -> execution.execute(computationManager, executionInput).join()); + SecurityAnalysisResult result = report.getResult(); - if (!result.getPreContingencyResult().isComputationOk()) { + if (!result.getPreContingencyLimitViolationsResult().isComputationOk()) { context.getErrorStream().println("Pre-contingency state divergence"); } diff --git a/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java similarity index 81% rename from security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java rename to security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java index 90828f105d4..bba05366140 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java +++ b/security-analysis/security-analysis-api/src/main/java/com/powsybl/security/tools/SecurityAnalysisToolConstants.java @@ -20,6 +20,9 @@ public final class SecurityAnalysisToolConstants { public static final String WITH_EXTENSIONS_OPTION = "with-extensions"; public static final String EXTERNAL = "external"; public static final String OUTPUT_LOG_OPTION = "log-file"; + public static final String MONITORING_FILE = "monitoring-file"; + public static final String MODULE_CONFIG_NAME_PROPERTY = "security-analysis"; + public static final String DEFAULT_SERVICE_IMPL_NAME_PROPERTY = "default-impl-name"; private SecurityAnalysisToolConstants() { } diff --git a/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationBuilderTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationBuilderTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/LimitViolationBuilderTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationBuilderTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationFilterTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationFilterTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/LimitViolationFilterTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationFilterTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/LimitViolationTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/LimitViolationTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/NetworkImporterMock.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/NetworkImporterMock.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/NetworkImporterMock.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/NetworkImporterMock.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisConfigTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisConfigTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisConfigTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisConfigTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisInputTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisInputTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisInputTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisInputTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisParametersTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisParametersTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisParametersTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisParametersTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java similarity index 85% rename from security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java index a8cbacbbe26..7923eb8a20f 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultBuilderTest.java @@ -5,6 +5,10 @@ import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.security.interceptors.*; +import com.powsybl.security.results.BranchResult; +import com.powsybl.security.results.BusResults; +import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.results.ThreeWindingsTransformerResult; import org.junit.Test; import java.util.Collections; @@ -30,8 +34,8 @@ public void failedResult() { SecurityAnalysisResult res = builder.preContingency().setComputationOk(false).endPreContingency().build(); - assertFalse(res.getPreContingencyResult().isComputationOk()); - assertTrue(res.getPreContingencyResult().getLimitViolations().isEmpty()); + assertFalse(res.getPreContingencyLimitViolationsResult().isComputationOk()); + assertTrue(res.getPreContingencyLimitViolationsResult().getLimitViolations().isEmpty()); assertTrue(res.getPostContingencyResults().isEmpty()); } @@ -67,7 +71,7 @@ public void completeResultWithCustomContext() { assertEquals(1, postResultContext.getCalledCount()); SecurityAnalysisResult result = builder.build(); - assertEquals(4, result.getPreContingencyResult().getLimitViolations().size()); + assertEquals(4, result.getPreContingencyLimitViolationsResult().getLimitViolations().size()); assertEquals(1, baseContext.getCalledCount()); } @@ -87,6 +91,10 @@ public void completeResult() { vl.getBusView().getBusStream().forEach(b -> b.setV(380)); builder.contingency(new Contingency("contingency1")).setComputationOk(true) + .addBranchResult(new BranchResult("branchId", 0, 0, 0, 0, 0, 0)) + .addBusResult(new BusResults("voltageLevelId", "busId", 400, 3.14)) + .addThreeWindingsTransformerResult(new ThreeWindingsTransformerResult("threeWindingsTransformerId", + 0, 0, 0, 0, 0, 0, 0, 0, 0)) .addViolations(Security.checkLimits(network)) .endContingency(); @@ -97,12 +105,16 @@ public void completeResult() { SecurityAnalysisResult res = builder.build(); - assertTrue(res.getPreContingencyResult().isComputationOk()); - assertEquals(4, res.getPreContingencyResult().getLimitViolations().size()); + assertTrue(res.getPreContingencyLimitViolationsResult().isComputationOk()); + assertEquals(4, res.getPreContingencyLimitViolationsResult().getLimitViolations().size()); assertEquals(2, res.getPostContingencyResults().size()); PostContingencyResult res1 = res.getPostContingencyResults().get(0); assertEquals("contingency1", res1.getContingency().getId()); + assertEquals(new BranchResult("branchId", 0, 0, 0, 0, 0, 0), res1.getBranchResult("branchId")); + assertEquals(new BusResults("voltageLevelId", "busId", 400, 3.14), res1.getBusResult("busId")); + assertEquals(new ThreeWindingsTransformerResult("threeWindingsTransformerId", + 0, 0, 0, 0, 0, 0, 0, 0, 0), res1.getThreeWindingsTransformerResult("threeWindingsTransformerId")); assertEquals(2, res.getPostContingencyResults().size()); List violations1 = res1.getLimitViolationsResult().getLimitViolations(); diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java similarity index 97% rename from security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java index 490fbc9267c..6f8fee710d4 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityAnalysisResultMergerTest.java @@ -8,6 +8,7 @@ import com.powsybl.contingency.Contingency; import com.powsybl.iidm.network.Branch; +import com.powsybl.security.results.PostContingencyResult; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -60,7 +61,7 @@ public void testMerge() { result1, result2 }; SecurityAnalysisResult mergedResult = SecurityAnalysisResultMerger.merge(results); - assertEquals(preContingencyResult, mergedResult.getPreContingencyResult()); + assertEquals(preContingencyResult, mergedResult.getPreContingencyLimitViolationsResult()); assertEquals(Arrays.asList(postContingencyResult, postContingencyResult2), mergedResult.getPostContingencyResults()); } diff --git a/security-analysis-api/src/test/java/com/powsybl/security/SecurityTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityTest.java similarity index 99% rename from security-analysis-api/src/test/java/com/powsybl/security/SecurityTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityTest.java index c1d485dbb71..c73d46efcab 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/SecurityTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/SecurityTest.java @@ -13,6 +13,7 @@ import com.powsybl.iidm.network.Branch; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.security.results.PostContingencyResult; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; diff --git a/security-analysis-api/src/test/java/com/powsybl/security/TestingNetworkFactory.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/TestingNetworkFactory.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/TestingNetworkFactory.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/TestingNetworkFactory.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsToolTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsToolTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsToolTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/CompareSecurityAnalysisResultsToolTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationComparatorTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationComparatorTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationComparatorTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationComparatorTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationEquivalenceTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationEquivalenceTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationEquivalenceTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationEquivalenceTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationsResultEquivalenceTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationsResultEquivalenceTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationsResultEquivalenceTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/LimitViolationsResultEquivalenceTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java similarity index 96% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java index a8f61c9219d..b27149fde92 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/PostContingencyResultComparatorTest.java @@ -16,7 +16,7 @@ import org.mockito.Mockito; import com.powsybl.contingency.Contingency; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; /** * diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriterTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriterTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriterTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultComparisonWriterTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java similarity index 99% rename from security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java index 26f7fcb985f..3a8cc71f116 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/comparator/SecurityAnalysisResultEquivalenceTest.java @@ -20,7 +20,7 @@ import com.powsybl.security.LimitViolation; import com.powsybl.security.LimitViolationType; import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.PostContingencyResult; +import com.powsybl.security.results.PostContingencyResult; import com.powsybl.security.SecurityAnalysisResult; /** diff --git a/security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java similarity index 75% rename from security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java index 32b2f6df15f..3ee60bcd16d 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/converter/ExporterTest.java @@ -17,15 +17,18 @@ import com.powsybl.security.extensions.CurrentExtension; import com.powsybl.security.extensions.VoltageExtension; import com.powsybl.security.json.SecurityAnalysisResultDeserializer; +import com.powsybl.security.results.BranchResult; +import com.powsybl.security.results.BusResults; +import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.results.ThreeWindingsTransformerResult; +import org.assertj.core.api.Assertions; import org.junit.Test; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.Properties; +import java.util.*; import java.util.function.BiConsumer; import static org.junit.Assert.*; @@ -54,21 +57,39 @@ private static SecurityAnalysisResult create() { LimitViolation violation6 = new LimitViolation("NHV1_NHV2_2", LimitViolationType.APPARENT_POWER, "20'", 1200, 100, 1.0f, 110.0, Branch.Side.TWO); Contingency contingency = Contingency.builder("contingency") - .addBranch("NHV1_NHV2_2", "VLNHV1") - .addBranch("NHV1_NHV2_1") - .addGenerator("GEN") - .addBusbarSection("BBS1") - .build(); + .addBranch("NHV1_NHV2_2", "VLNHV1") + .addBranch("NHV1_NHV2_1") + .addGenerator("GEN") + .addBusbarSection("BBS1") + .build(); LimitViolationsResult preContingencyResult = new LimitViolationsResult(true, Collections.singletonList(violation1)); PostContingencyResult postContingencyResult = new PostContingencyResult(contingency, true, Arrays.asList(violation2, violation3, violation4, violation5, violation6), Arrays.asList("action1", "action2")); - SecurityAnalysisResult result = new SecurityAnalysisResult(preContingencyResult, Collections.singletonList(postContingencyResult)); - result.setNetworkMetadata(new NetworkMetadata(NETWORK)); + List preContingencyBranchResults = new ArrayList<>(); + preContingencyBranchResults.add(new BranchResult("branchId", 0, 0, 0, 0, 0, 0)); + List preContingencyBusResults = new ArrayList<>(); + preContingencyBusResults.add(new BusResults("voltageLevelId", "busId", 400, 3.14)); + List threeWindingsTransformerResults = new ArrayList<>(); + threeWindingsTransformerResults.add(new ThreeWindingsTransformerResult("threeWindingsTransformerId", + 0, 0, 0, 0, 0, 0, 0, 0, 0)); + SecurityAnalysisResult result = new SecurityAnalysisResult(preContingencyResult, Collections.singletonList(postContingencyResult), + preContingencyBranchResults, preContingencyBusResults, threeWindingsTransformerResults); + result.setNetworkMetadata(new NetworkMetadata(NETWORK)); return result; } + @Test + public void testCompatibilityV1Deserialization() { + LimitViolation violation1 = new LimitViolation("NHV1_NHV2_1", LimitViolationType.CURRENT, null, Integer.MAX_VALUE, 100, 0.95f, 110.0, Branch.Side.ONE); + violation1.addExtension(ActivePowerExtension.class, new ActivePowerExtension(220.0)); + SecurityAnalysisResult result = SecurityAnalysisResultDeserializer.read(getClass().getResourceAsStream("/SecurityAnalysisResultV1.json")); + Assertions.assertThat(result.getPreContingencyLimitViolationsResult().getLimitViolations()).hasSize(1); + assertEquals(0, LimitViolations.comparator().compare(violation1, result.getPreContingencyLimitViolationsResult().getLimitViolations().get(0))); + + } + @Test public void roundTripJson() throws IOException { SecurityAnalysisResult result = create(); diff --git a/security-analysis-api/src/test/java/com/powsybl/security/detectors/DefaultLimitViolationDetectorTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/detectors/DefaultLimitViolationDetectorTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/detectors/DefaultLimitViolationDetectorTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/detectors/DefaultLimitViolationDetectorTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/detectors/LimitViolationDetectorTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/detectors/LimitViolationDetectorTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/detectors/LimitViolationDetectorTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/detectors/LimitViolationDetectorTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java similarity index 69% rename from security-analysis-api/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java index b749375a104..47d76578295 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/DistributedSecurityAnalysisTest.java @@ -16,10 +16,7 @@ import com.powsybl.contingency.ContingenciesProvider; import com.powsybl.contingency.Contingency; import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.VariantManagerConstants; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; -import com.powsybl.security.SecurityAnalysis; -import com.powsybl.security.SecurityAnalysisParameters; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -29,7 +26,6 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -77,32 +73,6 @@ public String asScript() { }; } - /** - * Checks that input files are written to working dir - * and that execution count is correctly set. - */ - @Test - public void testDistributed() throws IOException { - ExternalSecurityAnalysisConfig config = new ExternalSecurityAnalysisConfig(); - SecurityAnalysis analysis = new DistributedSecurityAnalysis(config, network, cm, Collections.emptyList(), 5); - - analysis.run(VariantManagerConstants.INITIAL_VARIANT_ID, new SecurityAnalysisParameters(), contingencies); - - checkInvocationOnExecutionHandler(workingDir); - checkWorkingDirContent(); - } - - @Test - public void testDistributedWithLog() throws IOException { - ExternalSecurityAnalysisConfig config = new ExternalSecurityAnalysisConfig(); - SecurityAnalysis analysis = new DistributedSecurityAnalysis(config, network, cm, Collections.emptyList(), 5); - - analysis.runWithLog(VariantManagerConstants.INITIAL_VARIANT_ID, new SecurityAnalysisParameters(), contingencies); - - checkInvocationOnExecutionHandler(workingDir); - checkWorkingDirContent(); - } - private void checkInvocationOnExecutionHandler(Path workingDir) throws IOException { //Capture the execution handler ArgumentCaptor capt = ArgumentCaptor.forClass(ExecutionHandler.class); @@ -120,29 +90,6 @@ private void checkWorkingDirContent() { assertTrue(Files.exists(workingDir.resolve("parameters.json"))); } - /** - * Checks that input files are written to working dir - * and that execution count is correctly set. - */ - @Test - public void testExternal() throws IOException { - ExternalSecurityAnalysisConfig config = new ExternalSecurityAnalysisConfig(); - SecurityAnalysis analysis = new ExternalSecurityAnalysis(config, network, cm, Collections.emptyList(), 5); - - analysis.run(VariantManagerConstants.INITIAL_VARIANT_ID, new SecurityAnalysisParameters(), contingencies); - - //Capture the execution handler - ArgumentCaptor capt = ArgumentCaptor.forClass(ExecutionHandler.class); - verify(cm, times(1)).execute(any(), capt.capture()); - - //checks methods of the execution handler - List cmd = capt.getValue().before(workingDir); - - checkWorkingDirContent(); - assertEquals(1, cmd.size()); - assertEquals(1, cmd.get(0).getExecutionCount()); - } - /** * Checks config class. */ diff --git a/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptionsTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptionsTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptionsTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisCommandOptionsTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java similarity index 85% rename from security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java index 20425ee754c..c0f6d64518e 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SecurityAnalysisExecutionHandlersTest.java @@ -18,6 +18,7 @@ import com.powsybl.security.*; import com.powsybl.security.converter.JsonSecurityAnalysisResultExporter; import com.powsybl.security.execution.SecurityAnalysisExecutionInput; +import com.powsybl.security.results.PostContingencyResult; import org.apache.commons.lang3.SystemUtils; import org.junit.After; import org.junit.Before; @@ -67,7 +68,7 @@ public void forwardedBeforeWithPartialInput() throws IOException { input.setParameters(new SecurityAnalysisParameters()); input.setNetworkVariant(EurostagTutorialExample1Factory.create(), VariantManagerConstants.INITIAL_VARIANT_ID); - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(input); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(input); List commandExecutions = handler.before(workingDir); @@ -98,12 +99,13 @@ public void forwardedAfter() throws IOException { new JsonSecurityAnalysisResultExporter().export(SecurityAnalysisResult.empty(), writer); } - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(new SecurityAnalysisExecutionInput()); - SecurityAnalysisResult result = handler.after(workingDir, new DefaultExecutionReport(workingDir)); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(new SecurityAnalysisExecutionInput()); + SecurityAnalysisReport report = handler.after(workingDir, new DefaultExecutionReport(workingDir)); + SecurityAnalysisResult result = report.getResult(); assertNotNull(result); - assertTrue(result.getPreContingencyResult().isComputationOk()); - assertTrue(result.getPreContingencyResult().getLimitViolations().isEmpty()); + assertTrue(result.getPreContingencyLimitViolationsResult().isComputationOk()); + assertTrue(result.getPreContingencyLimitViolationsResult().getLimitViolations().isEmpty()); assertTrue(result.getPostContingencyResults().isEmpty()); } @@ -115,7 +117,7 @@ public void forwardedBeforeWithCompleteInput() throws IOException { .setContingenciesSource(ByteSource.wrap("contingencies definition".getBytes(StandardCharsets.UTF_8))) .addResultExtensions(ImmutableList.of("ext1", "ext2")) .addViolationTypes(ImmutableList.of(LimitViolationType.CURRENT)); - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(input, 12); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(input, 12); Path workingDir = fileSystem.getPath("/work"); List commandExecutions = handler.before(workingDir); @@ -144,7 +146,7 @@ public void distributedBefore() throws IOException { .setContingenciesSource(ByteSource.wrap("contingencies definition".getBytes(StandardCharsets.UTF_8))) .addResultExtensions(ImmutableList.of("ext1", "ext2")) .addViolationTypes(ImmutableList.of(LimitViolationType.CURRENT)); - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributed(input, 3); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributed(input, 3); List commandExecutions = handler.before(workingDir); SimpleCommand command = (SimpleCommand) commandExecutions.get(0).getCommand(); @@ -175,8 +177,9 @@ public void distributedBeforeWithLog() throws IOException { SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput() .setParameters(new SecurityAnalysisParameters()) .setNetworkVariant(EurostagTutorialExample1Factory.create(), VariantManagerConstants.INITIAL_VARIANT_ID) - .setContingenciesSource(ByteSource.wrap("contingencies definition".getBytes(StandardCharsets.UTF_8))); - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributedWithLog(input, 3); + .setContingenciesSource(ByteSource.wrap("contingencies definition".getBytes(StandardCharsets.UTF_8))) + .setWithLogs(true); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributed(input, 3); List commandExecutions = handler.before(workingDir); SimpleCommand command = (SimpleCommand) commandExecutions.get(0).getCommand(); @@ -205,8 +208,9 @@ public void forwardedBeforeWithLog() throws IOException { SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput() .setParameters(new SecurityAnalysisParameters()) .setNetworkVariant(EurostagTutorialExample1Factory.create(), VariantManagerConstants.INITIAL_VARIANT_ID) - .setContingenciesSource(ByteSource.wrap("contingencies definition".getBytes(StandardCharsets.UTF_8))); - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwardedWithLogs(input); + .setContingenciesSource(ByteSource.wrap("contingencies definition".getBytes(StandardCharsets.UTF_8))) + .setWithLogs(true); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(input); List commandExecutions = handler.before(workingDir); SimpleCommand command = (SimpleCommand) commandExecutions.get(0).getCommand(); @@ -235,7 +239,7 @@ public void distributedAfter() throws IOException { SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput(); - ExecutionHandler handler3 = SecurityAnalysisExecutionHandlers.distributed(input, 2); + ExecutionHandler handler3 = SecurityAnalysisExecutionHandlers.distributed(input, 2); assertThatExceptionOfType(ComputationException.class).isThrownBy(() -> { Command cmd = Mockito.mock(Command.class); handler3.after(workingDir, new DefaultExecutionReport(workingDir, Collections.singletonList(new ExecutionError(cmd, 0, 42)))); @@ -247,13 +251,13 @@ public void distributedAfter() throws IOException { exporter.export(resultForContingency("c2"), writer); } - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributed(input, 2); - - SecurityAnalysisResult result = handler.after(workingDir, new DefaultExecutionReport(workingDir)); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributed(input, 2); + SecurityAnalysisReport report = handler.after(workingDir, new DefaultExecutionReport(workingDir)); + SecurityAnalysisResult result = report.getResult(); assertNotNull(result); - assertTrue(result.getPreContingencyResult().isComputationOk()); - assertTrue(result.getPreContingencyResult().getLimitViolations().isEmpty()); + assertTrue(result.getPreContingencyLimitViolationsResult().isComputationOk()); + assertTrue(result.getPreContingencyLimitViolationsResult().getLimitViolations().isEmpty()); assertEquals(2, result.getPostContingencyResults().size()); assertEquals("c1", result.getPostContingencyResults().get(0).getContingency().getId()); assertEquals("c2", result.getPostContingencyResults().get(1).getContingency().getId()); @@ -286,8 +290,9 @@ public void distributedAfterWithLogs() throws IOException { Files.write(workingDir.resolve(logFileName), "logs".getBytes(StandardCharsets.UTF_8)); } - SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput(); - ExecutionHandler handler2 = SecurityAnalysisExecutionHandlers.distributedWithLog(input, 2); + SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput() + .setWithLogs(true); + ExecutionHandler handler2 = SecurityAnalysisExecutionHandlers.distributed(input, 2); try { handler2.after(workingDir, new DefaultExecutionReport(workingDir)); fail(); @@ -314,19 +319,19 @@ public void distributedAfterWithLogs() throws IOException { try (Writer writer = Files.newBufferedWriter(workingDir.resolve("task_1_result.json"))) { exporter.export(resultForContingency("c2"), writer); } - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributedWithLog(input, 2); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.distributed(input, 2); - SecurityAnalysisResultWithLog resultWithLog = handler.after(workingDir, new DefaultExecutionReport(workingDir)); - SecurityAnalysisResult result = resultWithLog.getResult(); + SecurityAnalysisReport report = handler.after(workingDir, new DefaultExecutionReport(workingDir)); + SecurityAnalysisResult result = report.getResult(); assertNotNull(result); - assertTrue(result.getPreContingencyResult().isComputationOk()); - assertTrue(result.getPreContingencyResult().getLimitViolations().isEmpty()); + assertTrue(result.getPreContingencyLimitViolationsResult().isComputationOk()); + assertTrue(result.getPreContingencyLimitViolationsResult().getLimitViolations().isEmpty()); assertEquals(2, result.getPostContingencyResults().size()); assertEquals("c1", result.getPostContingencyResults().get(0).getContingency().getId()); assertEquals("c2", result.getPostContingencyResults().get(1).getContingency().getId()); - byte[] logBytes = resultWithLog.getLogBytes() + byte[] logBytes = report.getLogBytes() .orElseThrow(AssertionError::new); Set foundNames = getFileNamesFromZip(logBytes); assertEquals(expectedLogs, foundNames); @@ -344,9 +349,10 @@ public void forwardedAfterWithLogs() throws IOException { Files.write(workingDir.resolve(logFileName), "logs".getBytes(StandardCharsets.UTF_8)); } - SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput(); + SecurityAnalysisExecutionInput input = new SecurityAnalysisExecutionInput() + .setWithLogs(true); - ExecutionHandler handler2 = SecurityAnalysisExecutionHandlers.forwardedWithLogs(input, 2); + ExecutionHandler handler2 = SecurityAnalysisExecutionHandlers.forwarded(input, 2); assertThatExceptionOfType(ComputationException.class) .isThrownBy(() -> handler2.after(workingDir, new DefaultExecutionReport(workingDir))) @@ -357,23 +363,23 @@ public void forwardedAfterWithLogs() throws IOException { assertEquals("logs", ce.getOutLogs().get("security-analysis.out")); }); - ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwardedWithLogs(input, 2); + ExecutionHandler handler = SecurityAnalysisExecutionHandlers.forwarded(input, 2); try (Writer writer = Files.newBufferedWriter(workingDir.resolve("result.json"))) { exporter.export(resultForContingency("c1"), writer); } - SecurityAnalysisResultWithLog resultWithLog = handler.after(workingDir, new DefaultExecutionReport(workingDir)); - SecurityAnalysisResult result = resultWithLog.getResult(); + SecurityAnalysisReport report = handler.after(workingDir, new DefaultExecutionReport(workingDir)); + SecurityAnalysisResult result = report.getResult(); assertNotNull(result); - assertTrue(result.getPreContingencyResult().isComputationOk()); - assertTrue(result.getPreContingencyResult().getLimitViolations().isEmpty()); + assertTrue(result.getPreContingencyLimitViolationsResult().isComputationOk()); + assertTrue(result.getPreContingencyLimitViolationsResult().getLimitViolations().isEmpty()); assertEquals(1, result.getPostContingencyResults().size()); assertEquals("c1", result.getPostContingencyResults().get(0).getContingency().getId()); - assertTrue(resultWithLog.getLogBytes().isPresent()); + assertTrue(report.getLogBytes().isPresent()); - byte[] logBytes = resultWithLog.getLogBytes() + byte[] logBytes = report.getLogBytes() .orElseThrow(AssertionError::new); Set foundNames = getFileNamesFromZip(logBytes); assertEquals(expectedLogs, foundNames); diff --git a/security-analysis-api/src/test/java/com/powsybl/security/distributed/SubContingenciesProviderTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SubContingenciesProviderTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/distributed/SubContingenciesProviderTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/distributed/SubContingenciesProviderTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/execution/NetworkVariantTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/NetworkVariantTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/execution/NetworkVariantTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/NetworkVariantTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java similarity index 65% rename from security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java index 2b411d004a9..33c3beef720 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionBuilderTest.java @@ -6,26 +6,28 @@ */ package com.powsybl.security.execution; +import com.google.auto.service.AutoService; import com.powsybl.computation.ComputationManager; import com.powsybl.computation.Partition; import com.powsybl.contingency.ContingenciesProvider; import com.powsybl.contingency.Contingency; +import com.powsybl.iidm.network.Network; import com.powsybl.security.*; import com.powsybl.security.distributed.DistributedSecurityAnalysisExecution; import com.powsybl.security.distributed.ExternalSecurityAnalysisConfig; import com.powsybl.security.distributed.ForwardedSecurityAnalysisExecution; import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import java.util.Collections; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -34,9 +36,14 @@ */ public class SecurityAnalysisExecutionBuilderTest { - private SecurityAnalysis analysis; - private AtomicReference actualProvider; + private static AtomicReference actualProvider; private SecurityAnalysisExecutionBuilder builder; + private SecurityAnalysisExecutionInput input; + + @BeforeClass + public static void setUpClass() { + actualProvider = new AtomicReference<>(); + } @Before public void setUp() { @@ -44,32 +51,16 @@ public void setUp() { Contingency contingency = new Contingency("cont"); ContingenciesProvider provider = network -> Collections.nCopies(10, contingency); - actualProvider = new AtomicReference<>(); - - analysis = new SecurityAnalysis() { - @Override - public void addInterceptor(SecurityAnalysisInterceptor interceptor) { - } - - @Override - public boolean removeInterceptor(SecurityAnalysisInterceptor interceptor) { - return false; - } - - @Override - public CompletableFuture run(String workingVariantId, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider) { - actualProvider.set(contingenciesProvider); - return null; - } - }; - - SecurityAnalysisFactory factory = mock(SecurityAnalysisFactory.class); - when(factory.create(any(), any(), any(), any(), anyInt())) - .thenReturn(analysis); + NetworkVariant networkVariant = mock(NetworkVariant.class); + Network network = mock(Network.class); + input = mock(SecurityAnalysisExecutionInput.class); + when(input.getNetworkVariant()).thenReturn(networkVariant); + when(networkVariant.getNetwork()).thenReturn(network); + when(networkVariant.getVariantId()).thenReturn("mock"); builder = new SecurityAnalysisExecutionBuilder(ExternalSecurityAnalysisConfig::new, - () -> factory, - execInput -> new SecurityAnalysisInput(Mockito.mock(NetworkVariant.class)) + "ExecutionBuilderTestProvider", + execInput -> new SecurityAnalysisInput(networkVariant) .setContingencies(provider)); } @@ -78,7 +69,7 @@ public void checkLocal() { SecurityAnalysisExecution execution = builder.build(); assertTrue(execution instanceof SecurityAnalysisExecutionImpl); - execution.execute(Mockito.mock(ComputationManager.class), new SecurityAnalysisExecutionInput()); + execution.execute(Mockito.mock(ComputationManager.class), input); assertNotNull(actualProvider.get()); assertEquals(10, actualProvider.get().getContingencies(null).size()); @@ -108,10 +99,28 @@ public void checkSubtaskHasOnly5Contingencies() { SecurityAnalysisExecution execution = builder.subTask(new Partition(1, 2)).build(); assertTrue(execution instanceof SecurityAnalysisExecutionImpl); - execution.execute(Mockito.mock(ComputationManager.class), new SecurityAnalysisExecutionInput()); + execution.execute(Mockito.mock(ComputationManager.class), input); assertNotNull(actualProvider.get()); assertEquals(5, actualProvider.get().getContingencies(null).size()); } + @AutoService(SecurityAnalysisProvider.class) + public static class SecurityAnalysisProviderMock implements SecurityAnalysisProvider { + @Override + public CompletableFuture run(Network network, String workingVariantId, LimitViolationDetector detector, LimitViolationFilter filter, ComputationManager computationManager, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider, List interceptors) { + actualProvider.set(contingenciesProvider); + return null; + } + + @Override + public String getName() { + return "ExecutionBuilderTestProvider"; + } + + @Override + public String getVersion() { + return "1.0"; + } + } } diff --git a/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java new file mode 100644 index 00000000000..2cf6f15d727 --- /dev/null +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionImplTest.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2018, 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/. + */ +package com.powsybl.security.execution; + +import com.google.auto.service.AutoService; +import com.powsybl.commons.PowsyblException; +import com.powsybl.computation.ComputationManager; +import com.powsybl.contingency.ContingenciesProvider; +import com.powsybl.iidm.network.Network; +import com.powsybl.security.*; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * @author Sylvain Leclerc + * @author Thomas Adam + */ +public class SecurityAnalysisExecutionImplTest { + + private static LimitViolationFilter filter; + private static LimitViolationDetector detector; + private static ContingenciesProvider contingencies; + private static SecurityAnalysisParameters parameters; + private static SecurityAnalysisExecution execution; + private static Network network; + private static ComputationManager computationManager; + private static SecurityAnalysisExecutionInput input; + + @BeforeClass + public static void setUpClass() { + filter = Mockito.mock(LimitViolationFilter.class); + detector = Mockito.mock(LimitViolationDetector.class); + contingencies = Mockito.mock(ContingenciesProvider.class); + parameters = Mockito.mock(SecurityAnalysisParameters.class); + + execution = new SecurityAnalysisExecutionImpl(SecurityAnalysis.find("ExecutionImplTestProvider"), + execInput -> new SecurityAnalysisInput(execInput.getNetworkVariant()) + .setFilter(filter) + .setDetector(detector) + .setContingencies(contingencies) + .setParameters(parameters) + ); + + network = mock(Network.class); + computationManager = mock(ComputationManager.class); + input = new SecurityAnalysisExecutionInput(); + input.setNetworkVariant(network, "variantId"); + } + + @Test + public void checkExecutionCallAndArguments() { + assertThrows("run", PowsyblException.class, () -> execution.execute(computationManager, input)); + } + + @Test + public void checkExecutionWithLogCallAndArguments() { + input.setWithLogs(true); + assertThrows("run", PowsyblException.class, () -> execution.execute(computationManager, input)); + } + + @AutoService(SecurityAnalysisProvider.class) + public static class SecurityAnalysisProviderMock implements SecurityAnalysisProvider { + @Override + public CompletableFuture run(Network network, String workingVariantId, LimitViolationDetector detector, LimitViolationFilter filter, ComputationManager computationManager, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider, List interceptors) { + assertSame(SecurityAnalysisExecutionImplTest.network, network); + assertSame(SecurityAnalysisExecutionImplTest.input.getNetworkVariant().getVariantId(), workingVariantId); + assertSame(SecurityAnalysisExecutionImplTest.detector, detector); + assertSame(SecurityAnalysisExecutionImplTest.filter, filter); + assertSame(SecurityAnalysisExecutionImplTest.computationManager, computationManager); + assertSame(SecurityAnalysisExecutionImplTest.parameters, parameters); + assertSame(SecurityAnalysisExecutionImplTest.contingencies, contingenciesProvider); + assertTrue(interceptors.isEmpty()); + throw new PowsyblException("run"); + } + + @Override + public String getName() { + return "ExecutionImplTestProvider"; + } + + @Override + public String getVersion() { + return "1.0"; + } + } +} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionInputTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionInputTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionInputTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/execution/SecurityAnalysisExecutionInputTest.java diff --git a/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonMonitorTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonMonitorTest.java new file mode 100644 index 00000000000..8176a5f791b --- /dev/null +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonMonitorTest.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.json; + +import com.powsybl.commons.AbstractConverterTest; +import com.powsybl.contingency.ContingencyContext; +import com.powsybl.contingency.ContingencyContextType; +import com.powsybl.security.monitor.StateMonitor; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author Etienne Lesot + */ +public class JsonMonitorTest extends AbstractConverterTest { + @Test + public void roundTrip() throws IOException { + List monitors = new ArrayList<>(); + monitors.add(new StateMonitor(new ContingencyContext("contingency1", ContingencyContextType.SPECIFIC), + Collections.singleton("Branch1"), Collections.singleton("Bus1"), Collections.singleton("ThreeWindingsTransformer1"))); + roundTripTest(monitors, StateMonitor::write, StateMonitor::read, "/MonitoringFileTest.json"); + } +} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/json/JsonSecurityAnalysisParametersTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonSecurityAnalysisParametersTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/json/JsonSecurityAnalysisParametersTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/JsonSecurityAnalysisParametersTest.java diff --git a/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/PostContingencyResultTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/PostContingencyResultTest.java new file mode 100644 index 00000000000..eee6e5d2a27 --- /dev/null +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/json/PostContingencyResultTest.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.json; + +import com.powsybl.commons.AbstractConverterTest; +import com.powsybl.commons.json.JsonUtil; +import com.powsybl.contingency.Contingency; +import com.powsybl.security.*; +import com.powsybl.security.results.BranchResult; +import com.powsybl.security.results.BusResults; +import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.results.ThreeWindingsTransformerResult; +import org.junit.Test; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static junit.framework.TestCase.assertEquals; + +/** + * @author Etienne Lesot + */ +public class PostContingencyResultTest extends AbstractConverterTest { + + @Test + public void testGetters() { + Contingency contingency = new Contingency("contingency"); + LimitViolation violation = new LimitViolation("violation", LimitViolationType.HIGH_VOLTAGE, 420, (float) 0.1, 500); + LimitViolationsResult result = new LimitViolationsResult(true, Collections.singletonList(violation)); + Map threeWindingsTransformerResults = new HashMap<>(); + threeWindingsTransformerResults.put("threeWindingsTransformerId", new ThreeWindingsTransformerResult("threeWindingsTransformerId", + 0, 0, 0, 0, 0, 0, 0, 0, 0)); + Map branchResults = new HashMap<>(); + branchResults.put("branchId", new BranchResult("branchId", 0, 0, 0, 0, 0, 0)); + Map busResults = new HashMap<>(); + busResults.put("busId", new BusResults("voltageLevelId", "busId", 400, 3.14)); + PostContingencyResult postContingencyResult = new PostContingencyResult(contingency, result, branchResults, busResults, threeWindingsTransformerResults); + assertEquals(new BranchResult("branchId", 0, 0, 0, 0, 0, 0), postContingencyResult.getBranchResult("branchId")); + assertEquals(new BusResults("voltageLevelId", "busId", 400, 3.14), postContingencyResult.getBusResult("busId")); + assertEquals(new ThreeWindingsTransformerResult("threeWindingsTransformerId", + 0, 0, 0, 0, 0, 0, 0, 0, 0), postContingencyResult.getThreeWindingsTransformerResult("threeWindingsTransformerId")); + } + + @Test + public void roundTrip() throws IOException { + Contingency contingency = new Contingency("contingency"); + LimitViolation violation = new LimitViolation("violation", LimitViolationType.HIGH_VOLTAGE, 420, (float) 0.1, 500); + LimitViolationsResult result = new LimitViolationsResult(true, Collections.singletonList(violation)); + Map threeWindingsTransformerResults = new HashMap<>(); + threeWindingsTransformerResults.put("threeWindingsTransformerId", new ThreeWindingsTransformerResult("threeWindingsTransformerId", + 0, 0, 0, 0, 0, 0, 0, 0, 0)); + Map branchResults = new HashMap<>(); + branchResults.put("branchId", new BranchResult("branchId", 0, 0, 0, 0, 0, 0)); + Map busResults = new HashMap<>(); + busResults.put("busId", new BusResults("voltageLevelId", "busId", 400, 3.14)); + PostContingencyResult postContingencyResult = new PostContingencyResult(contingency, result, branchResults, busResults, threeWindingsTransformerResults); + roundTripTest(postContingencyResult, this::write, this::read, "/PostContingencyResultTest.json"); + } + + public void write(PostContingencyResult postContingencyResult, Path jsonFile) { + try { + OutputStream out = Files.newOutputStream(jsonFile); + JsonUtil.createObjectMapper() + .registerModule(new SecurityAnalysisJsonModule()) + .writer() + .writeValue(out, postContingencyResult); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public PostContingencyResult read(Path jsonFile) { + try { + return JsonUtil.createObjectMapper() + .registerModule(new SecurityAnalysisJsonModule()) + .readerFor(PostContingencyResult.class) + .readValue(Files.newInputStream(jsonFile)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorsTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorsTest.java similarity index 100% rename from security-analysis-api/src/test/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorsTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/preprocessor/SecurityAnalysisPreprocessorsTest.java diff --git a/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java similarity index 68% rename from security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java rename to security-analysis/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java index 4ee3b477ac1..b0993ae0cd5 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java +++ b/security-analysis/security-analysis-api/src/test/java/com/powsybl/security/tools/SecurityAnalysisToolTest.java @@ -6,18 +6,22 @@ */ package com.powsybl.security.tools; +import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.io.ByteSource; import com.powsybl.commons.io.table.TableFormatterConfig; import com.powsybl.computation.ComputationException; +import com.powsybl.computation.ComputationExceptionBuilder; import com.powsybl.computation.ComputationManager; +import com.powsybl.contingency.ContingenciesProvider; import com.powsybl.iidm.import_.ImportersLoaderList; import com.powsybl.iidm.network.Network; import com.powsybl.security.*; import com.powsybl.security.distributed.ExternalSecurityAnalysisConfig; import com.powsybl.security.execution.SecurityAnalysisExecutionBuilder; import com.powsybl.security.execution.SecurityAnalysisExecutionInput; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; import com.powsybl.security.preprocessor.SecurityAnalysisPreprocessor; import com.powsybl.security.preprocessor.SecurityAnalysisPreprocessorFactory; import com.powsybl.tools.AbstractToolTest; @@ -32,16 +36,14 @@ import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; -import java.util.Collections; -import java.util.Map; -import java.util.Properties; -import java.util.Set; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.junit.Assert.*; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; /** @@ -49,6 +51,8 @@ */ public class SecurityAnalysisToolTest extends AbstractToolTest { + private static final String OUTPUT_LOG_FILENAME = "out.zip"; + private SecurityAnalysisTool tool; @Override @@ -66,7 +70,7 @@ protected Iterable getTools() { @Override public void assertCommand() { - assertCommand(tool.getCommand(), "security-analysis", 13, 1); + assertCommand(tool.getCommand(), "security-analysis", 14, 1); assertOption(tool.getCommand().getOptions(), "case-file", true, true); assertOption(tool.getCommand().getOptions(), "parameters-file", false, true); assertOption(tool.getCommand().getOptions(), "limit-types", false, true); @@ -78,6 +82,7 @@ public void assertCommand() { assertOption(tool.getCommand().getOptions(), "task", false, true); assertOption(tool.getCommand().getOptions(), "external", false, false); assertOption(tool.getCommand().getOptions(), "log-file", false, true); + assertOption(tool.getCommand().getOptions(), "monitoring-file", false, true); } @Test @@ -184,49 +189,97 @@ public void testRunWithLog() throws Exception { PrintStream err = new PrintStream(berr); ComputationManager cm = mock(ComputationManager.class)) { CommandLine cl = mockCommandLine(ImmutableMap.of("case-file", "network.xml", - "log-file", "out.zip"), ImmutableSet.of("skip-postproc")); + SecurityAnalysisToolConstants.OUTPUT_LOG_OPTION, OUTPUT_LOG_FILENAME), ImmutableSet.of("skip-postproc")); ToolRunningContext context = new ToolRunningContext(out, err, fileSystem, cm, cm); - SecurityAnalysisFactory saFactory = new SecurityAnalysisMockFactory(); - SecurityAnalysis sa = saFactory.create(null, cm, 1); - - SecurityAnalysisExecutionBuilder builder = new SecurityAnalysisExecutionBuilder(ExternalSecurityAnalysisConfig::new, - () -> saFactory, + SecurityAnalysisExecutionBuilder builderRun = new SecurityAnalysisExecutionBuilder(ExternalSecurityAnalysisConfig::new, + "SecurityAnalysisToolProviderMock", executionInput -> new SecurityAnalysisInput(executionInput.getNetworkVariant())); - // execute - tool.run(cl, context, builder, + // Check runWithLog execution + tool.run(cl, context, builderRun, SecurityAnalysisParameters::new, new ImportersLoaderList(new NetworkImporterMock()), TableFormatterConfig::new); + // Check log-file creation + Path logPath = context.getFileSystem().getPath(OUTPUT_LOG_FILENAME); + assertTrue(Files.exists(logPath)); + // Need to clean for next test + Files.delete(logPath); - // verify that runWithLog() called instead of run(); - verify(sa, never()).run(any(), any(), any()); - verify(sa, times(1)).runWithLog(any(), any(), any()); - + // Check run execution when(cl.hasOption("log-file")).thenReturn(false); - // execute - tool.run(cl, context, builder, + + tool.run(cl, context, builderRun, SecurityAnalysisParameters::new, new ImportersLoaderList(new NetworkImporterMock()), TableFormatterConfig::new); - verify(sa, times(1)).run(any(), any(), any()); + + // Check no log-file creation + assertFalse(Files.exists(logPath)); // exception happens - SecurityAnalysisFactory saFactory2 = new SecurityAnalysisMockFactory(true); - SecurityAnalysisExecutionBuilder builder2 = new SecurityAnalysisExecutionBuilder(ExternalSecurityAnalysisConfig::new, - () -> saFactory2, + SecurityAnalysisExecutionBuilder builderException = new SecurityAnalysisExecutionBuilder(ExternalSecurityAnalysisConfig::new, + "SecurityAnalysisToolExceptionProviderMock", executionInput -> new SecurityAnalysisInput(executionInput.getNetworkVariant())); try { - tool.run(cl, context, builder2, + tool.run(cl, context, builderException, SecurityAnalysisParameters::new, new ImportersLoaderList(new NetworkImporterMock()), TableFormatterConfig::new); fail(); } catch (CompletionException exception) { assertTrue(exception.getCause() instanceof ComputationException); + assertEquals("outLog", ((ComputationException) exception.getCause()).getOutLogs().get("out")); + assertEquals("errLog", ((ComputationException) exception.getCause()).getErrLogs().get("err")); } } } + + @AutoService(SecurityAnalysisProvider.class) + public static class SecurityAnalysisProviderMock implements SecurityAnalysisProvider { + @Override + public CompletableFuture run(Network network, String workingVariantId, LimitViolationDetector detector, LimitViolationFilter filter, ComputationManager computationManager, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider, List interceptors) { + CompletableFuture cfSar = mock(CompletableFuture.class); + SecurityAnalysisReport report = mock(SecurityAnalysisReport.class); + when(report.getResult()).thenReturn(mock(SecurityAnalysisResult.class)); + when(report.getResult().getPreContingencyLimitViolationsResult()).thenReturn(mock(LimitViolationsResult.class)); + when(report.getLogBytes()).thenReturn(Optional.of("Hello world".getBytes())); + when(cfSar.join()).thenReturn(report); + return cfSar; + } + + @Override + public String getName() { + return "SecurityAnalysisToolProviderMock"; + } + + @Override + public String getVersion() { + return "1.0"; + } + } + + @AutoService(SecurityAnalysisProvider.class) + public static class SecurityAnalysisExceptionProviderMock implements SecurityAnalysisProvider { + @Override + public CompletableFuture run(Network network, String workingVariantId, LimitViolationDetector detector, LimitViolationFilter filter, ComputationManager computationManager, SecurityAnalysisParameters parameters, ContingenciesProvider contingenciesProvider, List interceptors) { + ComputationExceptionBuilder ceb = new ComputationExceptionBuilder(new RuntimeException("test")); + ceb.addOutLog("out", "outLog") + .addErrLog("err", "errLog"); + ComputationException computationException = ceb.build(); + throw new CompletionException(computationException); + } + + @Override + public String getName() { + return "SecurityAnalysisToolExceptionProviderMock"; + } + + @Override + public String getVersion() { + return "1.0"; + } + } } diff --git a/security-analysis/security-analysis-api/src/test/resources/MonitoringFileTest.json b/security-analysis/security-analysis-api/src/test/resources/MonitoringFileTest.json new file mode 100644 index 00000000000..f66e7d0803d --- /dev/null +++ b/security-analysis/security-analysis-api/src/test/resources/MonitoringFileTest.json @@ -0,0 +1 @@ +[{"contingencyContext":{"contingencyId":"contingency1","contextType":"SPECIFIC"},"branchIds":["Branch1"],"voltageLevelIds":["Bus1"],"threeWindingsTransformerIds":["ThreeWindingsTransformer1"]}] \ No newline at end of file diff --git a/security-analysis/security-analysis-api/src/test/resources/PostContingencyResultTest.json b/security-analysis/security-analysis-api/src/test/resources/PostContingencyResultTest.json new file mode 100644 index 00000000000..19e9393cd5d --- /dev/null +++ b/security-analysis/security-analysis-api/src/test/resources/PostContingencyResultTest.json @@ -0,0 +1 @@ +{"contingency":{"id":"contingency","elements":[]},"limitViolationsResult":{"computationOk":true,"limitViolations":[{"subjectId":"violation","limitType":"HIGH_VOLTAGE","limit":420.0,"limitReduction":0.1,"value":500.0}],"actionsTaken":[]},"branchResults":[{"branchId":"branchId","p1":0.0,"q1":0.0,"i1":0.0,"p2":0.0,"q2":0.0,"i2":0.0}],"busResults":[{"voltageLevelId":"voltageLevelId","busId":"busId","v":400.0,"angle":3.14}],"threeWindingsTransformerResults":[{"threeWindingsTransformerId":"threeWindingsTransformerId","p1":0.0,"q1":0.0,"i1":0.0,"p2":0.0,"q2":0.0,"i2":0.0,"p3":0.0,"q3":0.0,"i3":0.0}]} \ No newline at end of file diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisParameters.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParameters.json similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisParameters.json rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParameters.json diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisParametersExtensionUpdate.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersExtensionUpdate.json similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisParametersExtensionUpdate.json rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersExtensionUpdate.json diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisParametersIncomplete.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersIncomplete.json similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisParametersIncomplete.json rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersIncomplete.json diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisParametersInvalid.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersInvalid.json similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisParametersInvalid.json rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersInvalid.json diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisParametersWithExtension.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersWithExtension.json similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisParametersWithExtension.json rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisParametersWithExtension.json diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisResult.csv b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.csv similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisResult.csv rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.csv diff --git a/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.json new file mode 100644 index 00000000000..fc9c06cd5e1 --- /dev/null +++ b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.json @@ -0,0 +1,135 @@ +{ + "version" : "1.1", + "network" : { + "id" : "sim1", + "sourceFormat" : "test", + "caseDate" : "2018-01-01T11:00:00.000+01:00", + "forecastDistance" : 0 + }, + "preContingencyResult" : { + "limitViolationsResult" : { + "computationOk" : true, + "limitViolations" : [ { + "subjectId" : "NHV1_NHV2_1", + "limitType" : "CURRENT", + "limit" : 100.0, + "limitReduction" : 0.95, + "value" : 110.0, + "side" : "ONE", + "extensions" : { + "ActivePower" : { + "value" : 220.0 + } + } + } ], + "actionsTaken" : [ ] + }, + "branchResults" : [ { + "branchId" : "branchId", + "p1" : 0.0, + "q1" : 0.0, + "i1" : 0.0, + "p2" : 0.0, + "q2" : 0.0, + "i2" : 0.0 + } ], + "busResults" : [ { + "voltageLevelId" : "voltageLevelId", + "busId" : "busId", + "v" : 400.0, + "angle" : 3.14 + } ], + "threeWindingsTransformerResults" : [ { + "threeWindingsTransformerId" : "threeWindingsTransformerId", + "p1" : 0.0, + "q1" : 0.0, + "i1" : 0.0, + "p2" : 0.0, + "q2" : 0.0, + "i2" : 0.0, + "p3" : 0.0, + "q3" : 0.0, + "i3" : 0.0 + } ] + }, + "postContingencyResults" : [ { + "contingency" : { + "id" : "contingency", + "elements" : [ { + "id" : "NHV1_NHV2_2", + "type" : "BRANCH", + "voltageLevelId" : "VLNHV1" + }, { + "id" : "NHV1_NHV2_1", + "type" : "BRANCH" + }, { + "id" : "GEN", + "type" : "GENERATOR" + }, { + "id" : "BBS1", + "type" : "BUSBAR_SECTION" + } ] + }, + "limitViolationsResult" : { + "computationOk" : true, + "limitViolations" : [ { + "subjectId" : "NHV1_NHV2_2", + "limitType" : "CURRENT", + "limitName" : "20'", + "acceptableDuration" : 1200, + "limit" : 100.0, + "limitReduction" : 1.0, + "value" : 110.0, + "side" : "TWO", + "extensions" : { + "ActivePower" : { + "preContingencyValue" : 220.0, + "postContingencyValue" : 230.0 + }, + "Current" : { + "preContingencyValue" : 95.0 + } + } + }, { + "subjectId" : "GEN", + "limitType" : "HIGH_VOLTAGE", + "limit" : 100.0, + "limitReduction" : 0.9, + "value" : 110.0 + }, { + "subjectId" : "GEN2", + "limitType" : "LOW_VOLTAGE", + "limit" : 100.0, + "limitReduction" : 0.7, + "value" : 115.0, + "extensions" : { + "Voltage" : { + "preContingencyValue" : 400.0 + } + } + }, { + "subjectId" : "NHV1_NHV2_2", + "limitType" : "ACTIVE_POWER", + "limitName" : "20'", + "acceptableDuration" : 1200, + "limit" : 100.0, + "limitReduction" : 1.0, + "value" : 110.0, + "side" : "ONE" + }, { + "subjectId" : "NHV1_NHV2_2", + "limitType" : "APPARENT_POWER", + "limitName" : "20'", + "acceptableDuration" : 1200, + "limit" : 100.0, + "limitReduction" : 1.0, + "value" : 110.0, + "side" : "TWO" + } ], + "actionsTaken" : [ "action1", "action2" ] + }, + "branchResults" : [ ], + "busResults" : [ ], + "threeWindingsTransformerResults" : [ ] + } ] +} \ No newline at end of file diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisResult.txt b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.txt similarity index 100% rename from security-analysis-api/src/test/resources/SecurityAnalysisResult.txt rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResult.txt diff --git a/security-analysis-api/src/test/resources/SecurityAnalysisResult.json b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResultV1.json similarity index 68% rename from security-analysis-api/src/test/resources/SecurityAnalysisResult.json rename to security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResultV1.json index 65a8fd69279..d6090a3519e 100644 --- a/security-analysis-api/src/test/resources/SecurityAnalysisResult.json +++ b/security-analysis/security-analysis-api/src/test/resources/SecurityAnalysisResultV1.json @@ -7,22 +7,22 @@ "forecastDistance" : 0 }, "preContingencyResult" : { - "computationOk" : true, - "limitViolations" : [ { - "subjectId" : "NHV1_NHV2_1", - "limitType" : "CURRENT", - "limit" : 100.0, - "limitReduction" : 0.95, - "value" : 110.0, - "side" : "ONE", - "extensions" : { - "ActivePower" : { - "value" : 220.0 + "computationOk" : true, + "limitViolations" : [ { + "subjectId" : "NHV1_NHV2_1", + "limitType" : "CURRENT", + "limit" : 100.0, + "limitReduction" : 0.95, + "value" : 110.0, + "side" : "ONE", + "extensions" : { + "ActivePower" : { + "value" : 220.0 + } } - } - } ], - "actionsTaken" : [ ] - }, + } ], + "actionsTaken" : [ ] + }, "postContingencyResults" : [ { "contingency" : { "id" : "contingency", @@ -78,26 +78,11 @@ "preContingencyValue" : 400.0 } } - }, { - "subjectId" : "NHV1_NHV2_2", - "limitType" : "ACTIVE_POWER", - "limitName" : "20'", - "acceptableDuration" : 1200, - "limit" : 100.0, - "limitReduction" : 1.0, - "value" : 110.0, - "side" : "ONE" - }, { - "subjectId" : "NHV1_NHV2_2", - "limitType" : "APPARENT_POWER", - "limitName" : "20'", - "acceptableDuration" : 1200, - "limit" : 100.0, - "limitReduction" : 1.0, - "value" : 110.0, - "side" : "TWO" } ], "actionsTaken" : [ "action1", "action2" ] - } + }, + "branchResults" : [ ], + "busResults" : [ ], + "threeWindingsTransformerResults" : [ ] } ] } \ No newline at end of file diff --git a/security-analysis/security-analysis-default/pom.xml b/security-analysis/security-analysis-default/pom.xml new file mode 100644 index 00000000000..bbf6b4cdbdc --- /dev/null +++ b/security-analysis/security-analysis-default/pom.xml @@ -0,0 +1,154 @@ + + + + 4.0.0 + + + com.powsybl + powsybl-security-analysis + 4.3.0-SNAPSHOT + + + powsybl-security-analysis-default + Security Analysis Default Implementation + A default implementation to run security analysis + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.powsybl.security.analysis.defaultimpl + + + + + + + test-jar + + + + + + + + + + + com.fasterxml.jackson.core + jackson-databind + + + ${project.groupId} + powsybl-contingency-api + ${project.version} + + + ${project.groupId} + powsybl-iidm-api + ${project.version} + + + ${project.groupId} + powsybl-iidm-converter-api + ${project.version} + + + ${project.groupId} + powsybl-iidm-xml-converter + ${project.version} + + + ${project.groupId} + powsybl-loadflow-api + ${project.version} + + + ${project.groupId} + powsybl-security-analysis-api + ${project.version} + + + + + com.google.jimfs + jimfs + test + + + junit + junit + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + org.slf4j + log4j-over-slf4j + test + + + org.slf4j + slf4j-simple + test + + + ${project.groupId} + powsybl-commons + ${project.version} + test-jar + test + + + ${project.groupId} + powsybl-config-test + ${project.version} + test + + + ${project.groupId} + powsybl-iidm-impl + ${project.version} + test + + + ${project.groupId} + powsybl-iidm-test + ${project.version} + test + + + ${project.groupId} + powsybl-tools + ${project.version} + test + test-jar + + + com.google.guava + guava-testlib + + + + diff --git a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisImpl.java b/security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysis.java similarity index 52% rename from security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisImpl.java rename to security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysis.java index 27283379461..708119a413f 100644 --- a/security-analysis-api/src/main/java/com/powsybl/security/SecurityAnalysisImpl.java +++ b/security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysis.java @@ -4,27 +4,35 @@ * 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/. */ -package com.powsybl.security; +package com.powsybl.security.impl; import com.powsybl.commons.config.PlatformConfig; import com.powsybl.commons.exceptions.UncheckedInterruptedException; import com.powsybl.computation.ComputationManager; import com.powsybl.contingency.ContingenciesProvider; import com.powsybl.contingency.Contingency; -import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.*; import com.powsybl.loadflow.LoadFlow; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.loadflow.LoadFlowResult; -import com.powsybl.security.detectors.DefaultLimitViolationDetector; +import com.powsybl.security.*; import com.powsybl.security.interceptors.CurrentLimitViolationInterceptor; +import com.powsybl.security.interceptors.RunningContext; import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.monitor.StateMonitor; +import com.powsybl.security.monitor.StateMonitorIndex; +import com.powsybl.security.results.BranchResult; +import com.powsybl.security.results.BusResults; +import com.powsybl.security.results.ThreeWindingsTransformerResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.UUID; import java.util.concurrent.*; +import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -32,9 +40,9 @@ * @author Geoffroy Jamgotchian * @author Teofil Calin BANC */ -public class SecurityAnalysisImpl extends AbstractSecurityAnalysis { +public class DefaultSecurityAnalysis { - private static final Logger LOGGER = LoggerFactory.getLogger(SecurityAnalysisImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSecurityAnalysis.class); /** * This executor is used to create the variants of the network, submit the tasks @@ -59,9 +67,9 @@ public class SecurityAnalysisImpl extends AbstractSecurityAnalysis { */ private static int getOptionalIntProperty(String moduleName, String propertyName, int defaultValue) { return PlatformConfig.defaultConfig() - .getOptionalModuleConfig(moduleName) - .map(m -> m.getOptionalIntProperty(propertyName).orElse(defaultValue)) - .orElse(defaultValue); + .getOptionalModuleConfig(moduleName) + .map(m -> m.getOptionalIntProperty(propertyName).orElse(defaultValue)) + .orElse(defaultValue); } private static ExecutorService createThreadPool(int poolSize) { @@ -72,37 +80,37 @@ private static ExecutorService createThreadPool(int poolSize) { } private final ComputationManager computationManager; - - public SecurityAnalysisImpl(Network network, ComputationManager computationManager) { - this(network, new LimitViolationFilter(), computationManager); - } - - public SecurityAnalysisImpl(Network network, LimitViolationFilter filter, - ComputationManager computationManager) { - this(network, new DefaultLimitViolationDetector(), filter, computationManager); - } - - public SecurityAnalysisImpl(Network network, LimitViolationDetector detector, - LimitViolationFilter filter, ComputationManager computationManager) { - super(network, detector, filter); - + private final Network network; + private final LimitViolationDetector violationDetector; + private final LimitViolationFilter violationFilter; + private final List interceptors; + private final StateMonitorIndex monitorIndex; + + public DefaultSecurityAnalysis(Network network, LimitViolationDetector detector, + LimitViolationFilter filter, ComputationManager computationManager, + List monitors) { + this.network = Objects.requireNonNull(network); + this.violationDetector = Objects.requireNonNull(detector); + this.violationFilter = Objects.requireNonNull(filter); + this.interceptors = new ArrayList<>(); this.computationManager = Objects.requireNonNull(computationManager); - + this.monitorIndex = new StateMonitorIndex(monitors); interceptors.add(new CurrentLimitViolationInterceptor()); } - @Override public void addInterceptor(SecurityAnalysisInterceptor interceptor) { interceptors.add(Objects.requireNonNull(interceptor)); } - @Override public boolean removeInterceptor(SecurityAnalysisInterceptor interceptor) { return interceptors.remove(interceptor); } - @Override - public CompletableFuture run(String workingVariantId, + private SecurityAnalysisResultBuilder createResultBuilder(String initialWorkingStateId) { + return new SecurityAnalysisResultBuilder(violationFilter, new RunningContext(network, initialWorkingStateId), interceptors); + } + + public CompletableFuture run(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, ContingenciesProvider contingenciesProvider) { Objects.requireNonNull(workingVariantId); Objects.requireNonNull(securityAnalysisParameters); @@ -112,32 +120,34 @@ public CompletableFuture run(String workingVariantId, // start post contingency LF from pre-contingency state variables LoadFlowParameters postContParameters = loadFlowParameters.copy() - .setVoltageInitMode(LoadFlowParameters.VoltageInitMode.PREVIOUS_VALUES); + .setVoltageInitMode(LoadFlowParameters.VoltageInitMode.PREVIOUS_VALUES); SecurityAnalysisResultBuilder resultBuilder = createResultBuilder(workingVariantId); return LoadFlow - .runAsync(network, workingVariantId, computationManager, loadFlowParameters) - .thenCompose(loadFlowResult -> { - if (loadFlowResult.isOk()) { - return CompletableFuture - .runAsync(() -> { - network.getVariantManager().setWorkingVariant(workingVariantId); - setPreContigencyOkAndCheckViolations(resultBuilder); - }, computationManager.getExecutor()) - .thenComposeAsync(aVoid -> - submitAllLoadFlows(workingVariantId, contingenciesProvider, postContParameters, resultBuilder), - SCHEDULER_EXECUTOR); - } else { - return setPreContingencyKo(resultBuilder); - } - }) - .thenApply(aVoid -> resultBuilder.build()); + .runAsync(network, workingVariantId, computationManager, loadFlowParameters) + .thenCompose(loadFlowResult -> { + if (loadFlowResult.isOk()) { + return CompletableFuture + .runAsync(() -> { + network.getVariantManager().setWorkingVariant(workingVariantId); + setPreContigencyOkAndCheckViolations(resultBuilder); + }, computationManager.getExecutor()) + .thenComposeAsync(aVoid -> + submitAllLoadFlows(workingVariantId, contingenciesProvider, postContParameters, resultBuilder), + SCHEDULER_EXECUTOR); + } else { + return setPreContingencyKo(resultBuilder); + } + }) + .thenApply(aVoid -> new SecurityAnalysisReport(resultBuilder.build())); } private void setPreContigencyOkAndCheckViolations(SecurityAnalysisResultBuilder resultBuilder) { SecurityAnalysisResultBuilder.PreContingencyResultBuilder builder = resultBuilder.preContingency().setComputationOk(true); violationDetector.checkAll(network, builder::addViolation); + addMonitorInfos(network, monitorIndex.getAllStateMonitor(), builder::addBranchResult, builder::addBusResult, builder::addThreeWindingsTransformerResult); + addMonitorInfos(network, monitorIndex.getNoneStateMonitor(), builder::addBranchResult, builder::addBusResult, builder::addThreeWindingsTransformerResult); builder.endPreContingency(); } @@ -159,10 +169,10 @@ private CompletableFuture submitAllLoadFlows(String workingVariantId, network.getVariantManager().cloneVariant(workingVariantId, variantIds); return CompletableFuture - .allOf(contingencies.stream() - .map(contingency -> submitOneLoadFlow(workingVariantId, contingency, postContParameters, resultBuilder, queue)) - .toArray(CompletableFuture[]::new)) - .whenComplete((aVoid, throwable) -> variantIds.forEach(network.getVariantManager()::removeVariant)); + .allOf(contingencies.stream() + .map(contingency -> submitOneLoadFlow(workingVariantId, contingency, postContParameters, resultBuilder, queue)) + .toArray(CompletableFuture[]::new)) + .whenComplete((aVoid, throwable) -> variantIds.forEach(network.getVariantManager()::removeVariant)); } private static List makeWorkingVariantsNames(int workerCount) { @@ -177,7 +187,7 @@ private CompletableFuture submitOneLoadFlow(String workingVariantId, Conti return CompletableFuture.completedFuture(null).thenCompose(aaVoid -> { String postContVariantId = getVariantId(queue); return runOneLoadFlowAsync(workingVariantId, postContVariantId, postContParameters, resultBuilder, contingency) - .whenComplete((aVoid, throwable) -> queue.add(postContVariantId)); + .whenComplete((aVoid, throwable) -> queue.add(postContVariantId)); }); } @@ -193,17 +203,17 @@ private static String getVariantId(BlockingQueue queue) { private CompletableFuture runOneLoadFlowAsync(String workingVariantId, String postContVariantId, LoadFlowParameters postContParameters, SecurityAnalysisResultBuilder resultBuilder, Contingency contingency) { return CompletableFuture - .runAsync(() -> { - LOGGER.debug("Worker {} run loadflow for contingency '{}'.", postContVariantId, contingency.getId()); - applyContingency(workingVariantId, postContVariantId, contingency); - }, computationManager.getExecutor()) - .thenCompose(aVoid -> - LoadFlow.runAsync(network, postContVariantId, computationManager, postContParameters) - ) - .thenApplyAsync(lfResult -> { - setContingencyOkAndCheckViolations(postContVariantId, resultBuilder, contingency, lfResult); - return null; - }, computationManager.getExecutor()); + .runAsync(() -> { + LOGGER.debug("Worker {} run loadflow for contingency '{}'.", postContVariantId, contingency.getId()); + applyContingency(workingVariantId, postContVariantId, contingency); + }, computationManager.getExecutor()) + .thenCompose(aVoid -> + LoadFlow.runAsync(network, postContVariantId, computationManager, postContParameters) + ) + .thenApplyAsync(lfResult -> { + setContingencyOkAndCheckViolations(postContVariantId, resultBuilder, contingency, lfResult); + return null; + }, computationManager.getExecutor()); } private void setContingencyOkAndCheckViolations(String postContVariantId, SecurityAnalysisResultBuilder resultBuilder, @@ -212,6 +222,11 @@ private void setContingencyOkAndCheckViolations(String postContVariantId, Securi SecurityAnalysisResultBuilder.PostContingencyResultBuilder builder = resultBuilder.contingency(contingency).setComputationOk(lfResult.isOk()); if (lfResult.isOk()) { violationDetector.checkAll(contingency, network, builder::addViolation); + addMonitorInfos(network, monitorIndex.getAllStateMonitor(), builder::addBranchResult, builder::addBusResult, builder::addThreeWindingsTransformerResult); + StateMonitor stateMonitor = monitorIndex.getSpecificStateMonitors().get(contingency.getId()); + if (stateMonitor != null) { + addMonitorInfos(network, stateMonitor, builder::addBranchResult, builder::addBusResult, builder::addThreeWindingsTransformerResult); + } } builder.endContingency(); } @@ -222,4 +237,44 @@ private void applyContingency(String workingVariantId, String postContVariantId, contingency.toTask().modify(network, computationManager); } + private void addMonitorInfos(Network network, StateMonitor monitor, Consumer branchResultConsumer, + Consumer busResultsConsumer, Consumer threeWindingsTransformerResultConsumer) { + monitor.getBranchIds().forEach(branchId -> { + Branch branch = network.getBranch(branchId); + if (branch != null) { + branchResultConsumer.accept(createBranchResult(network.getBranch(branchId))); + } + }); + monitor.getVoltageLevelIds().forEach(voltageLevelId -> { + VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId); + if (voltageLevel != null) { + voltageLevel.getBusView().getBuses().forEach(bus -> + busResultsConsumer.accept(createBusResult(bus, voltageLevelId))); + } + }); + monitor.getThreeWindingsTransformerIds().forEach(threeWindingsTransformerId -> { + ThreeWindingsTransformer twt = network.getThreeWindingsTransformer(threeWindingsTransformerId); + if (twt != null) { + threeWindingsTransformerResultConsumer + .accept(createThreeWindingsTransformerResult(twt)); + } + }); + } + + private BranchResult createBranchResult(Branch branch) { + return new BranchResult(branch.getId(), branch.getTerminal1().getP(), branch.getTerminal1().getQ(), branch.getTerminal1().getI(), + branch.getTerminal2().getP(), branch.getTerminal2().getQ(), branch.getTerminal2().getI()); + } + + private BusResults createBusResult(Bus bus, String voltageLevelId) { + return new BusResults(voltageLevelId, bus.getId(), bus.getV(), bus.getAngle()); + } + + private ThreeWindingsTransformerResult createThreeWindingsTransformerResult(ThreeWindingsTransformer threeWindingsTransformer) { + return new ThreeWindingsTransformerResult(threeWindingsTransformer.getId(), threeWindingsTransformer.getLeg1().getTerminal().getP(), + threeWindingsTransformer.getLeg1().getTerminal().getQ(), threeWindingsTransformer.getLeg1().getTerminal().getI(), + threeWindingsTransformer.getLeg2().getTerminal().getP(), threeWindingsTransformer.getLeg2().getTerminal().getQ(), threeWindingsTransformer.getLeg2().getTerminal().getI(), + threeWindingsTransformer.getLeg3().getTerminal().getP(), threeWindingsTransformer.getLeg3().getTerminal().getQ(), threeWindingsTransformer.getLeg3().getTerminal().getI()); + } + } diff --git a/security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysisProvider.java b/security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysisProvider.java new file mode 100644 index 00000000000..95b0e4b73df --- /dev/null +++ b/security-analysis/security-analysis-default/src/main/java/com/powsybl/security/impl/DefaultSecurityAnalysisProvider.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2020, 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/. + */ +package com.powsybl.security.impl; + +import com.google.auto.service.AutoService; +import com.powsybl.computation.ComputationManager; +import com.powsybl.contingency.ContingenciesProvider; +import com.powsybl.iidm.network.Network; +import com.powsybl.security.*; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.monitor.StateMonitor; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * @author Thomas Adam + */ +@AutoService(SecurityAnalysisProvider.class) +public class DefaultSecurityAnalysisProvider implements SecurityAnalysisProvider { + + private static final String PROVIDER_NAME = "DefaultSecurityAnalysis"; + private static final String PROVIDER_VERSION = "1.0"; + + @Override + public CompletableFuture run(Network network, + String workingVariantId, + LimitViolationDetector detector, + LimitViolationFilter filter, + ComputationManager computationManager, + SecurityAnalysisParameters parameters, + ContingenciesProvider contingenciesProvider, + List interceptors, List monitors) { + DefaultSecurityAnalysis securityAnalysis = new DefaultSecurityAnalysis(network, detector, filter, computationManager, monitors); + interceptors.forEach(securityAnalysis::addInterceptor); + return securityAnalysis.run(workingVariantId, parameters, contingenciesProvider); + } + + @Override + public String getName() { + return PROVIDER_NAME; + } + + @Override + public String getVersion() { + return PROVIDER_VERSION; + } +} diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisProviderTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisProviderTest.java new file mode 100644 index 00000000000..afafc974c58 --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisProviderTest.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2020, 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/. + */ +package com.powsybl.security.impl; + +import com.powsybl.computation.ComputationManager; +import com.powsybl.computation.local.LocalComputationManagerFactory; +import com.powsybl.contingency.ContingenciesProvider; +import com.powsybl.contingency.EmptyContingencyListProvider; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.VariantManager; +import com.powsybl.security.*; +import com.powsybl.security.detectors.DefaultLimitViolationDetector; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.monitor.StateMonitor; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.*; + +/** + * @author Thomas Adam + */ +public class SecurityAnalysisProviderTest { + + private static final String DEFAULT_PROVIDER_NAME = "DefaultSecurityAnalysis"; + + private Network network; + private LimitViolationDetector detector; + private LimitViolationFilter filter; + private ComputationManager computationManager; + private SecurityAnalysisParameters parameters; + private ContingenciesProvider contingenciesProvider; + private List interceptors; + private List monitors; + + @Before + public void setUp() { + network = Mockito.mock(Network.class); + VariantManager variantManager = Mockito.mock(VariantManager.class); + Mockito.when(network.getVariantManager()).thenReturn(variantManager); + Mockito.when(variantManager.getWorkingVariantId()).thenReturn("v"); + detector = new DefaultLimitViolationDetector(); + filter = Mockito.mock(LimitViolationFilter.class); + computationManager = new LocalComputationManagerFactory().create(); + parameters = SecurityAnalysisParameters.load(); + contingenciesProvider = new EmptyContingencyListProvider(); + interceptors = Collections.emptyList(); + monitors = Collections.emptyList(); + + } + + @Test + public void testDefaultProvider() { + SecurityAnalysis.Runner defaultSecurityAnalysisRunner = SecurityAnalysis.find(); + assertEquals(DEFAULT_PROVIDER_NAME, defaultSecurityAnalysisRunner.getName()); + assertEquals("1.0", defaultSecurityAnalysisRunner.getVersion()); + } + + @Test + public void testAsyncDefaultProvider() throws InterruptedException, ExecutionException { + CompletableFuture report = SecurityAnalysis.runAsync(network, "v", detector, filter, computationManager, parameters, contingenciesProvider, interceptors); + assertNotNull(report.get()); + } + + @Test + public void testAsyncDefaultProviderWithFilter() throws InterruptedException, ExecutionException { + CompletableFuture report = SecurityAnalysis.runAsync(network, filter, computationManager); + assertNotNull(report.get()); + } + + @Test + public void testAsyncDefaultProviderWithComputationManager() throws InterruptedException, ExecutionException { + CompletableFuture report = SecurityAnalysis.runAsync(network, computationManager); + assertNotNull(report.get()); + } + + @Test + public void testAsyncDefaultProviderWithMiminumArguments() throws InterruptedException, ExecutionException { + CompletableFuture report = SecurityAnalysis.runAsync(network); + assertNotNull(report.get()); + } + + @Test + public void testSyncDefaultProvider() { + SecurityAnalysisReport report = SecurityAnalysis.run(network, "v", detector, filter, computationManager, parameters, contingenciesProvider, interceptors); + assertNotNull(report); + } + + @Test + public void testSyncDefaultProviderMonitor() { + SecurityAnalysisReport report = SecurityAnalysis.run(network, "v", detector, filter, computationManager, parameters, contingenciesProvider, interceptors, monitors); + assertNotNull(report); + } + + @Test + public void testSyncDefaultProviderWithFilter() { + SecurityAnalysisReport report = SecurityAnalysis.run(network, filter, computationManager); + assertNotNull(report); + } + + @Test + public void testSyncDefaultProviderWithComputationManager() { + SecurityAnalysisReport report = SecurityAnalysis.run(network, computationManager); + assertNotNull(report); + } + + @Test + public void testSyncDefaultProviderWithMiminumArguments() { + SecurityAnalysisReport report = SecurityAnalysis.run(network); + assertNotNull(report); + } +} diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisTest.java new file mode 100644 index 00000000000..94af8a57bee --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/SecurityAnalysisTest.java @@ -0,0 +1,241 @@ +/** + * Copyright (c) 2017-2018, 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/. + */ +package com.powsybl.security.impl; + +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; +import com.powsybl.commons.config.InMemoryPlatformConfig; +import com.powsybl.commons.config.PlatformConfig; +import com.powsybl.computation.ComputationManager; +import com.powsybl.computation.ComputationResourcesStatus; +import com.powsybl.contingency.*; +import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.VariantManagerConstants; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.security.*; +import com.powsybl.security.detectors.DefaultLimitViolationDetector; +import com.powsybl.security.extensions.ActivePowerExtension; +import com.powsybl.security.extensions.CurrentExtension; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.impl.interceptors.SecurityAnalysisInterceptorMock; +import com.powsybl.security.monitor.StateMonitor; +import com.powsybl.security.results.BranchResult; +import com.powsybl.security.results.BusResults; +import com.powsybl.security.results.PostContingencyResult; +import org.assertj.core.api.Assertions; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.stream.Collectors; + +import static org.junit.Assert.*; + +/** + * + * @author Massimo Ferraro + * @author Teofil Calin BANC + */ +public class SecurityAnalysisTest { + + private FileSystem fileSystem; + + private PlatformConfig platformConfig; + + @Before + public void setUp() { + fileSystem = Jimfs.newFileSystem(Configuration.unix()); + platformConfig = new InMemoryPlatformConfig(fileSystem); + } + + @After + public void tearDown() throws IOException { + fileSystem.close(); + } + + @Test + public void run() { + Network network = EurostagTutorialExample1Factory.create(); + ((Bus) network.getIdentifiable("NHV1")).setV(380.0); + ((Bus) network.getIdentifiable("NHV2")).setV(380.0); + network.getLine("NHV1_NHV2_1").getTerminal1().setP(560.0).setQ(550.0); + network.getLine("NHV1_NHV2_1").getTerminal2().setP(560.0).setQ(550.0); + network.getLine("NHV1_NHV2_1").newCurrentLimits1().setPermanentLimit(1500.0).add(); + network.getLine("NHV1_NHV2_1").newCurrentLimits2() + .setPermanentLimit(1200.0) + .beginTemporaryLimit() + .setName("10'") + .setAcceptableDuration(10 * 60) + .setValue(1300.0) + .endTemporaryLimit() + .add(); + + ComputationManager computationManager = createMockComputationManager(); + + Contingency contingency = Contingency.builder("NHV1_NHV2_2_contingency") + .addBranch("NHV1_NHV2_2") + .build(); + contingency = Mockito.spy(contingency); + Mockito.when(contingency.toTask()).thenReturn((network1, computationManager1) -> { + network1.getLine("NHV1_NHV2_2").getTerminal1().disconnect(); + network1.getLine("NHV1_NHV2_2").getTerminal2().disconnect(); + network1.getLine("NHV1_NHV2_1").getTerminal2().setP(600.0); + }); + ContingenciesProvider contingenciesProvider = Mockito.mock(ContingenciesProvider.class); + Mockito.when(contingenciesProvider.getContingencies(network)).thenReturn(Collections.singletonList(contingency)); + + LimitViolationFilter filter = new LimitViolationFilter(); + LimitViolationDetector detector = new DefaultLimitViolationDetector(); + SecurityAnalysisInterceptorMock interceptorMock = new SecurityAnalysisInterceptorMock(); + List interceptors = new ArrayList<>(); + interceptors.add(interceptorMock); + + SecurityAnalysisReport report = SecurityAnalysis.run(network, + VariantManagerConstants.INITIAL_VARIANT_ID, + detector, + filter, + computationManager, + SecurityAnalysisParameters.load(platformConfig), + contingenciesProvider, + interceptors); + + SecurityAnalysisResult result = report.getResult(); + + assertTrue(result.getPreContingencyLimitViolationsResult().isComputationOk()); + assertEquals(0, result.getPreContingencyLimitViolationsResult().getLimitViolations().size()); + PostContingencyResult postcontingencyResult = result.getPostContingencyResults().get(0); + assertTrue(postcontingencyResult.getLimitViolationsResult().isComputationOk()); + assertEquals(1, postcontingencyResult.getLimitViolationsResult().getLimitViolations().size()); + LimitViolation violation = postcontingencyResult.getLimitViolationsResult().getLimitViolations().get(0); + assertEquals(LimitViolationType.CURRENT, violation.getLimitType()); + assertEquals("NHV1_NHV2_1", violation.getSubjectId()); + + ActivePowerExtension extension1 = violation.getExtension(ActivePowerExtension.class); + assertNotNull(extension1); + assertEquals(560.0, extension1.getPreContingencyValue(), 0.0); + assertEquals(600.0, extension1.getPostContingencyValue(), 0.0); + + CurrentExtension extension2 = violation.getExtension(CurrentExtension.class); + assertNotNull(extension2); + assertEquals(1192.5631358010583, extension2.getPreContingencyValue(), 0.0); + + Assert.assertEquals(1, interceptorMock.getOnPostContingencyResultCount()); + Assert.assertEquals(1, interceptorMock.getOnPreContingencyResultCount()); + Assert.assertEquals(1, interceptorMock.getOnSecurityAnalysisResultCount()); + } + + @Test + public void runWithoutContingency() { + Network network = EurostagTutorialExample1Factory.create(); + ComputationManager computationManager = createMockComputationManager(); + + ContingenciesProvider contingenciesProvider = Mockito.mock(ContingenciesProvider.class); + Mockito.when(contingenciesProvider.getContingencies(network)).thenReturn(Collections.emptyList()); + + List interceptors = new ArrayList<>(); + SecurityAnalysisInterceptorMock interceptorMock = new SecurityAnalysisInterceptorMock(); + interceptors.add(interceptorMock); + + SecurityAnalysisReport report = SecurityAnalysis.run(network, + VariantManagerConstants.INITIAL_VARIANT_ID, + new DefaultLimitViolationDetector(), + new LimitViolationFilter(), + computationManager, + SecurityAnalysisParameters.load(platformConfig), + contingenciesProvider, + interceptors); + SecurityAnalysisResult result = report.getResult(); + + assertTrue(result.getPreContingencyLimitViolationsResult().isComputationOk()); + assertEquals(0, result.getPreContingencyLimitViolationsResult().getLimitViolations().size()); + assertEquals(0, result.getPostContingencyResults().size()); + + Assert.assertEquals(0, interceptorMock.getOnPostContingencyResultCount()); + Assert.assertEquals(1, interceptorMock.getOnPreContingencyResultCount()); + Assert.assertEquals(1, interceptorMock.getOnSecurityAnalysisResultCount()); + } + + private static ComputationManager createMockComputationManager() { + ComputationManager computationManager = Mockito.mock(ComputationManager.class); + Executor executor = Runnable::run; + Mockito.when(computationManager.getExecutor()).thenReturn(executor); + ComputationResourcesStatus computationResourcesStatus = Mockito.mock(ComputationResourcesStatus.class); + Mockito.when(computationResourcesStatus.getAvailableCores()).thenReturn(4); + Mockito.when(computationManager.getResourcesStatus()).thenReturn(computationResourcesStatus); + return computationManager; + } + + @Test + public void testStateMonitors() { + Network network = EurostagTutorialExample1Factory.create(); + ((Bus) network.getIdentifiable("NHV1")).setV(380.0); + ((Bus) network.getIdentifiable("NHV1")).setAngle(0.0); + ((Bus) network.getIdentifiable("NHV2")).setV(380.0); + ((Bus) network.getIdentifiable("NHV2")).setAngle(0.0); + network.getLine("NHV1_NHV2_1").getTerminal1().setP(560.0).setQ(550.0); + network.getLine("NHV1_NHV2_1").getTerminal2().setP(560.0).setQ(550.0); + network.getLine("NHV1_NHV2_1").newCurrentLimits1().setPermanentLimit(1500.0).add(); + network.getLine("NHV1_NHV2_1").newCurrentLimits2() + .setPermanentLimit(1200.0) + .beginTemporaryLimit() + .setName("10'") + .setAcceptableDuration(10 * 60) + .setValue(1300.0) + .endTemporaryLimit() + .add(); + network.getLine("NHV1_NHV2_2").getTerminal1().setP(600.0).setQ(500.0); + network.getLine("NHV1_NHV2_2").getTerminal2().setP(600.0).setQ(500.0); + network.getLine("NHV1_NHV2_2").newCurrentLimits1().setPermanentLimit(1500.0).add(); + network.getLine("NHV1_NHV2_2").newCurrentLimits2() + .setPermanentLimit(1200.0) + .beginTemporaryLimit() + .setName("10'") + .setAcceptableDuration(10 * 60) + .setValue(1300.0) + .endTemporaryLimit() + .add(); + ComputationManager computationManager = createMockComputationManager(); + // Testing all contingencies at once + ContingenciesProvider contingenciesProvider = n -> n.getBranchStream() + .map(b -> new Contingency(b.getId(), new BranchContingency(b.getId()))) + .collect(Collectors.toList()); + + SecurityAnalysisParameters saParameters = new SecurityAnalysisParameters(); + + LimitViolationFilter filter = new LimitViolationFilter(); + LimitViolationDetector detector = new DefaultLimitViolationDetector(); + + List monitors = new ArrayList<>(); + monitors.add(new StateMonitor(new ContingencyContext("NHV1_NHV2_1", ContingencyContextType.SPECIFIC), + Collections.singleton("NHV1_NHV2_2"), Collections.singleton("VLHV2"), Collections.emptySet())); + // this monitor will be filtered because the id of the branch of the state Monitor and the id of the branch of the contingency are the same + monitors.add(new StateMonitor(new ContingencyContext("NHV1_NHV2_2", ContingencyContextType.SPECIFIC), + Collections.singleton("NHV1_NHV2_2"), Collections.emptySet(), Collections.emptySet())); + monitors.add(new StateMonitor(new ContingencyContext(null, ContingencyContextType.NONE), + Set.of("NHV1_NHV2_1", "NOT_EXISTING_BRANCH"), Set.of("VLHV1", "NOT_EXISTING_VOLTAGE_LEVEL"), Collections.singleton("NOT_EXISTING_T3W"))); // ignore IDs of non existing equipment + + DefaultSecurityAnalysis defaultSecurityAnalysis = new DefaultSecurityAnalysis(network, detector, filter, computationManager, monitors); + SecurityAnalysisReport report = defaultSecurityAnalysis.run(network.getVariantManager().getWorkingVariantId(), saParameters, contingenciesProvider).join(); + SecurityAnalysisResult result = report.getResult(); + Assertions.assertThat(result.getPreContingencyResult().getPreContingencyBusResults()).containsExactly(new BusResults("VLHV1", "VLHV1_0", 380.0, 0.0)); + Assertions.assertThat(result.getPreContingencyResult().getPreContingencyBusResult("VLHV1_0")).isEqualToComparingOnlyGivenFields(new BusResults("VLHV1", "VLHV1_0", 380.0, 0.0)); + Assertions.assertThat(result.getPreContingencyResult().getPreContingencyBranchResults()).containsExactly(new BranchResult("NHV1_NHV2_1", 560.0, 550.0, 1192.5631358010583, 560.0, 550.0, 1192.5631358010583)); + Assertions.assertThat(result.getPreContingencyResult().getPreContingencyBranchResult("NHV1_NHV2_1")).isEqualToComparingOnlyGivenFields(new BranchResult("NHV1_NHV2_1", 560.0, 550.0, 1192.5631358010583, 560.0, 550.0, 1192.5631358010583)); + Assertions.assertThat(result.getPostContingencyResults().get(0).getBranchResults()).containsExactly(new BranchResult("NHV1_NHV2_2", 600.0, 500.0, 1186.6446717954987, 600.0, 500.0, 1186.6446717954987)); + Assertions.assertThat(result.getPostContingencyResults().get(0).getBusResults()).containsExactly(new BusResults("VLHV2", "VLHV2_0", 380.0, 0.0)); + } +} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorMock.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorMock.java similarity index 90% rename from security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorMock.java rename to security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorMock.java index 2827cf325e4..8fcdb2e09e5 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorMock.java +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorMock.java @@ -4,9 +4,12 @@ * 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/. */ -package com.powsybl.security.interceptors; +package com.powsybl.security.impl.interceptors; import com.powsybl.security.*; +import com.powsybl.security.interceptors.DefaultSecurityAnalysisInterceptor; +import com.powsybl.security.interceptors.SecurityAnalysisResultContext; +import com.powsybl.security.results.PostContingencyResult; import static org.junit.Assert.*; @@ -45,7 +48,7 @@ public void onSecurityAnalysisResult(SecurityAnalysisResult result, SecurityAnal assertRunningContext(context); assertNotNull(result); - assertPreContingencyResult(result.getPreContingencyResult()); + assertPreContingencyResult(result.getPreContingencyLimitViolationsResult()); result.getPostContingencyResults().forEach(SecurityAnalysisInterceptorMock::assertPostContingencyResult); onSecurityAnalysisResultCount++; } diff --git a/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorMockExtension.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorMockExtension.java similarity index 79% rename from security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorMockExtension.java rename to security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorMockExtension.java index f5de4bb4229..21e4ea0c20a 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/interceptors/SecurityAnalysisInterceptorMockExtension.java +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorMockExtension.java @@ -4,9 +4,11 @@ * 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/. */ -package com.powsybl.security.interceptors; +package com.powsybl.security.impl.interceptors; import com.google.auto.service.AutoService; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptorExtension; /** * @author Mathieu Bague diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorTest.java new file mode 100644 index 00000000000..0177f6f5cef --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/interceptors/SecurityAnalysisInterceptorTest.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2018, 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/. + */ +package com.powsybl.security.impl.interceptors; + +import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; +import com.powsybl.security.interceptors.SecurityAnalysisInterceptors; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; + +import static org.junit.Assert.*; + +/** + * @author Mathieu Bague + */ +public class SecurityAnalysisInterceptorTest { + + @Test + public void test() { + Assert.assertEquals(Collections.singleton("SecurityAnalysisInterceptorMock"), SecurityAnalysisInterceptors.getExtensionNames()); + + SecurityAnalysisInterceptor interceptor = SecurityAnalysisInterceptors.createInterceptor("SecurityAnalysisInterceptorMock"); + assertNotNull(interceptor); + assertEquals(SecurityAnalysisInterceptorMock.class, interceptor.getClass()); + + try { + interceptor = SecurityAnalysisInterceptors.createInterceptor(null); + fail(); + } catch (NullPointerException e) { + // Nothing to do + } + + try { + interceptor = SecurityAnalysisInterceptors.createInterceptor("unknown-security-analysis-interceptor"); + fail(); + } catch (IllegalArgumentException e) { + // Nothing to do + } + } +} diff --git a/security-analysis-api/src/test/java/com/powsybl/security/LoadFlowProviderMock.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/mocks/LoadFlowProviderMock.java similarity index 97% rename from security-analysis-api/src/test/java/com/powsybl/security/LoadFlowProviderMock.java rename to security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/mocks/LoadFlowProviderMock.java index bfd8a2ea3ac..80f5c0cefc6 100644 --- a/security-analysis-api/src/test/java/com/powsybl/security/LoadFlowProviderMock.java +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/mocks/LoadFlowProviderMock.java @@ -4,7 +4,7 @@ * 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/. */ -package com.powsybl.security; +package com.powsybl.security.impl.mocks; import com.google.auto.service.AutoService; import com.powsybl.computation.ComputationManager; diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/monitors/StateMonitorIndexTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/monitors/StateMonitorIndexTest.java new file mode 100644 index 00000000000..b27a07b384d --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/monitors/StateMonitorIndexTest.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.impl.monitors; + +import com.powsybl.contingency.ContingencyContext; +import com.powsybl.contingency.ContingencyContextType; +import com.powsybl.security.monitor.StateMonitor; +import com.powsybl.security.monitor.StateMonitorIndex; +import org.junit.Test; + +import java.util.*; + +import static junit.framework.TestCase.assertEquals; + +/** + * @author Etienne Lesot + */ +public class StateMonitorIndexTest { + + @Test + public void test() { + List monitors = new ArrayList<>(); + monitors.add(new StateMonitor(new ContingencyContext("contingency1", ContingencyContextType.SPECIFIC), + Collections.singleton("Branch1"), Collections.singleton("Bus1"), Collections.singleton("ThreeWindingsTransformer1"))); + monitors.add(new StateMonitor(new ContingencyContext("contingency1", ContingencyContextType.SPECIFIC), + Collections.singleton("Branch6"), Collections.singleton("Bus6"), Collections.singleton("ThreeWindingsTransformer6"))); + monitors.add(new StateMonitor(new ContingencyContext(null, ContingencyContextType.NONE), + Collections.singleton("Branch2"), Collections.singleton("Bus2"), Collections.singleton("ThreeWindingsTransformer2"))); + monitors.add(new StateMonitor(new ContingencyContext(null, ContingencyContextType.NONE), + Collections.singleton("Branch3"), Collections.singleton("Bus3"), Collections.singleton("ThreeWindingsTransformer3"))); + monitors.add(new StateMonitor(new ContingencyContext(null, ContingencyContextType.ALL), + Collections.singleton("Branch4"), Collections.singleton("Bus4"), Collections.singleton("ThreeWindingsTransformer4"))); + monitors.add(new StateMonitor(new ContingencyContext(null, ContingencyContextType.ALL), + Collections.singleton("Branch5"), Collections.singleton("Bus5"), Collections.singleton("ThreeWindingsTransformer5"))); + StateMonitorIndex monitorIndex = new StateMonitorIndex(monitors); + + assertEquals(new StateMonitor(new ContingencyContext("contingency1", ContingencyContextType.SPECIFIC), Set.of("Branch1", "Branch6"), + Set.of("Bus1", "Bus6"), Set.of("ThreeWindingsTransformer1", "ThreeWindingsTransformer6")), monitorIndex.getSpecificStateMonitors().get("contingency1")); + assertEquals(new StateMonitor(new ContingencyContext(null, ContingencyContextType.ALL), Set.of("Branch4", "Branch5"), + Set.of("Bus4", "Bus5"), Set.of("ThreeWindingsTransformer4", "ThreeWindingsTransformer5")), monitorIndex.getAllStateMonitor()); + assertEquals(new StateMonitor(new ContingencyContext(null, ContingencyContextType.NONE), Set.of("Branch2", "Branch3"), + Set.of("Bus2", "Bus3"), Set.of("ThreeWindingsTransformer2", "ThreeWindingsTransformer3")), monitorIndex.getNoneStateMonitor()); + + } +} diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BranchResultTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BranchResultTest.java new file mode 100644 index 00000000000..44eca3bbbdf --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BranchResultTest.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.impl.results; + +import com.google.common.testing.EqualsTester; +import com.powsybl.security.results.BranchResult; +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +/** + * @author Etienne Lesot + */ +public class BranchResultTest { + @Test + public void test() { + BranchResult branchResult = new BranchResult("id1", 500, 200, 300, -500, 300, -300); + assertEquals("id1", branchResult.getBranchId()); + assertEquals(300.0, branchResult.getI1()); + assertEquals(500.0, branchResult.getP1()); + assertEquals(200.0, branchResult.getQ1()); + assertEquals(-300.0, branchResult.getI2()); + assertEquals(-500.0, branchResult.getP2()); + assertEquals(300.0, branchResult.getQ2()); + + new EqualsTester() + .addEqualityGroup(new BranchResult("id2", 400, 200, 300, -500, 300, -300), + new BranchResult("id2", 400, 200, 300, -500, 300, -300)) + .addEqualityGroup(branchResult, branchResult) + .testEquals(); + } +} diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BusResultsTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BusResultsTest.java new file mode 100644 index 00000000000..2a15bd37b37 --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/BusResultsTest.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.impl.results; + +import com.google.common.testing.EqualsTester; +import com.powsybl.security.results.BusResults; +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +/** + * @author Etienne Lesot + */ +public class BusResultsTest { + @Test + public void test() { + BusResults busResults = new BusResults("vl_id", "bus_id", 400, 0.0003); + assertEquals("vl_id", busResults.getVoltageLevelId()); + assertEquals("bus_id", busResults.getBusId()); + assertEquals(400.0, busResults.getV()); + assertEquals(0.0003, busResults.getAngle()); + + new EqualsTester() + .addEqualityGroup(new BusResults("vl_id2", "bus_id2", 250, 0.0003), + new BusResults("vl_id2", "bus_id2", 250, 0.0003)) + .addEqualityGroup(busResults, busResults) + .testEquals(); + } +} diff --git a/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/ThreeWindingsTransformerResultTest.java b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/ThreeWindingsTransformerResultTest.java new file mode 100644 index 00000000000..5c45724b938 --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/java/com/powsybl/security/impl/results/ThreeWindingsTransformerResultTest.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2021, 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/. + */ +package com.powsybl.security.impl.results; + +import com.google.common.testing.EqualsTester; +import com.powsybl.security.results.ThreeWindingsTransformerResult; +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +/** + * @author Etienne Lesot + */ +public class ThreeWindingsTransformerResultTest { + + @Test + public void test() { + + ThreeWindingsTransformerResult threeWindingsTransformerResult = new ThreeWindingsTransformerResult("id1", 500, 200, 300, -500, 300, -300, 200, 300, 800); + assertEquals("id1", threeWindingsTransformerResult.getThreeWindingsTransformerId()); + assertEquals(300.0, threeWindingsTransformerResult.getI1()); + assertEquals(500.0, threeWindingsTransformerResult.getP1()); + assertEquals(200.0, threeWindingsTransformerResult.getQ1()); + assertEquals(-300.0, threeWindingsTransformerResult.getI2()); + assertEquals(-500.0, threeWindingsTransformerResult.getP2()); + assertEquals(300.0, threeWindingsTransformerResult.getQ2()); + assertEquals(800.0, threeWindingsTransformerResult.getI3()); + assertEquals(200.0, threeWindingsTransformerResult.getP3()); + assertEquals(300.0, threeWindingsTransformerResult.getQ3()); + + new EqualsTester() + .addEqualityGroup(new ThreeWindingsTransformerResult("id2", 400, 200, 300, -500, 300, -300, 200, 300, 500), + new ThreeWindingsTransformerResult("id2", 400, 200, 300, -500, 300, -300, 200, 300, 500)) + .addEqualityGroup(threeWindingsTransformerResult, threeWindingsTransformerResult) + .testEquals(); + } +} diff --git a/security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/config.yml b/security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/config.yml new file mode 100644 index 00000000000..a938d3775c8 --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/config.yml @@ -0,0 +1,2 @@ +security-analysis: + default-impl-name: "DefaultSecurityAnalysis" diff --git a/security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/filelist.txt b/security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/filelist.txt new file mode 100644 index 00000000000..e9abc7f6a85 --- /dev/null +++ b/security-analysis/security-analysis-default/src/test/resources/com/powsybl/config/test/filelist.txt @@ -0,0 +1 @@ +config.yml \ No newline at end of file