Skip to content

Commit

Permalink
CGMES export to version 3 (#1998)
Browse files Browse the repository at this point in the history
* CGMES export to specific CIM version

Signed-off-by: Luma <zamarrenolm@aia.es>

* Export to CGMES 3

Signed-off-by: Luma <zamarrenolm@aia.es>

* fix hard-coded path

Signed-off-by: Luma <zamarrenolm@aia.es>

* Update model description profiles when export CIM version is changed

Signed-off-by: Luma <zamarrenolm@aia.es>

* Not all CIM versions have profiles

Signed-off-by: Luma <zamarrenolm@aia.es>

* use proper CIM namespace in kind of regulating control and control area

Signed-off-by: Luma <zamarrenolm@aia.es>

* Small improvements

Signed-off-by: VEDELAGO MIORA <miora.ralambotiana@rte-france.com>

* Small improvements

Signed-off-by: VEDELAGO MIORA <miora.ralambotiana@rte-france.com>

* Test sample network export to CGMES 3, reimport and check

Signed-off-by: Luma <zamarrenolm@aia.es>

Co-authored-by: VEDELAGO MIORA <miora.ralambotiana@rte-france.com>
  • Loading branch information
zamarrenolm and miovd authored Mar 29, 2022
1 parent 0560bc0 commit 7bba64d
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public class CgmesExportContext {
private CgmesTopologyKind topologyKind = CgmesTopologyKind.BUS_BRANCH;
private DateTime scenarioTime = DateTime.now();

private ModelDescription eqModelDescription = new ModelDescription("EQ Model", CgmesNamespace.EQ_PROFILE);
private ModelDescription tpModelDescription = new ModelDescription("TP Model", CgmesNamespace.TP_PROFILE);
private ModelDescription svModelDescription = new ModelDescription("SV Model", CgmesNamespace.SV_PROFILE);
private ModelDescription sshModelDescription = new ModelDescription("SSH Model", CgmesNamespace.SSH_PROFILE);
private ModelDescription eqModelDescription = new ModelDescription("EQ Model", CgmesNamespace.getProfile(cimVersion, "EQ"));
private ModelDescription tpModelDescription = new ModelDescription("TP Model", CgmesNamespace.getProfile(cimVersion, "TP"));
private ModelDescription svModelDescription = new ModelDescription("SV Model", CgmesNamespace.getProfile(cimVersion, "SV"));
private ModelDescription sshModelDescription = new ModelDescription("SSH Model", CgmesNamespace.getProfile(cimVersion, "SSH"));

private boolean exportBoundaryPowerFlows = true;
private boolean exportFlowsForSwitches = false;
Expand Down Expand Up @@ -111,6 +111,11 @@ public ModelDescription setModelingAuthoritySet(String modelingAuthoritySet) {
public String getProfile() {
return profile;
}

public ModelDescription setProfile(String profile) {
this.profile = profile;
return this;
}
}

interface TopologicalConsumer {
Expand Down Expand Up @@ -512,6 +517,12 @@ public int getCimVersion() {

public CgmesExportContext setCimVersion(int cimVersion) {
this.cimVersion = cimVersion;
if (CgmesNamespace.hasProfiles(cimVersion)) {
eqModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "EQ"));
tpModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "TP"));
svModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SV"));
sshModelDescription.setProfile(CgmesNamespace.getProfile(cimVersion, "SSH"));
}
return this;
}

Expand Down Expand Up @@ -568,7 +579,7 @@ public CgmesExportContext setExportFlowsForSwitches(boolean exportFlowsForSwitch
}

public String getCimNamespace() {
return CgmesNamespace.getCimNamespace(cimVersion);
return CgmesNamespace.getCim(cimVersion);
}

public Set<CgmesIidmMapping.CgmesTopologicalNode> getTopologicalNodesByBusViewBus(String busId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.powsybl.cgmes.conversion.export.CgmesExportContext.ModelDescription;
import com.powsybl.cgmes.model.CgmesNames;
import com.powsybl.cgmes.model.CgmesNamespace;
import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.LoadDetail;
Expand Down Expand Up @@ -65,12 +66,12 @@ public static String getUniqueId() {
public static void writeRdfRoot(int cimVersion, XMLStreamWriter writer) throws XMLStreamException {
writer.setPrefix("entsoe", ENTSOE_NAMESPACE);
writer.setPrefix("rdf", RDF_NAMESPACE);
writer.setPrefix("cim", getCimNamespace(cimVersion));
writer.setPrefix("cim", CgmesNamespace.getCim(cimVersion));
writer.setPrefix("md", MD_NAMESPACE);
writer.writeStartElement(RDF_NAMESPACE, "RDF");
writer.writeNamespace("entsoe", ENTSOE_NAMESPACE);
writer.writeNamespace("rdf", RDF_NAMESPACE);
writer.writeNamespace("cim", getCimNamespace(cimVersion));
writer.writeNamespace("cim", CgmesNamespace.getCim(cimVersion));
writer.writeNamespace("md", MD_NAMESPACE);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static void write(Network network, XMLStreamWriter writer, CgmesExportCon
String cimNamespace = context.getCimNamespace();

// TODO fill EQ Model Description
if (context.getCimVersion() == 16) {
if (context.getCimVersion() >= 16) {
ModelDescriptionEq.write(writer, context.getEqModelDescription(), context);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* @author Marcos de Miguel <demiguelm at aia.es>
*/
public final class ControlAreaEq {
private static final String CONTROL_AREA_TYPE = "http://iec.ch/TC57/2013/CIM-schema-cim16#ControlAreaTypeKind.Interchange";
private static final String CONTROL_AREA_TYPE = "ControlAreaTypeKind.Interchange";

public static void write(String id, String controlAreaName, String energyIdentificationCodeEIC, String cimNamespace, XMLStreamWriter writer) throws XMLStreamException {
writer.writeStartElement(cimNamespace, "ControlArea");
Expand All @@ -30,7 +30,7 @@ public static void write(String id, String controlAreaName, String energyIdentif
writer.writeCharacters(energyIdentificationCodeEIC);
writer.writeEndElement();
writer.writeEmptyElement(cimNamespace, "ControlArea.type");
writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, CONTROL_AREA_TYPE);
writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, cimNamespace + CONTROL_AREA_TYPE);
writer.writeEndElement();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static void write(XMLStreamWriter writer, CgmesExportContext.ModelDescrip
writer.writeCharacters(modelDescription.getProfile());
writer.writeEndElement();
writer.writeStartElement(MD_NAMESPACE, CgmesNames.PROFILE);
writer.writeCharacters(CgmesNamespace.EQ_OPERATION_PROFILE);
writer.writeCharacters(CgmesNamespace.getProfile(context.getCimVersion(), "EQ_OP"));
writer.writeEndElement();
writer.writeStartElement(MD_NAMESPACE, CgmesNames.MODELING_AUTHORITY_SET);
writer.writeCharacters(modelDescription.getModelingAuthoritySet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
public final class RegulatingControlEq {

public static final String REGULATING_CONTROL_VOLTAGE = "http://iec.ch/TC57/2013/CIM-schema-cim16#RegulatingControlModeKind.voltage";
public static final String REGULATING_CONTROL_VOLTAGE = "RegulatingControlModeKind.voltage";

public static void write(String id, String regulatingControlName, String terminalId, String cimNamespace, XMLStreamWriter writer) throws XMLStreamException {
writer.writeStartElement(cimNamespace, "RegulatingControl");
Expand All @@ -29,7 +29,7 @@ public static void write(String id, String regulatingControlName, String termina
writer.writeEmptyElement(cimNamespace, "RegulatingControl.Terminal");
writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, "#" + terminalId);
writer.writeEmptyElement(cimNamespace, "RegulatingControl.mode");
writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, REGULATING_CONTROL_VOLTAGE);
writer.writeAttribute(RDF_NAMESPACE, CgmesNames.RESOURCE, cimNamespace + REGULATING_CONTROL_VOLTAGE);
writer.writeEndElement();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.powsybl.cgmes.extensions.CgmesSvMetadataAdder;
import com.powsybl.cgmes.extensions.CgmesTopologyKind;
import com.powsybl.cgmes.extensions.CimCharacteristicsAdder;
import com.powsybl.cgmes.model.CgmesNamespace;
import com.powsybl.commons.datasource.ReadOnlyDataSource;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
Expand All @@ -25,8 +26,6 @@
import java.util.List;
import java.util.Properties;

import static com.powsybl.cgmes.model.CgmesNamespace.CIM_14_NAMESPACE;
import static com.powsybl.cgmes.model.CgmesNamespace.CIM_16_NAMESPACE;
import static org.junit.Assert.*;

/**
Expand All @@ -48,7 +47,7 @@ public void networkConstructor() {
CgmesExportContext context1 = new CgmesExportContext(network);

assertEquals(16, context1.getCimVersion());
assertEquals(CIM_16_NAMESPACE, context1.getCimNamespace());
assertEquals(CgmesNamespace.getCim(16), context1.getCimNamespace());
assertEquals(CgmesTopologyKind.BUS_BRANCH, context1.getTopologyKind());
assertEquals(network.getCaseDate(), context1.getScenarioTime());
assertEquals("SV Model", context1.getSvModelDescription().getDescription());
Expand All @@ -71,7 +70,7 @@ public void networkConstructor() {
CgmesExportContext context2 = new CgmesExportContext(network);

assertEquals(14, context2.getCimVersion());
assertEquals(CIM_14_NAMESPACE, context2.getCimNamespace());
assertEquals(CgmesNamespace.getCim(14), context2.getCimNamespace());
assertEquals(CgmesTopologyKind.NODE_BREAKER, context2.getTopologyKind());
assertEquals(network.getCaseDate(), context2.getScenarioTime());
assertEquals("test", context2.getSvModelDescription().getDescription());
Expand All @@ -86,7 +85,7 @@ public void networkConstructor() {
public void emptyConstructor() {
CgmesExportContext context = new CgmesExportContext();
assertEquals(16, context.getCimVersion());
assertEquals(CIM_16_NAMESPACE, context.getCimNamespace());
assertEquals(CgmesNamespace.getCim(16), context.getCimNamespace());
assertEquals(CgmesTopologyKind.BUS_BRANCH, context.getTopologyKind());
assertTrue(new Duration(DateTime.now(), context.getScenarioTime()).getStandardMinutes() < 1);
assertEquals("SV Model", context.getSvModelDescription().getDescription());
Expand All @@ -112,7 +111,7 @@ public void getSet() {
.setModelingAuthoritySet("cgmes.org");

assertEquals(14, context.getCimVersion());
assertEquals(CIM_14_NAMESPACE, context.getCimNamespace());
assertEquals(CgmesNamespace.getCim(14), context.getCimNamespace());
assertEquals(CgmesTopologyKind.NODE_BREAKER, context.getTopologyKind());
assertEquals(DateTime.parse("2020-09-22T17:21:11.381+02:00"), context.getScenarioTime());
assertEquals("test", context.getSvModelDescription().getDescription());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,50 @@ public void testExportDataSourceEmptyBaseName() throws IOException {

@Test
public void testExportIEEE14Cim14ToCim16() {
testExportToCim(ieee14Cim14(), "IEEE14", 16);
}

@Test
public void testExportIEEE14Cim14ToCim100() {
// Testing export to CGMES 3
// TODO(Luma) verify that all classes and attributes are valid against profiles (using CIMdesk)
// TODO(Luma) Check mRID is exported
// TODO(Luma) Check GeneratingUnit.initialP (removed in CIM100)
// TODO(Luma) Check the way OperationalLimit TypeName is read
// TODO(Luma) Check OperationalLimit value (renamed to normalValue in CIM100)
Network network = ieee14Cim14();
assertEquals(14, network.getExtension(CimCharacteristics.class).getCimVersion());
testExportToCim(network, "IEEE14", 100);
}

private Network ieee14Cim14() {
ReadOnlyDataSource dataSource = Cim14SmallCasesCatalog.ieee14().dataSource();
Network networkCim14 = new CgmesImport().importData(dataSource, NetworkFactory.findDefault(), null);
CimCharacteristics cim14 = networkCim14.getExtension(CimCharacteristics.class);
return new CgmesImport().importData(dataSource, NetworkFactory.findDefault(), null);
}

private void testExportToCim(Network network, String name, int cimVersion) {
String cimZipFilename = name + "_CIM" + cimVersion;
Properties params = new Properties();
params.put(CgmesExport.CIM_VERSION, "16");
ZipFileDataSource zipIEEE14Cim16 = new ZipFileDataSource(tmpDir.resolve("."), "IEEE14");
new CgmesExport().export(networkCim14, params, zipIEEE14Cim16);
params.put(CgmesExport.CIM_VERSION, Integer.toString(cimVersion));
ZipFileDataSource zip = new ZipFileDataSource(tmpDir.resolve("."), cimZipFilename);
new CgmesExport().export(network, params, zip);

Network networkCim16 = Importers.loadNetwork(tmpDir.resolve("IEEE14.zip"));
CimCharacteristics cim16 = networkCim16.getExtension(CimCharacteristics.class);
// Reimport and verify contents of Network
Network networkCimVersion = Importers.loadNetwork(tmpDir.resolve(cimZipFilename + ".zip"));
CimCharacteristics cim = networkCimVersion.getExtension(CimCharacteristics.class);

assertEquals(14, cim14.getCimVersion());
assertEquals(16, cim16.getCimVersion());
assertEquals(cimVersion, cim.getCimVersion());
// Initial verification: check that we have the same number of elements in both networks
// TODO(Luma) compare the networks
// If the original was bus-branch (like IEEE14) and the exported is node-breaker at least compare attributes
// or select another network for verification (SmallGrid ?)
assertEquals(network.getSubstationCount(), networkCimVersion.getSubstationCount());
assertEquals(network.getVoltageLevelCount(), networkCimVersion.getVoltageLevelCount());
assertEquals(network.getLineCount(), networkCimVersion.getLineCount());
assertEquals(network.getTwoWindingsTransformerCount(), networkCimVersion.getTwoWindingsTransformerCount());
assertEquals(network.getThreeWindingsTransformerCount(), networkCimVersion.getThreeWindingsTransformerCount());
assertEquals(network.getGeneratorCount(), networkCimVersion.getGeneratorCount());
assertEquals(network.getLoadCount(), networkCimVersion.getLoadCount());
assertEquals(network.getShuntCompensatorCount(), networkCimVersion.getShuntCompensatorCount());
}

}
Loading

0 comments on commit 7bba64d

Please sign in to comment.