Skip to content

Commit

Permalink
Merge branch 'main' into sided_contingency_side_conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
flo-dup authored Dec 2, 2024
2 parents 30f6a17 + 358b4b4 commit 969445d
Show file tree
Hide file tree
Showing 92 changed files with 4,771 additions and 595 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,11 @@ public static CgmesModel expectedMicroGridType4BE() {
"fd227658-0e1b-4ecd-952a-c6b0307b1ea11",
"ff466d18-e4f5-439b-a50a-daec2fa41e2c",
"ff466d18-e4f5-439b-a50a-daec2fa41e2c1");
m.shuntCompensatorsPoints("46e3d51d-0a41-4e3f-8ce5-63e7bb165b73",
"7dc75c5a-74cc-434c-a125-860960b6ed35",
"89e965d7-0348-4dc1-98d4-be3bf8891fad",
"8b93ca77-3cc3-4c82-8524-2f8a13513e20",
"ca954c3a-5194-49eb-9097-10c77cea36b9");
Set<String> tlremove = new HashSet<>(Arrays.asList(
"acbd4688-6393-4b43-a9f4-27d8c3f8c309",
"1c8440dc-e65d-4337-9d3e-7558062228da1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1105,4 +1105,5 @@ public Config setCreateFictitiousVoltageLevelsForEveryNode(boolean b) {
public static final String PROPERTY_CGMES_GOVERNOR_SCD = CGMES_PREFIX_ALIAS_PROPERTIES + "governorSCD";
public static final String PROPERTY_CGMES_SYNCHRONOUS_MACHINE_TYPE = CGMES_PREFIX_ALIAS_PROPERTIES + "synchronousMachineType";
public static final String PROPERTY_CGMES_SYNCHRONOUS_MACHINE_OPERATING_MODE = CGMES_PREFIX_ALIAS_PROPERTIES + "synchronousMachineOperatingMode";
public static final String PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS = CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT_SET + "_identifiers";
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@

package com.powsybl.cgmes.conversion.elements;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.powsybl.cgmes.conversion.Context;
import com.powsybl.cgmes.conversion.Conversion;
import com.powsybl.cgmes.model.CgmesNames;
import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.triplestore.api.PropertyBag;

import java.util.Optional;
import java.util.function.Supplier;

import static com.powsybl.cgmes.conversion.Conversion.PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS;

/**
* @author Luma Zamarreño {@literal <zamarrenolm at aia.es>}
*/
Expand All @@ -28,7 +34,6 @@ public class OperationalLimitConversion extends AbstractIdentifiedObjectConversi
private static final String OPERATIONAL_LIMIT_SUBCLASS = "OperationalLimitSubclass";
private static final String OPERATIONAL_LIMIT_SET_ID = "OperationalLimitSet";
private static final String OPERATIONAL_LIMIT_SET_NAME = "OperationalLimitSetName";
private static final String PROPERTY_PREFIX = Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT_SET + "_";
private static final String PERMANENT_LIMIT = "Permanent Limit";
private static final String TEMPORARY_LIMIT = "Temporary Limit";

Expand Down Expand Up @@ -81,6 +86,30 @@ private void setVoltageLevelForVoltageLimit(Terminal terminal) {
}
}

/**
* Store the CGMES OperationalLimitSet id/name pair in a property of the identifiable.
* If the property already exists, meaning it has been created for another limit set of that identifiable,
* then append the id/name pair to the property value (which actually represents a serialized json).
* @param identifiable The Branch, DanglingLine, ThreeWindingsTransformer where the limit set id/name are stored.
* @param limitSetId The OperationalLimitSet id to store.
* @param limitSetName The OperationalLimitSet name to store.
*/
private void storeOperationalLimitSetIdentifiers(Identifiable<?> identifiable, String limitSetId, String limitSetName) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
if (identifiable.hasProperty(PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS)) {
node = mapper.readTree(identifiable.getProperty(PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS));
} else {
node = mapper.createObjectNode();
}
((ObjectNode) node).put(limitSetId, limitSetName);
identifiable.setProperty(PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS, mapper.writeValueAsString(node));
} catch (JsonProcessingException e) {
throw new PowsyblException(e.getMessage(), e);
}
}

/**
* Create the LoadingLimitsAdder for the given branch + side and the given limit set + subclass.
* @param terminalNumber The side of the branch to which the OperationalLimit applies.
Expand All @@ -92,12 +121,12 @@ private void setVoltageLevelForVoltageLimit(Terminal terminal) {
private void createLimitsAdder(int terminalNumber, String limitSubClass, String limitSetId, String limitSetName, Branch<?> b) {
if (terminalNumber == 1) {
OperationalLimitsGroup limitsGroup = b.getOperationalLimitsGroup1(limitSetId).orElseGet(() -> {
b.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName);
storeOperationalLimitSetIdentifiers(b, limitSetId, limitSetName);
return b.newOperationalLimitsGroup1(limitSetId); });
loadingLimitsAdder1 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass);
} else if (terminalNumber == 2) {
OperationalLimitsGroup limitsGroup = b.getOperationalLimitsGroup2(limitSetId).orElseGet(() -> {
b.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName);
storeOperationalLimitSetIdentifiers(b, limitSetId, limitSetName);
return b.newOperationalLimitsGroup2(limitSetId); });
loadingLimitsAdder2 = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass);
} else {
Expand All @@ -114,7 +143,7 @@ private void createLimitsAdder(int terminalNumber, String limitSubClass, String
*/
private void createLimitsAdder(String limitSubClass, String limitSetId, String limitSetName, DanglingLine dl) {
OperationalLimitsGroup limitsGroup = dl.getOperationalLimitsGroup(limitSetId).orElseGet(() -> {
dl.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName);
storeOperationalLimitSetIdentifiers(dl, limitSetId, limitSetName);
return dl.newOperationalLimitsGroup(limitSetId); });
loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass);
}
Expand All @@ -130,17 +159,17 @@ private void createLimitsAdder(String limitSubClass, String limitSetId, String l
private void createLimitsAdder(int terminalNumber, String limitSubClass, String limitSetId, String limitSetName, ThreeWindingsTransformer twt) {
if (terminalNumber == 1) {
OperationalLimitsGroup limitsGroup = twt.getLeg1().getOperationalLimitsGroup(limitSetId).orElseGet(() -> {
twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName);
storeOperationalLimitSetIdentifiers(twt, limitSetId, limitSetName);
return twt.getLeg1().newOperationalLimitsGroup(limitSetId); });
loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass);
} else if (terminalNumber == 2) {
OperationalLimitsGroup limitsGroup = twt.getLeg2().getOperationalLimitsGroup(limitSetId).orElseGet(() -> {
twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName);
storeOperationalLimitSetIdentifiers(twt, limitSetId, limitSetName);
return twt.getLeg2().newOperationalLimitsGroup(limitSetId); });
loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass);
} else if (terminalNumber == 3) {
OperationalLimitsGroup limitsGroup = twt.getLeg3().getOperationalLimitsGroup(limitSetId).orElseGet(() -> {
twt.setProperty(PROPERTY_PREFIX + limitSetId, limitSetName);
storeOperationalLimitSetIdentifiers(twt, limitSetId, limitSetName);
return twt.getLeg3().newOperationalLimitsGroup(limitSetId); });
loadingLimitsAdder = context.loadingLimitsMapping().getLoadingLimitsAdder(limitsGroup, limitSubClass);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
*/
package com.powsybl.cgmes.conversion.export;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.powsybl.cgmes.conversion.CgmesExport;
import com.powsybl.cgmes.conversion.Conversion;
import com.powsybl.cgmes.conversion.naming.NamingStrategy;
Expand Down Expand Up @@ -382,7 +385,15 @@ private static void writeGenerators(Network network, Map<Terminal, String> 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);
Expand All @@ -393,7 +404,7 @@ private static void writeGenerators(Network network, Map<Terminal, String> 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),
Expand Down Expand Up @@ -1203,10 +1214,16 @@ private static void writeLimitsGroup(Identifiable<?> identifiable, OperationalLi
// Write the OperationalLimitSet
String operationalLimitSetId;
String operationalLimitSetName;
String propertyKey = Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.OPERATIONAL_LIMIT_SET + "_" + limitsGroup.getId();
if (identifiable.hasProperty(propertyKey)) {
if (identifiable.hasProperty(Conversion.PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS)) {
operationalLimitSetId = limitsGroup.getId();
operationalLimitSetName = identifiable.getProperty(propertyKey);
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode propertyNode = mapper.readTree(identifiable.getProperty(Conversion.PROPERTY_OPERATIONAL_LIMIT_SET_IDENTIFIERS));
JsonNode limitsGroupNode = propertyNode.get(operationalLimitSetId);
operationalLimitSetName = limitsGroupNode != null ? limitsGroupNode.textValue() : operationalLimitSetId;
} catch (JsonProcessingException e) {
operationalLimitSetName = operationalLimitSetId;
}
} else {
operationalLimitSetId = context.getNamingStrategy().getCgmesId(ref(terminalId), ref(limitsGroup.getId()), OPERATIONAL_LIMIT_SET);
operationalLimitSetName = limitsGroup.getId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,14 @@ private static void addRegulatingControlView(Generator g, Map<String, List<Regul
enabled = rrpc.isEnabled();
} else {
target = g.getTargetV();
if (context.isExportGeneratorsInLocalRegulationMode()) {
double remoteNominalV = g.getRegulatingTerminal().getVoltageLevel().getNominalV();
double localNominalV = g.getTerminal().getVoltageLevel().getNominalV();
if (localNominalV != remoteNominalV) {
// This check prevents potential rounding variations of target when both voltages are equals
target = localNominalV * target / remoteNominalV;
}
}
targetValueUnitMultiplier = "k";
enabled = g.isVoltageRegulatorOn();
}
Expand Down
Loading

0 comments on commit 969445d

Please sign in to comment.