-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EMF module and merge tests #82
Changes from 2 commits
c58bb37
bfbf3dd
f6bea46
998badb
84f10a6
b817a92
fe467d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>powsybl-entsoe</artifactId> | ||
<groupId>com.powsybl</groupId> | ||
<version>2.2.0-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>powsybl-emf</artifactId> | ||
<name>European merging function algorithm</name> | ||
<description>Implementation of european merging function algorithm</description> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-commons</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-iidm-api</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-cgmes-extensions</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-cgmes-conversion</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-iidm-mergingview</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-cgmes-conformity</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-cgmes-model</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>ch.qos.logback</groupId> | ||
<artifactId>logback-classic</artifactId> | ||
<scope>runtime</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.jimfs</groupId> | ||
<artifactId>jimfs</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-config-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter</artifactId> | ||
<version>${junit-jupiter.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<!-- Runtime dependencies --> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-iidm-impl</artifactId> | ||
<scope>runtime</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-open-loadflow</artifactId> | ||
<scope>runtime</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.powsybl</groupId> | ||
<artifactId>powsybl-triple-store-impl-rdf4j</artifactId> | ||
<scope>runtime</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
/* | ||
* Copyright (c) 2022, RTE (http://www.rte-france.com) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. *2023 |
||
* 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/. | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add the SPDX? |
||
package com.powsybl.emf; | ||
|
||
import com.google.common.jimfs.Configuration; | ||
import com.google.common.jimfs.Jimfs; | ||
import com.powsybl.cgmes.conformity.CgmesConformity1Catalog; | ||
import com.powsybl.cgmes.conversion.export.*; | ||
import com.powsybl.cgmes.model.test.TestGridModelResources; | ||
import com.powsybl.commons.datasource.GenericReadOnlyDataSource; | ||
import com.powsybl.commons.datasource.ResourceSet; | ||
import com.powsybl.commons.xml.XmlUtil; | ||
import com.powsybl.iidm.mergingview.MergingView; | ||
import com.powsybl.iidm.network.Network; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import javax.xml.stream.XMLStreamException; | ||
import javax.xml.stream.XMLStreamWriter; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.nio.file.FileSystem; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.*; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
|
||
class IGMmergeTests { | ||
miovd marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add your name as |
||
|
||
@Test | ||
void igmsDestructiveMerge() throws IOException { | ||
miovd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can put this initialization in a |
||
|
||
Set<String> branchIds = new HashSet<>(); | ||
Set<String> generatorsId = new HashSet<>(); | ||
Set<String> voltageLevelIds = new HashSet<>(); | ||
|
||
//Load two IGMs BE and NL | ||
Map<String, Network> validNetworks = new HashMap<>(); | ||
TestGridModelResources resBE = CgmesConformity1Catalog.microGridBaseCaseBE(); | ||
Network igmBE = Network.read(resBE.dataSource()); | ||
validNetworks.put("BE", igmBE); | ||
igmBE.getBranches().forEach(b -> branchIds.add(b.getId())); | ||
igmBE.getGenerators().forEach(g -> generatorsId.add(g.getId())); | ||
igmBE.getVoltageLevels().forEach(v -> voltageLevelIds.add(v.getId())); | ||
|
||
TestGridModelResources resNL = CgmesConformity1Catalog.microGridBaseCaseNL(); | ||
Network igmNL = Network.read(resNL.dataSource()); | ||
validNetworks.put("NL", igmNL); | ||
igmNL.getBranches().forEach(b -> branchIds.add(b.getId())); | ||
igmNL.getGenerators().forEach(g -> generatorsId.add(g.getId())); | ||
igmNL.getVoltageLevels().forEach(v -> voltageLevelIds.add(v.getId())); | ||
|
||
//Merge, Serialize and Deserialize the network | ||
igmBE.merge(igmNL); | ||
validNetworks.put("Merged", igmBE); | ||
|
||
Path destructiveMergeDir = Files.createDirectory(fs.getPath("/destructiveMerge")); | ||
exportNetwork(igmBE, destructiveMergeDir, "BE_NL", validNetworks, Set.of("EQ", "TP", "SSH", "SV")); | ||
|
||
//Copy the boundary set explicitly it is not serialized and is needed for reimport | ||
ResourceSet boundaries = CgmesConformity1Catalog.microGridBaseCaseBoundaries(); | ||
for (String bFile : boundaries.getFileNames()) { | ||
Files.copy(boundaries.newInputStream(bFile), destructiveMergeDir.resolve("BE_NL" + bFile)); | ||
} | ||
|
||
//Reimport and check | ||
Network serializedMergedNetwork = Network.read(new GenericReadOnlyDataSource(destructiveMergeDir, "BE_NL"), null); | ||
validate(serializedMergedNetwork, branchIds, generatorsId, voltageLevelIds); | ||
} | ||
|
||
@Test | ||
void igmsMergeWithMergingView() throws IOException { | ||
miovd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same remark |
||
|
||
Set<String> branchIds = new HashSet<>(); | ||
Set<String> generatorsId = new HashSet<>(); | ||
Set<String> voltageLevelIds = new HashSet<>(); | ||
|
||
Map<String, Network> validNetworks = new HashMap<>(); | ||
TestGridModelResources resBE = CgmesConformity1Catalog.microGridBaseCaseBE(); | ||
Network igmBE = Network.read(resBE.dataSource()); | ||
validNetworks.put("BE", igmBE); | ||
igmBE.getBranches().forEach(b -> branchIds.add(b.getId())); | ||
igmBE.getGenerators().forEach(g -> generatorsId.add(g.getId())); | ||
igmBE.getVoltageLevels().forEach(v -> voltageLevelIds.add(v.getId())); | ||
|
||
TestGridModelResources resNL = CgmesConformity1Catalog.microGridBaseCaseNL(); | ||
Network igmNL = Network.read(resNL.dataSource()); | ||
|
||
MergingView mergingView = MergingView.create("merged", "validation"); | ||
mergingView.merge(igmBE, igmNL); | ||
validNetworks.put("NL", igmNL); | ||
igmNL.getBranches().forEach(b -> branchIds.add(b.getId())); | ||
igmNL.getGenerators().forEach(g -> generatorsId.add(g.getId())); | ||
igmNL.getVoltageLevels().forEach(v -> voltageLevelIds.add(v.getId())); | ||
validNetworks.put("Merged", mergingView); | ||
|
||
Path mergingViewMergeDir = Files.createDirectory(fs.getPath("/mergingViewMerge")); | ||
//Export to CGMES only state variable of the merged network, the rest is exported separately for each igms | ||
exportNetwork(mergingView, mergingViewMergeDir, "BE_NL", validNetworks, Set.of("SV")); | ||
exportNetwork(igmBE, mergingViewMergeDir, "BE_NL_BE", Map.of("BE", igmBE), Set.of("EQ", "TP", "SSH")); | ||
exportNetwork(igmNL, mergingViewMergeDir, "BE_NL_NL", Map.of("NL", igmNL), Set.of("EQ", "TP", "SSH")); | ||
|
||
//Copy the boundary set explicitly it is not serialized and is needed for reimport | ||
ResourceSet boundaries = CgmesConformity1Catalog.microGridBaseCaseBoundaries(); | ||
for (String bFile : boundaries.getFileNames()) { | ||
Files.copy(boundaries.newInputStream(bFile), mergingViewMergeDir.resolve("BE_NL" + bFile)); | ||
} | ||
|
||
Network serializedMergedNetwork = Network.read(new GenericReadOnlyDataSource(mergingViewMergeDir, "BE_NL"), null); | ||
validate(serializedMergedNetwork, branchIds, generatorsId, voltageLevelIds); | ||
} | ||
|
||
@Test | ||
void cgmToCgmes() throws IOException { | ||
miovd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
//Read resources for BE and NL, merge the resources themselves and read a network from this set of resources | ||
TestGridModelResources mergedResourcesBENL = new TestGridModelResources( | ||
"MicroGrid-BaseCase-BE_NL_MergedResources", | ||
null, | ||
new ResourceSet("/conformity/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/CGMES_v2.4.15_MicroGridTestConfiguration_BC_BE_v2/", | ||
"MicroGridTestConfiguration_BC_BE_DL_V2.xml", | ||
"MicroGridTestConfiguration_BC_BE_DY_V2.xml", | ||
"MicroGridTestConfiguration_BC_BE_EQ_V2.xml", | ||
"MicroGridTestConfiguration_BC_BE_GL_V2.xml", | ||
"MicroGridTestConfiguration_BC_BE_SSH_V2.xml", | ||
"MicroGridTestConfiguration_BC_BE_SV_V2.xml", | ||
"MicroGridTestConfiguration_BC_BE_TP_V2.xml"), | ||
new ResourceSet("/conformity/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/CGMES_v2.4.15_MicroGridTestConfiguration_BC_NL_v2/", | ||
"MicroGridTestConfiguration_BC_NL_DL_V2.xml", | ||
"MicroGridTestConfiguration_BC_NL_DY_V2.xml", | ||
"MicroGridTestConfiguration_BC_NL_EQ_V2.xml", | ||
"MicroGridTestConfiguration_BC_NL_GL_V2.xml", | ||
"MicroGridTestConfiguration_BC_NL_SSH_V2.xml", | ||
"MicroGridTestConfiguration_BC_NL_SV_V2.xml", | ||
"MicroGridTestConfiguration_BC_NL_TP_V2.xml"), | ||
CgmesConformity1Catalog.microGridBaseCaseBoundaries()); | ||
Network networkBENL = Network.read(mergedResourcesBENL.dataSource()); | ||
|
||
FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same remark |
||
|
||
Set<String> branchIds = new HashSet<>(); | ||
Set<String> generatorsId = new HashSet<>(); | ||
Set<String> voltageLevelIds = new HashSet<>(); | ||
|
||
networkBENL.getBranches().forEach(b -> branchIds.add(b.getId())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To prevent the encoding error (it will not be added in this release), do networkBENL.getBranches().forEach(b -> branchIds.add(b.getId().replace(" ", "%20)); // FIXME workaround before fixing CGMES export/import There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. |
||
networkBENL.getGenerators().forEach(g -> generatorsId.add(g.getId())); | ||
networkBENL.getVoltageLevels().forEach(v -> voltageLevelIds.add(v.getId())); | ||
|
||
Path mergedResourcesDir = Files.createDirectory(fs.getPath("/mergedResourcesExport")); | ||
exportNetwork(networkBENL, mergedResourcesDir, "BE_NL", Map.of("BENL", networkBENL), Set.of("EQ", "TP", "SSH", "SV")); | ||
|
||
//Copy the boundary set explicitly it is not serialized and is needed for reimport | ||
ResourceSet boundaries = CgmesConformity1Catalog.microGridBaseCaseBoundaries(); | ||
for (String bFile : boundaries.getFileNames()) { | ||
Files.copy(boundaries.newInputStream(bFile), mergedResourcesDir.resolve("BE_NL" + bFile)); | ||
} | ||
Network serializedMergedNetwork = Network.read(new GenericReadOnlyDataSource(mergedResourcesDir, "BE_NL"), null); | ||
validate(serializedMergedNetwork, branchIds, generatorsId, voltageLevelIds); | ||
} | ||
|
||
public void validate(Network n, Set<String> branchIds, Set<String> generatorsId, Set<String> voltageLevelIds) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can be static and private |
||
branchIds.forEach(b -> assertNotNull(n.getBranch(b))); | ||
generatorsId.forEach(g -> assertNotNull(n.getGenerator(g))); | ||
voltageLevelIds.forEach(v -> assertNotNull(n.getVoltageLevel(v))); | ||
} | ||
|
||
public void exportNetwork(Network network, Path outputDir, String baseName, Map<String, Network> validNetworks, Set<String> profilesToExport) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can be static and private |
||
Objects.requireNonNull(network); | ||
Path filenameEq = outputDir.resolve(baseName + "_EQ.xml"); | ||
Path filenameTp = outputDir.resolve(baseName + "_TP.xml"); | ||
Path filenameSsh = outputDir.resolve(baseName + "_SSH.xml"); | ||
Path filenameSv = outputDir.resolve(baseName + "_SV.xml"); | ||
CgmesExportContext context = new CgmesExportContext(); | ||
context.setScenarioTime(network.getCaseDate()); | ||
validNetworks.forEach((name, n) -> { | ||
context.addIidmMappings(n); | ||
}); | ||
|
||
if (profilesToExport.contains("EQ")) { | ||
exportEquipment(network, context, filenameEq); | ||
} | ||
if (profilesToExport.contains("TP")) { | ||
exportTopology(network, context, filenameTp); | ||
} | ||
if (profilesToExport.contains("SSH")) { | ||
exportSteadyStateHypothesis(network, context, filenameSsh); | ||
} | ||
if (profilesToExport.contains("SV")) { | ||
exportStateVariable(network, context, filenameSv); | ||
} | ||
} | ||
|
||
public void exportEquipment(Network network, CgmesExportContext context, Path file) { | ||
try (OutputStream out = Files.newOutputStream(file)) { | ||
XMLStreamWriter writer = XmlUtil.initializeWriter(true, " ", out); | ||
EquipmentExport.write(network, writer, context); | ||
} catch (IOException | XMLStreamException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public void exportTopology(Network network, CgmesExportContext context, Path file) { | ||
try (OutputStream out = Files.newOutputStream(file)) { | ||
XMLStreamWriter writer = XmlUtil.initializeWriter(true, " ", out); | ||
TopologyExport.write(network, writer, context); | ||
} catch (IOException | XMLStreamException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public void exportSteadyStateHypothesis(Network network, CgmesExportContext context, Path file) { | ||
try (OutputStream out = Files.newOutputStream(file)) { | ||
XMLStreamWriter writer = XmlUtil.initializeWriter(true, " ", out); | ||
SteadyStateHypothesisExport.write(network, writer, context); | ||
} catch (XMLStreamException | IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public void exportStateVariable(Network network, CgmesExportContext context, Path file) { | ||
try (OutputStream out = Files.newOutputStream(file)) { | ||
XMLStreamWriter writer = XmlUtil.initializeWriter(true, " ", out); | ||
StateVariablesExport.write(network, writer, context); | ||
} catch (IOException | XMLStreamException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can move these dependencies in
test
scope rather thanruntime