From dca2a82803768f33b615d5c4ce3f632c1154a02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Murgey?= Date: Wed, 20 Sep 2023 10:39:51 +0200 Subject: [PATCH] Add an implementation of GlskProvider that uses GlskDocument as data source (#113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sébastien Murgey --- flow-decomposition/pom.xml | 14 ++++ .../GlskDocumentBasedGlskProvider.java | 80 +++++++++++++++++++ .../powsybl/flow_decomposition/TestUtils.java | 7 ++ .../GlskDocumentBasedGlskProviderTest.java | 75 +++++++++++++++++ .../GlskUcteFrMultipleInstants.xml | 47 +++++++++++ .../GlskUcteFrUniqueInstant.xml | 31 +++++++ 6 files changed, 254 insertions(+) create mode 100644 flow-decomposition/src/main/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProvider.java create mode 100644 flow-decomposition/src/test/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProviderTest.java create mode 100644 flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrMultipleInstants.xml create mode 100644 flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrUniqueInstant.xml diff --git a/flow-decomposition/pom.xml b/flow-decomposition/pom.xml index 323f6f93..9dc1b6b8 100644 --- a/flow-decomposition/pom.xml +++ b/flow-decomposition/pom.xml @@ -26,6 +26,10 @@ com.powsybl powsybl-loadflow-api + + com.powsybl + powsybl-glsk-document-api + com.powsybl powsybl-sensitivity-analysis-api @@ -40,6 +44,16 @@ commons-csv ${commonscsv.version} + + com.powsybl + powsybl-glsk-document-io-api + test + + + com.powsybl + powsybl-glsk-document-ucte + test + com.powsybl powsybl-iidm-impl diff --git a/flow-decomposition/src/main/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProvider.java b/flow-decomposition/src/main/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProvider.java new file mode 100644 index 00000000..58152bbf --- /dev/null +++ b/flow-decomposition/src/main/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProvider.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.flow_decomposition.glsk_provider; + +import com.powsybl.flow_decomposition.GlskProvider; +import com.powsybl.glsk.api.GlskDocument; +import com.powsybl.glsk.commons.CountryEICode; +import com.powsybl.glsk.commons.ZonalData; +import com.powsybl.iidm.network.Country; +import com.powsybl.iidm.network.Network; +import com.powsybl.sensitivity.SensitivityVariableSet; + +import java.time.Instant; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author Sebastien Murgey {@literal } + */ +public final class GlskDocumentBasedGlskProvider implements GlskProvider { + private final GlskDocument glskDocument; + private final Instant instant; + private final boolean timeSpecific; + + private GlskDocumentBasedGlskProvider(GlskDocument glskDocument, Instant instant, boolean timeSpecific) { + this.glskDocument = glskDocument; + this.instant = instant; + this.timeSpecific = timeSpecific; + } + + @Override + public Map> getGlsk(Network network) { + Map> perCountryGlsk = getDefaultGlsk(network); + updateWithGlskFromDocument(network, perCountryGlsk); + return perCountryGlsk; + } + + private void updateWithGlskFromDocument(Network network, Map> perCountryGlsk) { + getSensitivityVariableSetZonalData(network).getDataPerZone().forEach((countryEicCode, glskData) -> perCountryGlsk.put(new CountryEICode(countryEicCode).getCountry(), + glskData.getVariablesById().entrySet().stream().collect(Collectors.toMap( + nodeFactorEntry -> nodeFactorEntry.getKey(), + nodeFactorEntry -> nodeFactorEntry.getValue().getWeight() + )))); + } + + private ZonalData getSensitivityVariableSetZonalData(Network network) { + if (timeSpecific) { + Instant glskInstant = Optional.ofNullable(instant).orElse(getNetworkInstant(network)); + return glskDocument.getZonalGlsks(network, glskInstant); + } else { + return glskDocument.getZonalGlsks(network); + } + } + + private Instant getNetworkInstant(Network network) { + return Instant.ofEpochMilli(network.getCaseDate().getMillis()); + } + + private Map> getDefaultGlsk(Network network) { + return new AutoGlskProvider().getGlsk(network); + } + + public static GlskProvider notTimeSpecific(GlskDocument glskDocument) { + return new GlskDocumentBasedGlskProvider(glskDocument, null, false); + } + + public static GlskProvider basedOnNetworkInstant(GlskDocument glskDocument) { + return new GlskDocumentBasedGlskProvider(glskDocument, null, true); + } + + public static GlskProvider basedOnGivenInstant(GlskDocument glskDocument, Instant instant) { + return new GlskDocumentBasedGlskProvider(glskDocument, instant, true); + } +} diff --git a/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/TestUtils.java b/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/TestUtils.java index 9bdc87b3..acb00c3f 100644 --- a/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/TestUtils.java +++ b/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/TestUtils.java @@ -6,6 +6,8 @@ */ package com.powsybl.flow_decomposition; +import com.powsybl.glsk.api.GlskDocument; +import com.powsybl.glsk.api.io.GlskDocumentImporters; import com.powsybl.iidm.network.Bus; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.Terminal; @@ -30,6 +32,11 @@ public static Network importNetwork(String networkResourcePath) { return Network.read(networkName, TestUtils.class.getResourceAsStream(networkResourcePath)); } + public static GlskDocument importGlskDocument(String glskFileName) { + String glskName = Paths.get(glskFileName).getFileName().toString(); + return GlskDocumentImporters.importGlsk(TestUtils.class.getResourceAsStream(glskName)); + } + public static void assertCoherenceTotalFlow(boolean enableRescaledResults, FlowDecompositionResults flowDecompositionResults) { for (String xnec : flowDecompositionResults.getDecomposedFlowMap().keySet()) { DecomposedFlow decomposedFlow = flowDecompositionResults.getDecomposedFlowMap().get(xnec); diff --git a/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProviderTest.java b/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProviderTest.java new file mode 100644 index 00000000..ac55ed50 --- /dev/null +++ b/flow-decomposition/src/test/java/com/powsybl/flow_decomposition/glsk_provider/GlskDocumentBasedGlskProviderTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.flow_decomposition.glsk_provider; + +import com.powsybl.flow_decomposition.GlskProvider; +import com.powsybl.glsk.api.GlskDocument; +import com.powsybl.iidm.network.Country; +import com.powsybl.iidm.network.Network; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.util.Map; + +import static com.powsybl.flow_decomposition.TestUtils.importGlskDocument; +import static com.powsybl.flow_decomposition.TestUtils.importNetwork; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Sebastien Murgey {@literal } + */ +class GlskDocumentBasedGlskProviderTest { + private static final double EPSILON = 1e-3; + + @Test + void testThatGlskProviderWithFirstInstantGetsCorrectFactors() { + String networkFileName = "testCase.xiidm"; + String glskFileName = "GlskUcteFrUniqueInstant.xml"; + Network network = importNetwork(networkFileName); + GlskDocument glskDocument = importGlskDocument(glskFileName); + GlskProvider glskProvider = GlskDocumentBasedGlskProvider.notTimeSpecific(glskDocument); + Map> glsks = glskProvider.getGlsk(network); + assertEquals(0.5, glsks.get(Country.FR).get("FFR1AA1 _generator"), EPSILON); + assertEquals(0.5, glsks.get(Country.FR).get("FFR2AA1 _generator"), EPSILON); + } + + @Test + void testThatGlskProviderWithNetworkInstantGetsCorrectFactors() { + String networkFileName = "testCase.xiidm"; + String glskFileName = "GlskUcteFrMultipleInstants.xml"; + Network network = importNetwork(networkFileName); + GlskDocument glskDocument = importGlskDocument(glskFileName); + GlskProvider glskProvider = GlskDocumentBasedGlskProvider.basedOnNetworkInstant(glskDocument); + Map> glsks = glskProvider.getGlsk(network); + assertEquals(1, glsks.get(Country.FR).get("FFR1AA1 _generator"), EPSILON); + } + + @Test + void testThatGlskProviderWithGivenInstantGetsCorrectFactors() { + String networkFileName = "testCase.xiidm"; + String glskFileName = "GlskUcteFrMultipleInstants.xml"; + Network network = importNetwork(networkFileName); + GlskDocument glskDocument = importGlskDocument(glskFileName); + GlskProvider glskProvider = GlskDocumentBasedGlskProvider.basedOnGivenInstant(glskDocument, Instant.parse("2014-01-16T21:00:00Z")); + Map> glsks = glskProvider.getGlsk(network); + assertEquals(1, glsks.get(Country.FR).get("FFR2AA1 _generator"), EPSILON); + } + + @Test + void testThatCountriesNotIncludedInGlskDocumentHaveAutoGlskFactorsCalculated() { + String networkFileName = "testCase.xiidm"; + String glskFileName = "GlskUcteFrMultipleInstants.xml"; + Network network = importNetwork(networkFileName); + GlskDocument glskDocument = importGlskDocument(glskFileName); + GlskProvider glskProvider = GlskDocumentBasedGlskProvider.basedOnNetworkInstant(glskDocument); + Map> glsks = glskProvider.getGlsk(network); + assertEquals(0.214, glsks.get(Country.BE).get("BBE1AA1 _generator"), EPSILON); + assertEquals(0.429, glsks.get(Country.BE).get("BBE2AA1 _generator"), EPSILON); + assertEquals(0.357, glsks.get(Country.BE).get("BBE3AA1 _generator"), EPSILON); + } +} diff --git a/flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrMultipleInstants.xml b/flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrMultipleInstants.xml new file mode 100644 index 00000000..9d263e2a --- /dev/null +++ b/flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrMultipleInstants.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrUniqueInstant.xml b/flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrUniqueInstant.xml new file mode 100644 index 00000000..3fa02a34 --- /dev/null +++ b/flow-decomposition/src/test/resources/com/powsybl/flow_decomposition/GlskUcteFrUniqueInstant.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +