From cb0a0582cd73a2a6ca229177dfb94a515473138b Mon Sep 17 00:00:00 2001 From: Coline Piloquet <55250145+colinepiloquet@users.noreply.github.com> Date: Tue, 4 Jul 2023 12:27:18 +0200 Subject: [PATCH] CGMES export loads with negative p0 as EnergySource (#2627) Signed-off-by: Coline PILOQUET --- .../conversion/export/EquipmentExport.java | 21 +++-- .../export/SteadyStateHypothesisExport.java | 85 +++++++++++-------- 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java index dd886a8518f..197f39cac09 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/EquipmentExport.java @@ -277,16 +277,25 @@ private static void writeLoads(Network network, LoadGroups loadGroups, String ci if (context.isExportedEquipment(load)) { LoadDetail loadDetail = load.getExtension(LoadDetail.class); String className = CgmesExportUtil.loadClassName(loadDetail); - String loadGroup = loadGroups.groupFor(className); - EnergyConsumerEq.write(className, - context.getNamingStrategy().getCgmesId(load), - load.getNameOrId(), loadGroup, - context.getNamingStrategy().getCgmesId(load.getTerminal().getVoltageLevel()), - cimNamespace, writer, context); + String loadId = context.getNamingStrategy().getCgmesId(load); + if (load.getP0() < 0) { + // As negative loads are not allowed, they are modeled as energy source. + // Note that negative loads can be the result of network reduction and could be modeled + // as equivalent injections. + writeEnergySource(loadId, load.getNameOrId(), cimNamespace, writer, context); + } else { + String loadGroup = loadGroups.groupFor(className); + EnergyConsumerEq.write(className, loadId, load.getNameOrId(), loadGroup, context.getNamingStrategy().getCgmesId(load.getTerminal().getVoltageLevel()), cimNamespace, writer, context); + } } } } + public static void writeEnergySource(String id, String name, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { + CgmesExportUtil.writeStartIdName("EnergySource", id, name, cimNamespace, writer, context); + writer.writeEndElement(); + } + private static void writeGenerators(Network network, Map mapTerminal2Id, Set regulatingControlsWritten, String cimNamespace, boolean writeInitialP, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { // Multiple synchronous machines may be grouped in the same generating unit diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/SteadyStateHypothesisExport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/SteadyStateHypothesisExport.java index 209134c2ad8..3ceb86a6aad 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/SteadyStateHypothesisExport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/SteadyStateHypothesisExport.java @@ -121,7 +121,22 @@ private static void writeEquivalentInjections(Network network, String cimNamespa // One equivalent injection for every dangling line List exported = new ArrayList<>(); for (DanglingLine dl : network.getDanglingLines(DanglingLineFilter.UNPAIRED)) { - writeEquivalentInjection(dl, exported, cimNamespace, writer, context); + String ei = dl.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "EquivalentInjection"); + if (!exported.contains(ei) && ei != null) { + // Ensure equivalent injection identifier is valid + String cgmesId = context.getNamingStrategy().getCgmesIdFromProperty(dl, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "EquivalentInjection"); + // regulationStatus and regulationTarget are optional, + // but test cases contain the attributes with disabled and 0 + boolean regulationStatus = false; + double regulationTarget = 0; + if (dl.getGeneration() != null) { + regulationStatus = dl.getGeneration().isVoltageRegulationOn(); + regulationTarget = dl.getGeneration().getTargetV(); + } + writeEquivalentInjection(cgmesId, dl.getP0(), dl.getQ0(), regulationStatus, regulationTarget, cimNamespace, writer, context); + exported.add(ei); + } + } } @@ -515,48 +530,50 @@ private static void writeTerminal(String terminalId, boolean connected, String c } } - private static void writeEquivalentInjection(DanglingLine dl, List exported, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { - String ei = dl.getProperty(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "EquivalentInjection"); - if (exported.contains(ei)) { - return; - } - if (ei != null) { - // Ensure equivalent injection identifier is valid - String cgmesId = context.getNamingStrategy().getCgmesIdFromProperty(dl, Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "EquivalentInjection"); - CgmesExportUtil.writeStartAbout("EquivalentInjection", cgmesId, cimNamespace, writer, context); - writer.writeStartElement(cimNamespace, "EquivalentInjection.p"); - writer.writeCharacters(CgmesExportUtil.format(dl.getP0())); - writer.writeEndElement(); - writer.writeStartElement(cimNamespace, "EquivalentInjection.q"); - writer.writeCharacters(CgmesExportUtil.format(dl.getQ0())); - writer.writeEndElement(); - // regulationStatus and regulationTarget are optional, - // but test cases contain the attributes with disabled and 0 - boolean regulationStatus = false; - double regulationTarget = 0; - if (dl.getGeneration() != null) { - regulationStatus = dl.getGeneration().isVoltageRegulationOn(); - regulationTarget = dl.getGeneration().getTargetV(); - } - writer.writeStartElement(cimNamespace, "EquivalentInjection.regulationStatus"); - writer.writeCharacters(Boolean.toString(regulationStatus)); - writer.writeEndElement(); - writer.writeStartElement(cimNamespace, "EquivalentInjection.regulationTarget"); - writer.writeCharacters(CgmesExportUtil.format(regulationTarget)); - writer.writeEndElement(); - writer.writeEndElement(); - exported.add(ei); - } + private static void writeEquivalentInjection(String cgmesId, double p, double q, boolean regulationStatus, double regulationTarget, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { + CgmesExportUtil.writeStartAbout("EquivalentInjection", cgmesId, cimNamespace, writer, context); + writer.writeStartElement(cimNamespace, "EquivalentInjection.p"); + writer.writeCharacters(CgmesExportUtil.format(p)); + writer.writeEndElement(); + writer.writeStartElement(cimNamespace, "EquivalentInjection.q"); + writer.writeCharacters(CgmesExportUtil.format(q)); + writer.writeEndElement(); + writer.writeStartElement(cimNamespace, "EquivalentInjection.regulationStatus"); + writer.writeCharacters(Boolean.toString(regulationStatus)); + writer.writeEndElement(); + writer.writeStartElement(cimNamespace, "EquivalentInjection.regulationTarget"); + writer.writeCharacters(CgmesExportUtil.format(regulationTarget)); + writer.writeEndElement(); + writer.writeEndElement(); } private static void writeEnergyConsumers(Network network, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { for (Load load : network.getLoads()) { if (context.isExportedEquipment(load)) { - writeSshEnergyConsumer(context.getNamingStrategy().getCgmesId(load), load.getP0(), load.getQ0(), load.getExtension(LoadDetail.class), cimNamespace, writer, context); + if (load.getP0() < 0) { + // As negative loads are not allowed, they are modeled as energy source. + // Note that negative loads can be the result of network reduction and could be modeled + // as equivalent injections. + String cgmesId = context.getNamingStrategy().getCgmesId(load); + writeEnergySource(cgmesId, load.getP0(), load.getQ0(), cimNamespace, writer, context); + } else { + writeSshEnergyConsumer(context.getNamingStrategy().getCgmesId(load), load.getP0(), load.getQ0(), load.getExtension(LoadDetail.class), cimNamespace, writer, context); + } } } } + private static void writeEnergySource(String id, double p, double q, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { + CgmesExportUtil.writeStartAbout("EnergySource", id, cimNamespace, writer, context); + writer.writeStartElement(cimNamespace, "EnergySource.activePower"); + writer.writeCharacters(CgmesExportUtil.format(p)); + writer.writeEndElement(); + writer.writeStartElement(cimNamespace, "EnergySource.reactivePower"); + writer.writeCharacters(CgmesExportUtil.format(q)); + writer.writeEndElement(); + writer.writeEndElement(); + } + private static void writeSshEnergyConsumer(String id, double p, double q, LoadDetail loadDetail, String cimNamespace, XMLStreamWriter writer, CgmesExportContext context) throws XMLStreamException { CgmesExportUtil.writeStartAbout(CgmesExportUtil.loadClassName(loadDetail), id, cimNamespace, writer, context); writer.writeStartElement(cimNamespace, "EnergyConsumer.p");