From bf12fddc82f45cb11827ec6295fec5153b62cb0c Mon Sep 17 00:00:00 2001 From: rcourtier <129156292+rcourtier@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:56:27 +0100 Subject: [PATCH] CGMES export - Add a parameter to export generators in local regulation mode (#3198) * Gives an option to export generators in local regulation mode in the CGMES export * Remove duplicated code by setting the proper value for the terminal used for regulation in the CGMES Equipment export * Update the CGMES export documentation * Avoid potential rounding variations of targetV if local nominalV and remote nominalV are identical Signed-off-by: Romain Courtier --- .../powsybl/cgmes/conversion/CgmesExport.java | 9 ++++++++- .../conversion/export/CgmesExportContext.java | 11 +++++++++++ .../conversion/export/EquipmentExport.java | 12 ++++++++++-- .../export/SteadyStateHypothesisExport.java | 8 ++++++++ .../test/export/EquipmentExportTest.java | 8 ++++++++ .../SteadyStateHypothesisExportTest.java | 18 +++++++++++++----- docs/grid_exchange_formats/cgmes/export.md | 5 +++++ .../test/EurostagTutorialExample1Factory.java | 3 ++- 8 files changed, 65 insertions(+), 9 deletions(-) diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesExport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesExport.java index 311efbc54fc..e5369dbd89a 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesExport.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesExport.java @@ -423,6 +423,7 @@ private void addParametersToContext(CgmesExportContext context, Properties param .setExportTransformersWithHighestVoltageAtEnd1(Parameter.readBoolean(getFormat(), params, EXPORT_TRANSFORMERS_WITH_HIGHEST_VOLTAGE_AT_END1_PARAMETER, defaultValueConfig)) .setExportLoadFlowStatus(Parameter.readBoolean(getFormat(), params, EXPORT_LOAD_FLOW_STATUS_PARAMETER, defaultValueConfig)) .setExportAllLimitsGroup(Parameter.readBoolean(getFormat(), params, EXPORT_ALL_LIMITS_GROUP_PARAMETER, defaultValueConfig)) + .setExportGeneratorsInLocalRegulationMode(Parameter.readBoolean(getFormat(), params, EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE_PARAMETER, defaultValueConfig)) .setMaxPMismatchConverged(Parameter.readDouble(getFormat(), params, MAX_P_MISMATCH_CONVERGED_PARAMETER, defaultValueConfig)) .setMaxQMismatchConverged(Parameter.readDouble(getFormat(), params, MAX_Q_MISMATCH_CONVERGED_PARAMETER, defaultValueConfig)) .setExportSvInjectionsForSlacks(Parameter.readBoolean(getFormat(), params, EXPORT_SV_INJECTIONS_FOR_SLACKS_PARAMETER, defaultValueConfig)) @@ -544,6 +545,7 @@ public String getFormat() { public static final String EXPORT_TRANSFORMERS_WITH_HIGHEST_VOLTAGE_AT_END1 = "iidm.export.cgmes.export-transformers-with-highest-voltage-at-end1"; public static final String EXPORT_LOAD_FLOW_STATUS = "iidm.export.cgmes.export-load-flow-status"; public static final String EXPORT_ALL_LIMITS_GROUP = "iidm.export.cgmes.export-all-limits-group"; + public static final String EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE = "iidm.export.cgmes.export-generators-in-local-regulation-mode"; public static final String MAX_P_MISMATCH_CONVERGED = "iidm.export.cgmes.max-p-mismatch-converged"; public static final String MAX_Q_MISMATCH_CONVERGED = "iidm.export.cgmes.max-q-mismatch-converged"; public static final String EXPORT_SV_INJECTIONS_FOR_SLACKS = "iidm.export.cgmes.export-sv-injections-for-slacks"; @@ -637,7 +639,12 @@ public String getFormat() { EXPORT_ALL_LIMITS_GROUP, ParameterType.BOOLEAN, "True to export all OperationalLimitsGroup, False to export only the selected group", - CgmesExportContext.EXPORT_LOAD_FLOW_STATUS_DEFAULT_VALUE); + CgmesExportContext.EXPORT_ALL_LIMITS_GROUP_DEFAULT_VALUE); + private static final Parameter EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE_PARAMETER = new Parameter( + EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE, + ParameterType.BOOLEAN, + "True to export voltage regulating generators in local regulation mode, False to keep their regulation mode unchanged.", + CgmesExportContext.EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE_DEFAULT_VALUE); private static final Parameter MAX_P_MISMATCH_CONVERGED_PARAMETER = new Parameter( MAX_P_MISMATCH_CONVERGED, ParameterType.DOUBLE, diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java index a4f8f6df99f..409b0376e1f 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/export/CgmesExportContext.java @@ -74,6 +74,7 @@ public class CgmesExportContext { public static final boolean ENCODE_IDS_DEFAULT_VALUE = true; public static final boolean EXPORT_LOAD_FLOW_STATUS_DEFAULT_VALUE = true; public static final boolean EXPORT_ALL_LIMITS_GROUP_DEFAULT_VALUE = true; + public static final boolean EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE_DEFAULT_VALUE = false; // From QoCDC 3.3.1 rules IGMConvergence, KirchhoffsFirstLaw, ... that refer to SV_INJECTION_LIMIT=0.1 public static final double MAX_P_MISMATCH_CONVERGED_DEFAULT_VALUE = 0.1; public static final double MAX_Q_MISMATCH_CONVERGED_DEFAULT_VALUE = 0.1; @@ -88,6 +89,7 @@ public class CgmesExportContext { private boolean exportTransformersWithHighestVoltageAtEnd1 = EXPORT_TRANSFORMERS_WITH_HIGHEST_VOLTAGE_AT_END1_DEFAULT_VALUE; private boolean exportLoadFlowStatus = EXPORT_LOAD_FLOW_STATUS_DEFAULT_VALUE; private boolean exportAllLimitsGroup = EXPORT_ALL_LIMITS_GROUP_DEFAULT_VALUE; + private boolean exportGeneratorsInLocalRegulationMode = EXPORT_GENERATORS_IN_LOCAL_REGULATION_MODE_DEFAULT_VALUE; private double maxPMismatchConverged = MAX_P_MISMATCH_CONVERGED_DEFAULT_VALUE; private double maxQMismatchConverged = MAX_Q_MISMATCH_CONVERGED_DEFAULT_VALUE; private boolean isExportSvInjectionsForSlacks = EXPORT_SV_INJECTIONS_FOR_SLACKS_DEFAULT_VALUE; @@ -619,6 +621,15 @@ public CgmesExportContext setExportAllLimitsGroup(boolean exportAllLimitsGroup) return this; } + public boolean isExportGeneratorsInLocalRegulationMode() { + return exportGeneratorsInLocalRegulationMode; + } + + public CgmesExportContext setExportGeneratorsInLocalRegulationMode(boolean exportGeneratorsInLocalRegulationMode) { + this.exportGeneratorsInLocalRegulationMode = exportGeneratorsInLocalRegulationMode; + return this; + } + public double getMaxPMismatchConverged() { return maxPMismatchConverged; } 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 ca89b0f6326..42a1c9c348f 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 @@ -382,7 +382,15 @@ private static void writeGenerators(Network network, Map mapTe String cgmesOriginalClass = generator.getProperty(Conversion.PROPERTY_CGMES_ORIGINAL_CLASS, CgmesNames.SYNCHRONOUS_MACHINE); RemoteReactivePowerControl rrpc = generator.getExtension(RemoteReactivePowerControl.class); String mode = CgmesExportUtil.getGeneratorRegulatingControlMode(generator, rrpc); - Terminal regulatingTerminal = mode.equals(RegulatingControlEq.REGULATING_CONTROL_VOLTAGE) ? generator.getRegulatingTerminal() : rrpc.getRegulatingTerminal(); + Terminal regulatingTerminal; + if (mode.equals(RegulatingControlEq.REGULATING_CONTROL_REACTIVE_POWER)) { + regulatingTerminal = rrpc.getRegulatingTerminal(); + } else if (context.isExportGeneratorsInLocalRegulationMode()) { + regulatingTerminal = generator.getTerminal(); + } else { + regulatingTerminal = generator.getRegulatingTerminal(); + } + String regulatingControlId; switch (cgmesOriginalClass) { case CgmesNames.EQUIVALENT_INJECTION: String reactiveCapabilityCurveId = writeReactiveCapabilityCurve(generator, cimNamespace, writer, context); @@ -393,7 +401,7 @@ private static void writeGenerators(Network network, Map mapTe cimNamespace, writer, context); break; case CgmesNames.EXTERNAL_NETWORK_INJECTION: - String regulatingControlId = RegulatingControlEq.writeRegulatingControlEq(generator, exportedTerminalId(mapTerminal2Id, regulatingTerminal), regulatingControlsWritten, mode, cimNamespace, writer, context); + regulatingControlId = RegulatingControlEq.writeRegulatingControlEq(generator, exportedTerminalId(mapTerminal2Id, regulatingTerminal), regulatingControlsWritten, mode, cimNamespace, writer, context); ExternalNetworkInjectionEq.write(context.getNamingStrategy().getCgmesId(generator), generator.getNameOrId(), context.getNamingStrategy().getCgmesId(generator.getTerminal().getVoltageLevel()), obtainGeneratorGovernorScd(generator), generator.getMaxP(), obtainMaxQ(generator), generator.getMinP(), obtainMinQ(generator), 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 f0aa90ddd5e..3e994d5370d 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 @@ -389,6 +389,14 @@ private static void addRegulatingControlView(Generator g, Map